]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Merge tag 'drm/tegra/for-5.7-fixes' of git://anongit.freedesktop.org/tegra/linux...
authorDave Airlie <airlied@redhat.com>
Thu, 14 May 2020 02:29:45 +0000 (12:29 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 14 May 2020 02:29:50 +0000 (12:29 +1000)
drm/tegra: Fixes for v5.7

This contains a pair of patches which fix SMMU support on Tegra124 and
Tegra210 for host1x and the Tegra DRM driver.

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Thierry Reding <thierry.reding@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200508101355.3031268-1-thierry.reding@gmail.com
1171 files changed:
.clang-format
Documentation/admin-guide/device-mapper/dm-integrity.rst
Documentation/admin-guide/kernel-parameters.txt
Documentation/admin-guide/sysctl/kernel.rst
Documentation/arm64/amu.rst
Documentation/core-api/timekeeping.rst
Documentation/devicetree/bindings/Makefile
Documentation/devicetree/bindings/arm/sunxi/allwinner,sun4i-a10-mbus.yaml
Documentation/devicetree/bindings/clock/arm,syscon-icst.yaml
Documentation/devicetree/bindings/display/bridge/adi,adv7123.txt
Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt
Documentation/devicetree/bindings/display/panel/leadtek,ltk500hd1829.yaml
Documentation/devicetree/bindings/display/panel/lvds.yaml
Documentation/devicetree/bindings/display/panel/xinpeng,xpp055c272.yaml
Documentation/devicetree/bindings/dma/adi,axi-dmac.txt
Documentation/devicetree/bindings/dma/socionext,uniphier-xdmac.yaml
Documentation/devicetree/bindings/hwmon/adi,axi-fan-control.yaml
Documentation/devicetree/bindings/hwmon/adt7475.yaml
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml
Documentation/devicetree/bindings/iio/dac/ad5755.txt
Documentation/devicetree/bindings/iio/dac/adi,ad5770r.yaml
Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
Documentation/devicetree/bindings/interrupt-controller/loongson,liointc.yaml
Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml
Documentation/devicetree/bindings/mfd/rohm,bd71837-pmic.yaml
Documentation/devicetree/bindings/mfd/rohm,bd71847-pmic.yaml
Documentation/devicetree/bindings/mfd/st,stpmic1.yaml
Documentation/devicetree/bindings/net/ethernet-phy.yaml
Documentation/devicetree/bindings/net/fsl-fec.txt
Documentation/devicetree/bindings/net/qcom,ipq8064-mdio.yaml
Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt
Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml
Documentation/devicetree/bindings/phy/ti,phy-j721e-wiz.yaml
Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.yaml
Documentation/devicetree/bindings/regulator/mps,mp5416.yaml
Documentation/devicetree/bindings/regulator/mps,mpq7920.yaml
Documentation/devicetree/bindings/regulator/rohm,bd71828-regulator.yaml
Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.yaml
Documentation/devicetree/bindings/regulator/rohm,bd71847-regulator.yaml
Documentation/devicetree/bindings/rng/brcm,bcm2835.yaml
Documentation/devicetree/bindings/sound/rockchip-i2s.yaml
Documentation/devicetree/bindings/sound/rockchip-spdif.txt [deleted file]
Documentation/devicetree/bindings/sound/rockchip-spdif.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/spi/qcom,spi-qcom-qspi.yaml
Documentation/devicetree/bindings/usb/ingenic,musb.yaml
Documentation/devicetree/bindings/usb/qcom,dwc3.txt
Documentation/devicetree/bindings/usb/renesas,usb3-peri.yaml
Documentation/devicetree/bindings/usb/renesas,usbhs.yaml
Documentation/devicetree/bindings/usb/rockchip,dwc3.txt
Documentation/devicetree/bindings/usb/usb-xhci.txt
Documentation/filesystems/debugfs.rst
Documentation/hwmon/isl68137.rst
Documentation/kbuild/makefiles.rst
Documentation/networking/devlink/devlink-trap.rst
Documentation/networking/devlink/ice.rst
Documentation/networking/index.rst
Documentation/networking/ip-sysctl.txt
Documentation/networking/net_dim.rst [moved from Documentation/networking/net_dim.txt with 78% similarity]
Documentation/virt/kvm/index.rst
Documentation/virt/kvm/running-nested-guests.rst [new file with mode: 0644]
Documentation/x86/boot.rst
MAINTAINERS
Makefile
arch/arc/include/asm/module.h
arch/arc/include/asm/vermagic.h [new file with mode: 0644]
arch/arm/boot/compressed/head.S
arch/arm/boot/dts/bcm2835-rpi.dtsi
arch/arm/boot/dts/bcm283x.dtsi
arch/arm/boot/dts/imx6qdl.dtsi
arch/arm/boot/dts/imx6qp.dtsi
arch/arm/boot/dts/omap3-n950-n9.dtsi
arch/arm/crypto/chacha-glue.c
arch/arm/crypto/nhpoly1305-neon-glue.c
arch/arm/crypto/poly1305-glue.c
arch/arm/include/asm/futex.h
arch/arm/include/asm/module.h
arch/arm/include/asm/vermagic.h [new file with mode: 0644]
arch/arm/mach-imx/Makefile
arch/arm/net/bpf_jit_32.c
arch/arm/xen/enlighten.c
arch/arm64/crypto/chacha-neon-glue.c
arch/arm64/crypto/nhpoly1305-neon-glue.c
arch/arm64/crypto/poly1305-glue.c
arch/arm64/include/asm/module.h
arch/arm64/include/asm/pointer_auth.h
arch/arm64/include/asm/sysreg.h
arch/arm64/include/asm/vermagic.h [new file with mode: 0644]
arch/arm64/kernel/vdso.c
arch/arm64/kernel/vdso/Makefile
arch/arm64/kvm/guest.c
arch/arm64/kvm/hyp/entry.S
arch/arm64/kvm/hyp/hyp-entry.S
arch/arm64/kvm/hyp/sysreg-sr.c
arch/arm64/mm/hugetlbpage.c
arch/h8300/kernel/.gitignore [new file with mode: 0644]
arch/hexagon/include/asm/vermagic.h [moved from arch/hexagon/include/asm/module.h with 64% similarity]
arch/ia64/include/asm/module.h
arch/ia64/include/asm/vermagic.h [new file with mode: 0644]
arch/m68k/include/asm/Kbuild
arch/mips/include/asm/module.h
arch/mips/include/asm/vermagic.h [new file with mode: 0644]
arch/nds32/include/asm/vermagic.h [moved from arch/nds32/include/asm/module.h with 52% similarity]
arch/powerpc/include/asm/module.h
arch/powerpc/include/asm/vermagic.h [new file with mode: 0644]
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/setup_64.c
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/book3s_64_mmu_radix.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/mm/nohash/8xx.c
arch/powerpc/platforms/Kconfig.cputype
arch/riscv/Kconfig
arch/riscv/include/asm/csr.h
arch/riscv/include/asm/hwcap.h
arch/riscv/include/asm/module.h
arch/riscv/include/asm/set_memory.h
arch/riscv/include/asm/vermagic.h [new file with mode: 0644]
arch/riscv/kernel/cpu_ops.c
arch/riscv/kernel/cpufeature.c
arch/riscv/kernel/sbi.c
arch/riscv/kernel/smp.c
arch/riscv/kernel/stacktrace.c
arch/riscv/kernel/vdso/Makefile
arch/riscv/kernel/vdso/note.S [new file with mode: 0644]
arch/riscv/mm/init.c
arch/riscv/net/bpf_jit_comp64.c
arch/s390/boot/uv.c
arch/s390/kernel/diag.c
arch/s390/kernel/smp.c
arch/s390/kernel/trace.c
arch/s390/kernel/uv.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/priv.c
arch/s390/lib/uaccess.c
arch/s390/mm/pgalloc.c
arch/s390/pci/pci_irq.c
arch/sh/include/asm/module.h
arch/sh/include/asm/vermagic.h [new file with mode: 0644]
arch/sh/mm/init.c
arch/um/Makefile
arch/x86/Kconfig
arch/x86/crypto/blake2s-glue.c
arch/x86/crypto/chacha_glue.c
arch/x86/crypto/nhpoly1305-avx2-glue.c
arch/x86/crypto/nhpoly1305-sse2-glue.c
arch/x86/crypto/poly1305_glue.c
arch/x86/entry/calling.h
arch/x86/entry/entry_64.S
arch/x86/events/intel/cstate.c
arch/x86/hyperv/hv_init.c
arch/x86/include/asm/efi.h
arch/x86/include/asm/ftrace.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/microcode_amd.h
arch/x86/include/asm/module.h
arch/x86/include/asm/mshyperv.h
arch/x86/include/asm/nospec-branch.h
arch/x86/include/asm/unwind.h
arch/x86/include/asm/vermagic.h [new file with mode: 0644]
arch/x86/kernel/apic/apic.c
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/mshyperv.c
arch/x86/kernel/cpu/resctrl/core.c
arch/x86/kernel/cpu/resctrl/internal.h
arch/x86/kernel/cpu/resctrl/rdtgroup.c
arch/x86/kernel/dumpstack_64.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/umip.c
arch/x86/kernel/unwind_frame.c
arch/x86/kernel/unwind_orc.c
arch/x86/kvm/Makefile
arch/x86/kvm/ioapic.c
arch/x86/kvm/svm/sev.c
arch/x86/kvm/svm/svm.c
arch/x86/kvm/svm/vmenter.S
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/vmenter.S
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/pat/set_memory.c
arch/x86/net/bpf_jit_comp.c
arch/x86/net/bpf_jit_comp32.c
arch/x86/platform/efi/efi_64.c
arch/xtensa/include/asm/vermagic.h [moved from arch/xtensa/include/asm/module.h with 57% similarity]
block/bfq-iosched.c
block/blk-cgroup.c
block/blk-iocost.c
block/blk-mq.c
block/blk-wbt.c
block/partitions/core.c
crypto/lrw.c
crypto/xts.c
drivers/acpi/button.c
drivers/acpi/device_pm.c
drivers/acpi/pci_link.c
drivers/amba/bus.c
drivers/ata/ahci.c
drivers/ata/sata_inic162x.c
drivers/base/component.c
drivers/base/core.c
drivers/base/dd.c
drivers/base/firmware_loader/fallback_table.c
drivers/base/platform.c
drivers/base/power/main.c
drivers/block/null_blk.h
drivers/block/null_blk_main.c
drivers/block/null_blk_zoned.c
drivers/block/rbd.c
drivers/block/virtio_blk.c
drivers/bus/mhi/core/init.c
drivers/bus/mhi/core/internal.h
drivers/bus/mhi/core/main.c
drivers/bus/mhi/core/pm.c
drivers/char/hw_random/virtio-rng.c
drivers/char/tpm/tpm-interface.c
drivers/char/tpm/tpm2-cmd.c
drivers/char/tpm/tpm_ibmvtpm.c
drivers/char/tpm/tpm_tis_core.c
drivers/clk/clk-asm9260.c
drivers/clk/mmp/clk-pll.c
drivers/clk/mmp/clk.c
drivers/clk/mmp/clk.h
drivers/clk/sprd/sc9863a-clk.c
drivers/counter/104-quad-8.c
drivers/cpufreq/intel_pstate.c
drivers/crypto/caam/caamalg.c
drivers/crypto/caam/caamhash.c
drivers/crypto/caam/caampkc.c
drivers/crypto/chelsio/chcr_ktls.c
drivers/dma-buf/dma-buf.c
drivers/dma/Kconfig
drivers/dma/dmaengine.c
drivers/dma/dmatest.c
drivers/dma/mmp_tdma.c
drivers/dma/pch_dma.c
drivers/dma/tegra20-apb-dma.c
drivers/dma/ti/k3-psil.c
drivers/dma/xilinx/xilinx_dma.c
drivers/firmware/efi/cper.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/file.c
drivers/firmware/efi/libstub/x86-stub.c
drivers/firmware/efi/tpm.c
drivers/firmware/imx/Kconfig
drivers/firmware/xilinx/zynqmp-debug.c
drivers/fpga/dfl-pci.c
drivers/fpga/zynq-fpga.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/cik.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/navi10_sdma_pkt_open.h
drivers/gpu/drm/amd/amdgpu/nv.c
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdgpu/vi.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/amdgpu_dm/amdgpu_dm_mst_types.h
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
drivers/gpu/drm/amd/display/dc/os_types.h
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/renoir_ppt.c
drivers/gpu/drm/amd/powerplay/smu_v11_0.c
drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_hdcp.c
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_display_power.c
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
drivers/gpu/drm/i915/display/intel_fbc.c
drivers/gpu/drm/i915/display/intel_hdmi.c
drivers/gpu/drm/i915/display/intel_sprite.c
drivers/gpu/drm/i915/gem/i915_gem_domain.c
drivers/gpu/drm/i915/gem/i915_gem_tiling.c
drivers/gpu/drm/i915/gem/selftests/huge_pages.c
drivers/gpu/drm/i915/gt/intel_context_types.h
drivers/gpu/drm/i915/gt/intel_engine.h
drivers/gpu/drm/i915/gt/intel_engine_cs.c
drivers/gpu/drm/i915/gt/intel_engine_types.h
drivers/gpu/drm/i915/gt/intel_gt_irq.c
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gt/intel_rps.c
drivers/gpu/drm/i915/gt/intel_timeline.c
drivers/gpu/drm/i915/gt/selftest_lrc.c
drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_vma.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/selftests/i915_vma.c
drivers/gpu/drm/ingenic/ingenic-drm.c
drivers/gpu/drm/meson/meson_dw_hdmi.c
drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp108.c
drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c
drivers/gpu/drm/qxl/qxl_cmd.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_draw.c
drivers/gpu/drm/qxl/qxl_image.c
drivers/gpu/drm/qxl/qxl_ioctl.c
drivers/gpu/drm/scheduler/sched_main.c
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
drivers/gpu/drm/tidss/tidss_crtc.c
drivers/gpu/drm/tidss/tidss_encoder.c
drivers/gpu/drm/tidss/tidss_plane.c
drivers/gpu/drm/virtio/virtgpu_drv.h
drivers/gpu/drm/virtio/virtgpu_gem.c
drivers/gpu/drm/virtio/virtgpu_ioctl.c
drivers/gpu/drm/virtio/virtgpu_kms.c
drivers/hid/Kconfig
drivers/hid/hid-alps.c
drivers/hid/hid-ids.h
drivers/hid/hid-lg-g15.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-quirks.c
drivers/hid/i2c-hid/i2c-hid-core.c
drivers/hid/usbhid/hid-core.c
drivers/hid/usbhid/usbhid.h
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c
drivers/hv/channel_mgmt.c
drivers/hv/hv.c
drivers/hv/hv_debugfs.c
drivers/hv/hv_trace.h
drivers/hv/hyperv_vmbus.h
drivers/hv/vmbus_drv.c
drivers/hwmon/Kconfig
drivers/hwmon/drivetemp.c
drivers/hwmon/jc42.c
drivers/hwmon/k10temp.c
drivers/hwmon/pmbus/isl68137.c
drivers/i2c/busses/i2c-altera.c
drivers/i2c/busses/i2c-amd-mp2-pci.c
drivers/i2c/busses/i2c-aspeed.c
drivers/i2c/busses/i2c-bcm-iproc.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/i2c-core-base.c
drivers/iio/adc/ad7192.c
drivers/iio/adc/ad7793.c
drivers/iio/adc/stm32-adc.c
drivers/iio/adc/ti-ads8344.c
drivers/iio/adc/xilinx-xadc-core.c
drivers/iio/common/st_sensors/st_sensors_core.c
drivers/iio/dac/ad5770r.c
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
drivers/iio/industrialio-core.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/rdma_core.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/i40iw/i40iw_ctrl.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/sw/rdmavt/cq.c
drivers/infiniband/sw/rdmavt/mmap.c
drivers/infiniband/sw/rdmavt/qp.c
drivers/infiniband/sw/rdmavt/srq.c
drivers/infiniband/sw/siw/siw_qp_tx.c
drivers/interconnect/qcom/bcm-voter.c
drivers/interconnect/qcom/osm-l3.c
drivers/interconnect/qcom/sdm845.c
drivers/iommu/Kconfig
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/amd_iommu_types.h
drivers/iommu/intel-iommu.c
drivers/iommu/iommu.c
drivers/iommu/qcom_iommu.c
drivers/iommu/virtio-iommu.c
drivers/irqchip/irq-bcm7038-l1.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-mbigen.c
drivers/irqchip/irq-meson-gpio.c
drivers/irqchip/irq-mvebu-icu.c
drivers/irqchip/irq-sifive-plic.c
drivers/irqchip/irq-ti-sci-inta.c
drivers/isdn/hardware/mISDN/mISDNisar.c
drivers/md/dm-mpath.c
drivers/md/dm-verity-fec.c
drivers/md/dm-writecache.c
drivers/misc/mei/hw-me.c
drivers/misc/mei/hw-me.h
drivers/misc/mei/pci-me.c
drivers/misc/mic/Kconfig
drivers/mmc/core/mmc_ops.c
drivers/mmc/host/cqhci.c
drivers/mmc/host/meson-mx-sdio.c
drivers/mmc/host/sdhci-msm.c
drivers/mmc/host/sdhci-pci-core.c
drivers/mmc/host/sdhci-xenon.c
drivers/most/core.c
drivers/mtd/spi-nor/Makefile
drivers/net/caif/Kconfig
drivers/net/dsa/b53/b53_common.c
drivers/net/dsa/b53/b53_regs.h
drivers/net/dsa/mt7530.c
drivers/net/dsa/mt7530.h
drivers/net/dsa/mv88e6xxx/Kconfig
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/ocelot/felix.c
drivers/net/dsa/ocelot/felix.h
drivers/net/dsa/ocelot/felix_vsc9959.c
drivers/net/dsa/sja1105/Kconfig
drivers/net/dsa/sja1105/sja1105_ptp.c
drivers/net/ethernet/amazon/ena/ena_netdev.h
drivers/net/ethernet/amd/xgbe/xgbe-drv.c
drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bgmac-platform.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/cadence/Kconfig
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/cavium/Kconfig
drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
drivers/net/ethernet/dec/tulip/tulip_core.c
drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mediatek/mtk_eth_soc.h
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx5/core/Kconfig
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/devlink.c
drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.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/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/health.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c
drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_mr_tcam.c
drivers/net/ethernet/moxa/moxart_ether.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot.h
drivers/net/ethernet/mscc/ocelot_regs.c
drivers/net/ethernet/natsemi/jazzsonic.c
drivers/net/ethernet/neterion/s2io.c
drivers/net/ethernet/netronome/nfp/abm/main.c
drivers/net/ethernet/pensando/ionic/ionic_debugfs.c
drivers/net/ethernet/pensando/ionic/ionic_lif.c
drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c
drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h
drivers/net/ethernet/sgi/meth.h
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.h [new file with mode: 0644]
drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
drivers/net/ethernet/stmicro/stmmac/dwmac5.c
drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/ti/Kconfig
drivers/net/ethernet/ti/am65-cpsw-nuss.c
drivers/net/ethernet/toshiba/tc35815.c
drivers/net/ethernet/xscale/ixp4xx_eth.c
drivers/net/geneve.c
drivers/net/gtp.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/ipa/gsi.c
drivers/net/ipa/gsi_reg.h
drivers/net/ipa/ipa_endpoint.c
drivers/net/ipa/ipa_modem.c
drivers/net/macsec.c
drivers/net/macvlan.c
drivers/net/phy/bcm84881.c
drivers/net/phy/dp83640.c
drivers/net/phy/dp83822.c
drivers/net/phy/dp83tc811.c
drivers/net/phy/marvell.c
drivers/net/phy/marvell10g.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/micrel.c
drivers/net/phy/microchip_t1.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/qmi_wwan.c
drivers/net/vrf.c
drivers/net/vxlan.c
drivers/net/wimax/i2400m/usb-fw.c
drivers/net/wireguard/queueing.c
drivers/net/wireguard/receive.c
drivers/net/wireguard/selftest/ratelimiter.c
drivers/net/wireguard/send.c
drivers/net/wireguard/socket.c
drivers/net/wireless/ath/ath11k/thermal.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
drivers/net/wireless/intel/iwlegacy/3945-rs.c
drivers/net/wireless/intel/iwlegacy/4965-rs.c
drivers/net/wireless/intel/iwlwifi/dvm/rs.c
drivers/net/wireless/intel/iwlwifi/fw/acpi.c
drivers/net/wireless/intel/iwlwifi/fw/api/txq.h
drivers/net/wireless/intel/iwlwifi/iwl-drv.c
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/mvm/rs.c
drivers/net/wireless/intel/iwlwifi/mvm/rx.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/realtek/rtlwifi/rc.c
drivers/net/wireless/realtek/rtw88/pci.c
drivers/nvme/host/core.c
drivers/nvme/host/pci.c
drivers/of/overlay.c
drivers/of/unittest-data/overlay_bad_add_dup_prop.dts
drivers/of/unittest.c
drivers/opp/core.c
drivers/pci/quirks.c
drivers/phy/qualcomm/phy-qcom-qusb2.c
drivers/phy/qualcomm/phy-qcom-usb-hs-28nm.c
drivers/phy/tegra/Kconfig
drivers/platform/chrome/cros_ec_sensorhub.c
drivers/platform/chrome/cros_ec_sensorhub_ring.c
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/intel-uncore-frequency.c
drivers/platform/x86/intel_pmc_core.c
drivers/platform/x86/intel_pmc_core.h
drivers/platform/x86/surface3_power.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/xiaomi-wmi.c
drivers/ptp/ptp_ines.c
drivers/regulator/core.c
drivers/remoteproc/mtk_common.h
drivers/remoteproc/mtk_scp.c
drivers/remoteproc/qcom_q6v5_mss.c
drivers/remoteproc/remoteproc_sysfs.c
drivers/remoteproc/stm32_rproc.c
drivers/rpmsg/mtk_rpmsg.c
drivers/s390/block/Kconfig
drivers/s390/net/qeth_core_main.c
drivers/scsi/Kconfig
drivers/scsi/hisi_sas/Kconfig
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/scsi_lib.c
drivers/scsi/sg.c
drivers/soc/fsl/dpio/dpio-service.c
drivers/soc/fsl/dpio/qbman-portal.c
drivers/soc/imx/Kconfig
drivers/soc/xilinx/Kconfig
drivers/staging/comedi/comedi_fops.c
drivers/staging/comedi/drivers/dt2815.c
drivers/staging/gasket/apex_driver.c
drivers/staging/gasket/gasket_core.c
drivers/staging/gasket/gasket_sysfs.c
drivers/staging/gasket/gasket_sysfs.h
drivers/staging/ks7010/TODO
drivers/staging/vt6656/key.c
drivers/staging/vt6656/main_usb.c
drivers/staging/vt6656/usbpipe.c
drivers/target/target_core_fabric_lib.c
drivers/target/target_core_iblock.c
drivers/target/target_core_user.c
drivers/thunderbolt/usb4.c
drivers/tty/hvc/Kconfig
drivers/tty/hvc/hvc_console.c
drivers/tty/rocket.c
drivers/tty/serial/Kconfig
drivers/tty/serial/owl-uart.c
drivers/tty/serial/sh-sci.c
drivers/tty/serial/sunhv.c
drivers/tty/serial/xilinx_uartps.c
drivers/tty/sysrq.c
drivers/tty/vt/vt.c
drivers/usb/chipidea/ci_hdrc_msm.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.h
drivers/usb/core/devio.c
drivers/usb/core/hub.c
drivers/usb/core/message.c
drivers/usb/core/quirks.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/gadget.c
drivers/usb/early/xhci-dbc.c
drivers/usb/early/xhci-dbc.h
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/legacy/raw_gadget.c
drivers/usb/gadget/udc/atmel_usba_udc.c
drivers/usb/gadget/udc/bdc/bdc_ep.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/misc/sisusbvga/sisusb_init.h
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/qcserial.c
drivers/usb/storage/uas.c
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/unusual_uas.h
drivers/usb/typec/bus.c
drivers/usb/typec/mux/intel_pmc_mux.c
drivers/usb/typec/mux/pi3usb30532.c
drivers/usb/typec/tcpm/tcpm.c
drivers/vdpa/Kconfig
drivers/vdpa/ifcvf/ifcvf_base.c
drivers/vdpa/ifcvf/ifcvf_main.c
drivers/vdpa/vdpa.c
drivers/vdpa/vdpa_sim/vdpa_sim.c
drivers/vfio/vfio_iommu_type1.c
drivers/vhost/Kconfig
drivers/vhost/net.c
drivers/vhost/scsi.c
drivers/vhost/test.c
drivers/vhost/vdpa.c
drivers/vhost/vhost.h
drivers/vhost/vringh.c
drivers/vhost/vsock.c
drivers/virtio/Kconfig
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_input.c
drivers/watchdog/sp805_wdt.c
drivers/xen/xenbus/xenbus_client.c
fs/afs/cmservice.c
fs/afs/dir.c
fs/afs/dir_silly.c
fs/afs/fs_probe.c
fs/afs/fsclient.c
fs/afs/internal.h
fs/afs/rotate.c
fs/afs/server.c
fs/afs/vl_rotate.c
fs/afs/volume.c
fs/afs/yfsclient.c
fs/block_dev.c
fs/btrfs/backref.c
fs/btrfs/block-group.c
fs/btrfs/discard.h
fs/btrfs/disk-io.c
fs/btrfs/file.c
fs/btrfs/reflink.c
fs/btrfs/relocation.c
fs/btrfs/space-info.c
fs/btrfs/transaction.c
fs/btrfs/tree-log.c
fs/buffer.c
fs/ceph/caps.c
fs/ceph/debugfs.c
fs/ceph/dir.c
fs/ceph/file.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/quota.c
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/inode.c
fs/cifs/misc.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2transport.c
fs/configfs/dir.c
fs/coredump.c
fs/debugfs/file.c
fs/eventpoll.c
fs/exfat/balloc.c
fs/exfat/exfat_fs.h
fs/exfat/file.c
fs/exfat/misc.c
fs/exfat/namei.c
fs/exfat/super.c
fs/ext4/balloc.c
fs/ext4/ext4_jbd2.c
fs/ext4/extents.c
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/super.c
fs/io_uring.c
fs/ioctl.c
fs/iomap/fiemap.c
fs/nfs/nfs3acl.c
fs/nfs/nfs4proc.c
fs/nfs/pnfs.c
fs/nfs/super.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4state.c
fs/ocfs2/dlmfs/dlmfs.c
fs/pnode.c
fs/proc/base.c
fs/proc/root.c
fs/proc/vmcore.c
fs/splice.c
fs/super.c
fs/vboxsf/super.c
fs/xfs/xfs_icache.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_reflink.c
fs/xfs/xfs_super.c
include/asm-generic/Kbuild
include/asm-generic/mshyperv.h
include/asm-generic/vermagic.h [new file with mode: 0644]
include/linux/amba/bus.h
include/linux/backing-dev-defs.h
include/linux/backing-dev.h
include/linux/bio.h
include/linux/blk-mq.h
include/linux/blk_types.h
include/linux/buffer_head.h
include/linux/can/dev/peak_canfd.h
include/linux/cpu_rmap.h
include/linux/debugfs.h
include/linux/digsig.h
include/linux/dirent.h
include/linux/dma-buf.h
include/linux/dmaengine.h
include/linux/enclosure.h
include/linux/energy_model.h
include/linux/ethtool.h
include/linux/fs.h
include/linux/genalloc.h
include/linux/i2c.h
include/linux/igmp.h
include/linux/ihex.h
include/linux/iio/iio.h
include/linux/irq.h
include/linux/irqchip/arm-gic-v3.h
include/linux/kvm_host.h
include/linux/list_lru.h
include/linux/lsm_hook_defs.h
include/linux/memcontrol.h
include/linux/mhi.h
include/linux/nfs_xdr.h
include/linux/platform_data/cros_ec_sensorhub.h
include/linux/platform_data/wilco-ec.h
include/linux/platform_device.h
include/linux/pnp.h
include/linux/posix_acl.h
include/linux/rio.h
include/linux/rslib.h
include/linux/sched/topology.h
include/linux/skbuff.h
include/linux/stmmac.h
include/linux/sunrpc/clnt.h
include/linux/sunrpc/svc_rdma.h
include/linux/swap.h
include/linux/tcp.h
include/linux/ti_wilink_st.h
include/linux/tpm_eventlog.h
include/linux/tracepoint.h
include/linux/tty.h
include/linux/vdpa.h
include/linux/vermagic.h
include/linux/virtio.h
include/linux/virtio_net.h
include/linux/virtio_vsock.h
include/linux/vmalloc.h
include/linux/vringh.h
include/linux/xattr.h
include/net/cfg80211.h
include/net/flow_offload.h
include/net/inet_ecn.h
include/net/ip6_fib.h
include/net/ip6_route.h
include/net/mac80211.h
include/net/mptcp.h
include/net/ndisc.h
include/net/net_namespace.h
include/net/netfilter/nf_tables.h
include/net/sch_generic.h
include/net/sock.h
include/net/tcp.h
include/soc/mscc/ocelot.h
include/soc/tegra/pmc.h
include/sound/hda_codec.h
include/sound/soc-dai.h
include/sound/soc.h
include/trace/events/gpu_mem.h
include/trace/events/iocost.h
include/trace/events/rpcrdma.h
include/trace/events/wbt.h
include/trace/events/writeback.h
include/uapi/drm/amdgpu_drm.h
include/uapi/linux/bpf.h
include/uapi/linux/btrfs.h
include/uapi/linux/dma-buf.h
include/uapi/linux/hyperv.h
include/uapi/linux/if_arcnet.h
include/uapi/linux/mmc/ioctl.h
include/uapi/linux/net_dropmon.h
include/uapi/linux/netfilter/nf_tables.h
include/uapi/linux/netfilter/xt_IDLETIMER.h
include/uapi/linux/netfilter_bridge/ebt_among.h
include/uapi/linux/virtio_balloon.h
include/uapi/scsi/scsi_bsg_fc.h
include/vdso/datapage.h
init/Kconfig
init/initramfs.c
init/main.c
ipc/mqueue.c
kernel/audit.c
kernel/bpf/bpf_lru_list.h
kernel/bpf/cpumap.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/events/core.c
kernel/exit.c
kernel/fork.c
kernel/irq/manage.c
kernel/kcov.c
kernel/power/hibernate.c
kernel/rcu/tree.c
kernel/sched/core.c
kernel/sched/cputime.c
kernel/sched/isolation.c
kernel/signal.c
kernel/time/namespace.c
kernel/trace/Kconfig
kernel/trace/ftrace.c
kernel/trace/preemptirq_delay_test.c
kernel/trace/trace.c
kernel/trace/trace_boot.c
kernel/trace/trace_events_hist.c
kernel/trace/trace_events_trigger.c
kernel/trace/trace_kprobe.c
kernel/trace/tracing_map.c
kernel/umh.c
lib/Kconfig.debug
lib/Kconfig.ubsan
lib/kunit/test.c
lib/mpi/longlong.h
mm/backing-dev.c
mm/gup.c
mm/hugetlb.c
mm/ksm.c
mm/madvise.c
mm/memcontrol.c
mm/mremap.c
mm/page_alloc.c
mm/percpu.c
mm/shmem.c
mm/slub.c
mm/vmalloc.c
mm/vmscan.c
net/atm/common.c
net/atm/lec.c
net/batman-adv/bat_v_ogm.c
net/batman-adv/network-coding.c
net/batman-adv/sysfs.c
net/bridge/br_netlink.c
net/core/dev.c
net/core/devlink.c
net/core/drop_monitor.c
net/core/filter.c
net/core/neighbour.c
net/core/net-sysfs.c
net/core/netclassid_cgroup.c
net/core/sock.c
net/dsa/dsa2.c
net/dsa/master.c
net/dsa/port.c
net/dsa/slave.c
net/hsr/hsr_netlink.c
net/hsr/hsr_slave.c
net/ipv4/devinet.c
net/ipv4/fib_semantics.c
net/ipv4/tcp_input.c
net/ipv4/xfrm4_output.c
net/ipv6/icmp.c
net/ipv6/ipv6_sockglue.c
net/ipv6/route.c
net/ipv6/rpl.c
net/ipv6/seg6.c
net/ipv6/xfrm6_output.c
net/l2tp/l2tp_netlink.c
net/mac80211/main.c
net/mac80211/mesh.c
net/mac80211/rate.c
net/mac80211/rate.h
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/sta_info.c
net/mptcp/options.c
net/mptcp/pm_netlink.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_nat_proto.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_osf.c
net/netfilter/nft_lookup.c
net/netfilter/nft_set_bitmap.c
net/netfilter/nft_set_rbtree.c
net/netfilter/xt_IDLETIMER.c
net/netlabel/Kconfig
net/netrom/nr_route.c
net/openvswitch/conntrack.c
net/openvswitch/datapath.c
net/qrtr/qrtr.c
net/rds/message.c
net/rds/rdma.c
net/rds/rds.h
net/rds/send.c
net/rxrpc/local_object.c
net/rxrpc/output.c
net/sched/cls_api.c
net/sched/sch_choke.c
net/sched/sch_etf.c
net/sched/sch_fq_codel.c
net/sched/sch_sfq.c
net/sched/sch_skbprio.c
net/sctp/sm_make_chunk.c
net/sctp/sm_statefuns.c
net/sunrpc/cache.c
net/sunrpc/clnt.c
net/sunrpc/svc_xprt.c
net/sunrpc/svcsock.c
net/sunrpc/xprtrdma/rpc_rdma.c
net/sunrpc/xprtrdma/svc_rdma_backchannel.c
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
net/sunrpc/xprtrdma/svc_rdma_rw.c
net/sunrpc/xprtrdma/svc_rdma_sendto.c
net/sunrpc/xprtrdma/svc_rdma_transport.c
net/sunrpc/xprtrdma/verbs.c
net/sunrpc/xprtsock.c
net/tipc/crypto.c
net/tipc/link.c
net/tipc/node.c
net/tipc/topsrv.c
net/tls/tls_main.c
net/tls/tls_sw.c
net/vmw_vsock/virtio_transport_common.c
net/wireless/nl80211.c
net/x25/x25_dev.c
net/x25/x25_subr.c
net/xdp/xdp_umem.c
net/xdp/xsk.c
samples/trace_events/trace-events-sample.h
samples/vfio-mdev/mdpy.c
scripts/Makefile.lib
scripts/checkpatch.pl
scripts/config
scripts/decodecode
scripts/documentation-file-ref-check
scripts/dtc/Makefile
scripts/gcc-plugins/Makefile
scripts/gcc-plugins/gcc-common.h
scripts/gcc-plugins/stackleak_plugin.c
scripts/gdb/linux/rbtree.py
scripts/kallsyms.c
scripts/kernel-doc
security/keys/proc.c
security/selinux/hooks.c
security/selinux/ss/conditional.c
security/selinux/ss/policydb.c
sound/core/oss/pcm_plugin.c
sound/hda/Kconfig
sound/isa/opti9xx/miro.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/pci/ctxfi/cthw20k1.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_intel.h
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/amd/acp3x-rt5682-max9836.c
sound/soc/codecs/Kconfig
sound/soc/codecs/hdac_hdmi.c
sound/soc/codecs/madera.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/sgtl5000.h
sound/soc/codecs/tas571x.c
sound/soc/codecs/wm8960.c
sound/soc/codecs/wsa881x.c
sound/soc/intel/common/soc-acpi-intel-cml-match.c
sound/soc/intel/common/soc-acpi-intel-icl-match.c
sound/soc/meson/axg-card.c
sound/soc/meson/gx-card.c
sound/soc/qcom/apq8096.c
sound/soc/qcom/qdsp6/q6afe-dai.c
sound/soc/qcom/sdm845.c
sound/soc/samsung/s3c-i2s-v2.c
sound/soc/samsung/s3c2412-i2s.c
sound/soc/sh/rcar/ssi.c
sound/soc/sh/rcar/ssiu.c
sound/soc/soc-dai.c
sound/soc/soc-dapm.c
sound/soc/soc-pcm.c
sound/soc/soc-topology.c
sound/soc/sof/intel/bdw.c
sound/soc/sof/intel/byt.c
sound/soc/stm/stm32_sai_sub.c
sound/usb/format.c
sound/usb/line6/podhd.c
sound/usb/mixer.c
sound/usb/mixer.h
sound/usb/mixer_maps.c
sound/usb/mixer_quirks.c
sound/usb/quirks-table.h
sound/usb/quirks.c
sound/usb/usx2y/usbusx2yaudio.c
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/asm/msr-index.h
tools/bootconfig/main.c
tools/bpf/bpftool/struct_ops.c
tools/bpf/runqslower/Makefile
tools/build/feature/test-sync-compare-and-swap.c
tools/cgroup/iocost_monitor.py
tools/include/linux/bits.h
tools/include/linux/build_bug.h [new file with mode: 0644]
tools/include/linux/compiler.h
tools/include/linux/const.h
tools/include/linux/kernel.h
tools/include/uapi/drm/drm.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/bpf.h
tools/include/uapi/linux/fscrypt.h
tools/include/uapi/linux/kvm.h
tools/include/uapi/linux/mman.h
tools/include/uapi/linux/sched.h
tools/include/uapi/linux/vhost.h
tools/include/vdso/bits.h [new file with mode: 0644]
tools/include/vdso/const.h [new file with mode: 0644]
tools/lib/bpf/libbpf.c
tools/lib/bpf/libbpf.h
tools/lib/bpf/netlink.c
tools/objtool/check.c
tools/objtool/elf.c
tools/objtool/elf.h
tools/objtool/orc_dump.c
tools/objtool/orc_gen.c
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
tools/perf/check-headers.sh
tools/perf/trace/beauty/clone.c
tools/perf/trace/beauty/mmap.c
tools/perf/util/setup.py
tools/perf/util/stat-shadow.c
tools/power/pm-graph/Makefile
tools/power/pm-graph/README
tools/power/pm-graph/bootgraph.py
tools/power/pm-graph/sleepgraph.8
tools/power/pm-graph/sleepgraph.py
tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
tools/testing/selftests/bpf/prog_tests/mmap.c
tools/testing/selftests/bpf/prog_tests/section_names.c
tools/testing/selftests/bpf/prog_tests/test_lsm.c
tools/testing/selftests/bpf/prog_tests/xdp_attach.c
tools/testing/selftests/bpf/prog_tests/xdp_info.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/connect4_prog.c
tools/testing/selftests/bpf/progs/freplace_connect4.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/lsm.c
tools/testing/selftests/bpf/progs/test_btf_haskv.c
tools/testing/selftests/bpf/progs/test_btf_newkv.c
tools/testing/selftests/bpf/progs/test_btf_nokv.c
tools/testing/selftests/bpf/test_btf.c
tools/testing/selftests/bpf/verifier/bounds.c
tools/testing/selftests/bpf/verifier/stack_ptr.c
tools/testing/selftests/bpf/verifier/value_illegal_alu.c
tools/testing/selftests/filesystems/epoll/epoll_wakeup_test.c
tools/testing/selftests/ftrace/config
tools/testing/selftests/ftrace/ftracetest
tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc
tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-notrace-pid.tc
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-pid.tc
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-stacktrace.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_mod_trace.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_set_ftrace_file.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_stack_tracer.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc
tools/testing/selftests/ftrace/test.d/functions
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc
tools/testing/selftests/gpio/Makefile
tools/testing/selftests/intel_pstate/Makefile
tools/testing/selftests/ipc/msgque.c
tools/testing/selftests/kselftest/runner.sh
tools/testing/selftests/kselftest_deps.sh [new file with mode: 0755]
tools/testing/selftests/kselftest_harness.h
tools/testing/selftests/kvm/Makefile
tools/testing/selftests/kvm/include/evmcs.h
tools/testing/selftests/kvm/lib/x86_64/vmx.c
tools/testing/selftests/memfd/Makefile
tools/testing/selftests/net/fib_nexthops.sh
tools/testing/selftests/net/fib_tests.sh
tools/testing/selftests/net/tcp_mmap.c
tools/testing/selftests/seccomp/seccomp_bpf.c
tools/testing/selftests/tc-testing/tdc.py
tools/testing/selftests/tpm2/test_smoke.sh
tools/testing/selftests/tpm2/test_space.sh
tools/testing/selftests/vm/Makefile
tools/testing/selftests/vm/run_vmtests
tools/testing/selftests/wireguard/netns.sh
tools/testing/selftests/wireguard/qemu/arch/powerpc64le.config
tools/testing/selftests/wireguard/qemu/debug.config
tools/virtio/Makefile
tools/virtio/asm/barrier.h
tools/virtio/generated/autoconf.h [new file with mode: 0644]
tools/virtio/linux/compiler.h
tools/vm/Makefile
virt/kvm/arm/hyp/aarch32.c
virt/kvm/arm/psci.c
virt/kvm/arm/vgic/vgic-init.c
virt/kvm/arm/vgic/vgic-its.c
virt/kvm/arm/vgic/vgic-mmio-v2.c
virt/kvm/arm/vgic/vgic-mmio-v3.c
virt/kvm/arm/vgic/vgic-mmio.c
virt/kvm/arm/vgic/vgic-mmio.h

index 6ec5558b516bd909e2bb266208e08fdffee4364e..e92e6dd1780d0b2eeebf34d8cbac5bc18bbc8204 100644 (file)
@@ -142,10 +142,13 @@ ForEachMacros:
   - 'for_each_card_auxs'
   - 'for_each_card_auxs_safe'
   - 'for_each_card_components'
+  - 'for_each_card_dapms'
   - 'for_each_card_pre_auxs'
   - 'for_each_card_prelinks'
   - 'for_each_card_rtds'
   - 'for_each_card_rtds_safe'
+  - 'for_each_card_widgets'
+  - 'for_each_card_widgets_safe'
   - 'for_each_cgroup_storage_type'
   - 'for_each_child_of_node'
   - 'for_each_clear_bit'
@@ -160,6 +163,7 @@ ForEachMacros:
   - 'for_each_cpu_and'
   - 'for_each_cpu_not'
   - 'for_each_cpu_wrap'
+  - 'for_each_dapm_widgets'
   - 'for_each_dev_addr'
   - 'for_each_dev_scope'
   - 'for_each_displayid_db'
@@ -170,7 +174,6 @@ 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'
@@ -191,6 +194,7 @@ ForEachMacros:
   - 'for_each_ip_tunnel_rcu'
   - 'for_each_irq_nr'
   - 'for_each_link_codecs'
+  - 'for_each_link_cpus'
   - 'for_each_link_platforms'
   - 'for_each_lru'
   - 'for_each_matching_node'
@@ -250,6 +254,7 @@ ForEachMacros:
   - 'for_each_pci_bridge'
   - 'for_each_pci_dev'
   - 'for_each_pci_msi_entry'
+  - 'for_each_pcm_streams'
   - 'for_each_populated_zone'
   - 'for_each_possible_cpu'
   - 'for_each_present_cpu'
@@ -260,9 +265,12 @@ ForEachMacros:
   - 'for_each_property_of_node'
   - 'for_each_registered_fb'
   - 'for_each_reserved_mem_region'
-  - 'for_each_rtd_codec_dai'
-  - 'for_each_rtd_codec_dai_rollback'
+  - 'for_each_rtd_codec_dais'
+  - 'for_each_rtd_codec_dais_rollback'
   - 'for_each_rtd_components'
+  - 'for_each_rtd_cpu_dais'
+  - 'for_each_rtd_cpu_dais_rollback'
+  - 'for_each_rtd_dais'
   - 'for_each_set_bit'
   - 'for_each_set_bit_from'
   - 'for_each_set_clump8'
@@ -334,6 +342,7 @@ ForEachMacros:
   - 'klp_for_each_object'
   - 'klp_for_each_object_safe'
   - 'klp_for_each_object_static'
+  - 'kunit_suite_for_each_test_case'
   - 'kvm_for_each_memslot'
   - 'kvm_for_each_vcpu'
   - 'list_for_each'
@@ -387,6 +396,7 @@ ForEachMacros:
   - 'of_property_for_each_string'
   - 'of_property_for_each_u32'
   - 'pci_bus_for_each_resource'
+  - 'pcm_for_each_format'
   - 'ping_portaddr_for_each_entry'
   - 'plist_for_each'
   - 'plist_for_each_continue'
@@ -482,7 +492,7 @@ KeepEmptyLinesAtTheStartOfBlocks: false
 MacroBlockBegin: ''
 MacroBlockEnd: ''
 MaxEmptyLinesToKeep: 1
-NamespaceIndentation: Inner
+NamespaceIndentation: None
 #ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
 ObjCBlockIndentWidth: 8
 ObjCSpaceAfterProperty: true
index c00f9f11e3f3f6133d4b741244e034ae2a3c430e..8439d2ae689b4e2bc99f4110340c4cfef8f6d1e4 100644 (file)
@@ -182,12 +182,15 @@ fix_padding
        space-efficient. If this option is not present, large padding is
        used - that is for compatibility with older kernels.
 
-
-The journal mode (D/J), buffer_sectors, journal_watermark, commit_time can
-be changed when reloading the target (load an inactive table and swap the
-tables with suspend and resume). The other arguments should not be changed
-when reloading the target because the layout of disk data depend on them
-and the reloaded target would be non-functional.
+allow_discards
+       Allow block discard requests (a.k.a. TRIM) for the integrity device.
+       Discards are only allowed to devices using internal hash.
+
+The journal mode (D/J), buffer_sectors, journal_watermark, commit_time and
+allow_discards can be changed when reloading the target (load an inactive
+table and swap the tables with suspend and resume). The other arguments
+should not be changed when reloading the target because the layout of disk
+data depend on them and the reloaded target would be non-functional.
 
 
 The layout of the formatted block device:
index f2a93c8679e889151aea5261262d1c7dc13635e6..7bc83f3d9bdfe376762ede68db1d2982eb4d586e 100644 (file)
 
        usbcore.old_scheme_first=
                        [USB] Start with the old device initialization
-                       scheme,  applies only to low and full-speed devices
-                        (default 0 = off).
+                       scheme (default 0 = off).
 
        usbcore.usbfs_memory_mb=
                        [USB] Memory limit (in MB) for buffers allocated by
index 39c95c0e13d30d656b213bfe6715332bf5a269a6..0d427fd1094194204d0fed72caf4b468e2d62017 100644 (file)
@@ -390,9 +390,17 @@ When ``kptr_restrict`` is set to 2, kernel pointers printed using
 modprobe
 ========
 
-This gives the full path of the modprobe command which the kernel will
-use to load modules. This can be used to debug module loading
-requests::
+The full path to the usermode helper for autoloading kernel modules,
+by default "/sbin/modprobe".  This binary is executed when the kernel
+requests a module.  For example, if userspace passes an unknown
+filesystem type to mount(), then the kernel will automatically request
+the corresponding filesystem module by executing this usermode helper.
+This usermode helper should insert the needed module into the kernel.
+
+This sysctl only affects module autoloading.  It has no effect on the
+ability to explicitly insert modules.
+
+This sysctl can be used to debug module loading requests::
 
     echo '#! /bin/sh' > /tmp/modprobe
     echo 'echo "$@" >> /tmp/modprobe.log' >> /tmp/modprobe
@@ -400,10 +408,15 @@ requests::
     chmod a+x /tmp/modprobe
     echo /tmp/modprobe > /proc/sys/kernel/modprobe
 
-This only applies when the *kernel* is requesting that the module be
-loaded; it won't have any effect if the module is being loaded
-explicitly using ``modprobe`` from userspace.
+Alternatively, if this sysctl is set to the empty string, then module
+autoloading is completely disabled.  The kernel will not try to
+execute a usermode helper at all, nor will it call the
+kernel_module_request LSM hook.
 
+If CONFIG_STATIC_USERMODEHELPER=y is set in the kernel configuration,
+then the configured static usermode helper overrides this sysctl,
+except that the empty string is still accepted to completely disable
+module autoloading as described above.
 
 modules_disabled
 ================
@@ -446,28 +459,6 @@ Notes:
      successful IPC object allocation. If an IPC object allocation syscall
      fails, it is undefined if the value remains unmodified or is reset to -1.
 
-modprobe:
-=========
-
-The path to the usermode helper for autoloading kernel modules, by
-default "/sbin/modprobe".  This binary is executed when the kernel
-requests a module.  For example, if userspace passes an unknown
-filesystem type to mount(), then the kernel will automatically request
-the corresponding filesystem module by executing this usermode helper.
-This usermode helper should insert the needed module into the kernel.
-
-This sysctl only affects module autoloading.  It has no effect on the
-ability to explicitly insert modules.
-
-If this sysctl is set to the empty string, then module autoloading is
-completely disabled.  The kernel will not try to execute a usermode
-helper at all, nor will it call the kernel_module_request LSM hook.
-
-If CONFIG_STATIC_USERMODEHELPER=y is set in the kernel configuration,
-then the configured static usermode helper overrides this sysctl,
-except that the empty string is still accepted to completely disable
-module autoloading as described above.
-
 nmi_watchdog
 ============
 
index 5057b11100ed28656893e69c28dd9759092d18f4..036783ee327f252726f645d4684b6673f8a4aad9 100644 (file)
@@ -23,13 +23,14 @@ optional external memory-mapped interface.
 
 Version 1 of the Activity Monitors architecture implements a counter group
 of four fixed and architecturally defined 64-bit event counters.
-  - CPU cycle counter: increments at the frequency of the CPU.
-  - Constant counter: increments at the fixed frequency of the system
-    clock.
-  - Instructions retired: increments with every architecturally executed
-    instruction.
-  - Memory stall cycles: counts instruction dispatch stall cycles caused by
-    misses in the last level cache within the clock domain.
+
+- CPU cycle counter: increments at the frequency of the CPU.
+- Constant counter: increments at the fixed frequency of the system
+  clock.
+- Instructions retired: increments with every architecturally executed
+  instruction.
+- Memory stall cycles: counts instruction dispatch stall cycles caused by
+  misses in the last level cache within the clock domain.
 
 When in WFI or WFE these counters do not increment.
 
@@ -57,11 +58,12 @@ counters, only the presence of the extension.
 
 Firmware (code running at higher exception levels, e.g. arm-tf) support is
 needed to:
- - Enable access for lower exception levels (EL2 and EL1) to the AMU
-   registers.
- - Enable the counters. If not enabled these will read as 0.
- - Save/restore the counters before/after the CPU is being put/brought up
-   from the 'off' power state.
+
+- Enable access for lower exception levels (EL2 and EL1) to the AMU
+  registers.
+- Enable the counters. If not enabled these will read as 0.
+- Save/restore the counters before/after the CPU is being put/brought up
+  from the 'off' power state.
 
 When using kernels that have this feature enabled but boot with broken
 firmware the user may experience panics or lockups when accessing the
@@ -78,10 +80,11 @@ are not trapped in EL2/EL3.
 
 The fixed counters of AMUv1 are accessible though the following system
 register definitions:
- - SYS_AMEVCNTR0_CORE_EL0
- - SYS_AMEVCNTR0_CONST_EL0
- - SYS_AMEVCNTR0_INST_RET_EL0
- - SYS_AMEVCNTR0_MEM_STALL_EL0
+
+- SYS_AMEVCNTR0_CORE_EL0
+- SYS_AMEVCNTR0_CONST_EL0
+- SYS_AMEVCNTR0_INST_RET_EL0
+- SYS_AMEVCNTR0_MEM_STALL_EL0
 
 Auxiliary platform specific counters can be accessed using
 SYS_AMEVCNTR1_EL0(n), where n is a value between 0 and 15.
@@ -93,9 +96,10 @@ Userspace access
 ----------------
 
 Currently, access from userspace to the AMU registers is disabled due to:
- - Security reasons: they might expose information about code executed in
-   secure mode.
- - Purpose: AMU counters are intended for system management use.
+
+- Security reasons: they might expose information about code executed in
+  secure mode.
+- Purpose: AMU counters are intended for system management use.
 
 Also, the presence of the feature is not visible to userspace.
 
@@ -105,8 +109,9 @@ Virtualization
 
 Currently, access from userspace (EL0) and kernelspace (EL1) on the KVM
 guest side is disabled due to:
- - Security reasons: they might expose information about code executed
-   by other guests or the host.
+
+- Security reasons: they might expose information about code executed
+  by other guests or the host.
 
 Any attempt to access the AMU registers will result in an UNDEFINED
 exception being injected into the guest.
index c0ffa30c7c37e3060731645a55bf01922b5ca93f..729e24864fe738a3f5bd79a62d56d9e7c4542c85 100644 (file)
@@ -154,9 +154,9 @@ architectures. These are the recommended replacements:
 
        Use ktime_get() or ktime_get_ts64() instead.
 
-.. c:function:: struct timeval do_gettimeofday( void )
-               struct timespec getnstimeofday( void )
-               struct timespec64 getnstimeofday64( void )
+.. c:function:: void do_gettimeofday( struct timeval * )
+               void getnstimeofday( struct timespec * )
+               void getnstimeofday64( struct timespec64 * )
                void ktime_get_real_ts( struct timespec * )
 
        ktime_get_real_ts64() is a direct replacement, but consider using
index 1df680d0746108b177a566bbd1060f1bc161a544..7782d99850823f9c8e70a494b0aab659f8d88d32 100644 (file)
@@ -2,6 +2,7 @@
 DT_DOC_CHECKER ?= dt-doc-validate
 DT_EXTRACT_EX ?= dt-extract-example
 DT_MK_SCHEMA ?= dt-mk-schema
+DT_MK_SCHEMA_USERONLY_FLAG := $(if $(DT_SCHEMA_FILES), -u)
 
 quiet_cmd_chk_binding = CHKDT   $(patsubst $(srctree)/%,%,$<)
       cmd_chk_binding = $(DT_DOC_CHECKER) -u $(srctree)/$(src) $< ; \
@@ -13,16 +14,18 @@ $(obj)/%.example.dts: $(src)/%.yaml FORCE
 # Use full schemas when checking %.example.dts
 DT_TMP_SCHEMA := $(obj)/processed-schema-examples.yaml
 
+find_cmd = find $(srctree)/$(src) \( -name '*.yaml' ! \
+               -name 'processed-schema*' ! \
+               -name '*.example.dt.yaml' \)
+
 quiet_cmd_mk_schema = SCHEMA  $@
-      cmd_mk_schema = $(DT_MK_SCHEMA) $(DT_MK_SCHEMA_FLAGS) -o $@ $(real-prereqs)
+      cmd_mk_schema = rm -f $@ ; \
+                      $(if $(DT_MK_SCHEMA_FLAGS), \
+                           echo $(real-prereqs), \
+                           $(find_cmd)) | \
+                      xargs $(DT_MK_SCHEMA) $(DT_MK_SCHEMA_FLAGS) >> $@
 
-DT_DOCS = $(addprefix $(src)/, \
-       $(shell \
-       cd $(srctree)/$(src) && \
-       find * \( -name '*.yaml' ! \
-               -name 'processed-schema*' ! \
-               -name '*.example.dt.yaml' \) \
-       ))
+DT_DOCS = $(shell $(find_cmd) | sed -e 's|^$(srctree)/||')
 
 DT_SCHEMA_FILES ?= $(DT_DOCS)
 
@@ -37,7 +40,7 @@ override DTC_FLAGS := \
 $(obj)/processed-schema-examples.yaml: $(DT_DOCS) FORCE
        $(call if_changed,mk_schema)
 
-$(obj)/processed-schema.yaml: DT_MK_SCHEMA_FLAGS := -u
+$(obj)/processed-schema.yaml: DT_MK_SCHEMA_FLAGS := $(DT_MK_SCHEMA_USERONLY_FLAG)
 $(obj)/processed-schema.yaml: $(DT_SCHEMA_FILES) FORCE
        $(call if_changed,mk_schema)
 
index aa0738b4d53401dc84afc4cd8e5bb88e724acd8f..e713a6fe4cf7da2e8aed749ea9cade99d2c3099e 100644 (file)
@@ -42,6 +42,10 @@ properties:
     description:
       See section 2.3.9 of the DeviceTree Specification.
 
+  '#address-cells': true
+
+  '#size-cells': true
+
 required:
   - "#interconnect-cells"
   - compatible
@@ -59,6 +63,8 @@ examples:
         compatible = "allwinner,sun5i-a13-mbus";
         reg = <0x01c01000 0x1000>;
         clocks = <&ccu CLK_MBUS>;
+        #address-cells = <1>;
+        #size-cells = <1>;
         dma-ranges = <0x00000000 0x40000000 0x20000000>;
         #interconnect-cells = <1>;
     };
index de9a465096dbd887bac9c2829d1fe4d8855f311d..444aeea27db83c3cadceae5a7ba877569e3ad1f8 100644 (file)
@@ -91,7 +91,7 @@ required:
 
 examples:
   - |
-    vco1: clock@00 {
+    vco1: clock {
       compatible = "arm,impd1-vco1";
       #clock-cells = <0>;
       lock-offset = <0x08>;
index a6b2b2b8f3d9e3a6b770f349d7e2f6dff91c68d6..d3c2a4914ea2c2474fec4370c6634a96c7e65196 100644 (file)
@@ -1,5 +1,5 @@
-Analog Device ADV7123 Video DAC
--------------------------------
+Analog Devices ADV7123 Video DAC
+--------------------------------
 
 The ADV7123 is a digital-to-analog converter that outputs VGA signals from a
 parallel video input.
index e8ddec5d9d910a5a1d2d68684ffc9b4f4a822261..659523f538bfc0eee3fcf88a346c2ef08d40b039 100644 (file)
@@ -1,5 +1,5 @@
-Analog Device ADV7511(W)/13/33/35 HDMI Encoders
------------------------------------------
+Analog Devices ADV7511(W)/13/33/35 HDMI Encoders
+------------------------------------------------
 
 The ADV7511, ADV7511W, ADV7513, ADV7533 and ADV7535 are HDMI audio and video
 transmitters compatible with HDMI 1.4 and DVI 1.0. They support color space
index fd931b29381670bcf271f926b9543522f06d260c..b900973b5f7b7622fba9ccd3f4b5720a61e159cf 100644 (file)
@@ -37,7 +37,6 @@ examples:
     dsi {
         #address-cells = <1>;
         #size-cells = <0>;
-        reg = <0xff450000 0x1000>;
 
         panel@0 {
             compatible = "leadtek,ltk500hd1829";
index d0083301acbefbe78a1d528a413ae2f2a24f73a2..946dd354256c11d2e461f4810e8b094ef08117f3 100644 (file)
@@ -96,12 +96,20 @@ properties:
       If set, reverse the bit order described in the data mappings below on all
       data lanes, transmitting bits for slots 6 to 0 instead of 0 to 6.
 
+  port: true
+  ports: true
+
 required:
   - compatible
   - data-mapping
   - width-mm
   - height-mm
   - panel-timing
-  - port
+
+oneOf:
+  - required:
+      - port
+  - required:
+      - ports
 
 ...
index d9fdb58e06b4218bc1db4d2b9b8534085903f336..6913923df5695ccd453a7597ebf532f18c509c78 100644 (file)
@@ -37,7 +37,6 @@ examples:
     dsi {
         #address-cells = <1>;
         #size-cells = <0>;
-        reg = <0xff450000 0x1000>;
 
         panel@0 {
             compatible = "xinpeng,xpp055c272";
index b38ee732efa9fd5f857b207c8941ca17acf83c5f..cd17684aaab5bcd38bb8b1d7644601ae0a0186a1 100644 (file)
@@ -1,4 +1,4 @@
-Analog Device AXI-DMAC DMA controller
+Analog Devices AXI-DMAC DMA controller
 
 Required properties:
  - compatible: Must be "adi,axi-dmac-1.00.a".
index 86cfb599256ed5ddd67191164b2fcd01745ae714..371f187731983f2450f56f324f2e3ad23c5ec4df 100644 (file)
@@ -22,9 +22,7 @@ properties:
     const: socionext,uniphier-xdmac
 
   reg:
-    items:
-      - description: XDMAC base register region (offset and length)
-      - description: XDMAC extension register region (offset and length)
+    maxItems: 1
 
   interrupts:
     maxItems: 1
@@ -49,12 +47,13 @@ required:
   - reg
   - interrupts
   - "#dma-cells"
+  - dma-channels
 
 examples:
   - |
     xdmac: dma-controller@5fc10000 {
         compatible = "socionext,uniphier-xdmac";
-        reg = <0x5fc10000 0x1000>, <0x5fc20000 0x800>;
+        reg = <0x5fc10000 0x5300>;
         interrupts = <0 188 4>;
         #dma-cells = <2>;
         dma-channels = <16>;
index 57a240d2d02694b8d3d2547390bc5eb9654c5dc8..7db78767c02d0dba38d2c40e7c9de59ddafb2af0 100644 (file)
@@ -2,7 +2,7 @@
 # Copyright 2019 Analog Devices Inc.
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/bindings/hwmon/adi,axi-fan-control.yaml#
+$id: http://devicetree.org/schemas/hwmon/adi,axi-fan-control.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Analog Devices AXI FAN Control Device Tree Bindings
@@ -47,7 +47,7 @@ required:
 
 examples:
   - |
-    fpga_axi: fpga-axi@0 {
+    fpga_axi: fpga-axi {
             #address-cells = <0x2>;
             #size-cells = <0x1>;
 
index 76985034ea7351de10b1de07a0b0351e8b6b1a88..46c441574f98b592e651b57fe34c885a9d41a8a0 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/adt7475.yaml#
+$id: http://devicetree.org/schemas/hwmon/adt7475.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: ADT7475 hwmon sensor
index 933ba37944d7175a12fc5bde0cef17aa7139a265..dd8eb15aeb6395b68b1583f03a5f8a0621315f08 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/bindings/iio/adc/st,stm32-adc.yaml#"
+$id: "http://devicetree.org/schemas/iio/adc/st,stm32-adc.yaml#"
 $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 
 title: STMicroelectronics STM32 ADC bindings
index f0bbd7e1029bd44d7c2c989217cbfc0b144635f9..502e1e55adbdebd08d588350ba8a2f57b28a8696 100644 (file)
@@ -1,4 +1,4 @@
-* Analog Device AD5755 IIO Multi-Channel DAC Linux Driver
+* Analog Devices AD5755 IIO Multi-Channel DAC Linux Driver
 
 Required properties:
  - compatible: Has to contain one of the following:
index d9c25cf4b92f2f17cc4488d5f8cde3ef74eb0caf..58d81ca434605be574fecf06d75324c0e0bddb7c 100644 (file)
@@ -2,7 +2,7 @@
 # Copyright 2020 Analog Devices Inc.
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/bindings/iio/dac/adi,ad5770r.yaml#
+$id: http://devicetree.org/schemas/iio/dac/adi,ad5770r.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Analog Devices AD5770R DAC device driver
@@ -49,93 +49,86 @@ properties:
       asserted during driver probe.
     maxItems: 1
 
-  channel0:
+  channel@0:
     description: Represents an external channel which are
       connected to the DAC. Channel 0 can act both as a current
       source and sink.
     type: object
 
     properties:
-      num:
+      reg:
         description: This represents the channel number.
-        items:
-          const: 0
+        const: 0
 
       adi,range-microamp:
           description: Output range of the channel.
           oneOf:
-            - $ref: /schemas/types.yaml#/definitions/int32-array
             - items:
-                - enum: [0 300000]
-                - enum: [-60000 0]
-                - enum: [-60000 300000]
+                - const: 0
+                - const: 300000
+            - items:
+                - const: -60000
+                - const: 0
+            - items:
+                - const: -60000
+                - const: 300000
 
-  channel1:
+  channel@1:
     description: Represents an external channel which are
       connected to the DAC.
     type: object
 
     properties:
-      num:
+      reg:
         description: This represents the channel number.
-        items:
-          const: 1
+        const: 1
 
       adi,range-microamp:
           description: Output range of the channel.
-          oneOf:
-            - $ref: /schemas/types.yaml#/definitions/uint32-array
-            - items:
-                - enum: [0 140000]
-                - enum: [0 250000]
+          items:
+            - const: 0
+            - enum: [ 140000, 250000 ]
 
-  channel2:
+  channel@2:
     description: Represents an external channel which are
       connected to the DAC.
     type: object
 
     properties:
-      num:
+      reg:
         description: This represents the channel number.
-        items:
-          const: 2
+        const: 2
 
       adi,range-microamp:
           description: Output range of the channel.
-          oneOf:
-            - $ref: /schemas/types.yaml#/definitions/uint32-array
-            - items:
-                - enum: [0 140000]
-                - enum: [0 250000]
+          items:
+            - const: 0
+            - enum: [ 55000, 150000 ]
 
 patternProperties:
   "^channel@([3-5])$":
     type: object
     description: Represents the external channels which are connected to the DAC.
     properties:
-      num:
+      reg:
         description: This represents the channel number.
-        items:
-          minimum: 3
-          maximum: 5
+        minimum: 3
+        maximum: 5
 
       adi,range-microamp:
           description: Output range of the channel.
-          oneOf:
-            - $ref: /schemas/types.yaml#/definitions/uint32-array
-            - items:
-                - enum: [0 45000]
-                - enum: [0 100000]
+          items:
+            - const: 0
+            - enum: [ 45000, 100000 ]
 
 required:
 - reg
-- diff-channels
-- channel0
-- channel1
-- channel2
-- channel3
-- channel4
-- channel5
+- channel@0
+- channel@1
+- channel@2
+- channel@3
+- channel@4
+- channel@5
 
 examples:
   - |
@@ -144,40 +137,42 @@ examples:
                 #size-cells = <0>;
 
                 ad5770r@0 {
-                        compatible = "ad5770r";
+                        compatible = "adi,ad5770r";
                         reg = <0>;
                         spi-max-frequency = <1000000>;
                         vref-supply = <&vref>;
                         adi,external-resistor;
                         reset-gpios = <&gpio 22 0>;
+                        #address-cells = <1>;
+                        #size-cells = <0>;
 
                         channel@0 {
-                                num = <0>;
-                                adi,range-microamp = <(-60000) 300000>;
+                                reg = <0>;
+                                adi,range-microamp = <0 300000>;
                         };
 
                         channel@1 {
-                                num = <1>;
+                                reg = <1>;
                                 adi,range-microamp = <0 140000>;
                         };
 
                         channel@2 {
-                                num = <2>;
+                                reg = <2>;
                                 adi,range-microamp = <0 55000>;
                         };
 
                         channel@3 {
-                                num = <3>;
+                                reg = <3>;
                                 adi,range-microamp = <0 45000>;
                         };
 
                         channel@4 {
-                                num = <4>;
+                                reg = <4>;
                                 adi,range-microamp = <0 45000>;
                         };
 
                         channel@5 {
-                                num = <5>;
+                                reg = <5>;
                                 adi,range-microamp = <0 45000>;
                         };
                 };
index 8d58709d4b478368215210189c96f054b71611ca..383d64a918547ea1c851d2c6b19982c94e39f3a6 100644 (file)
@@ -109,7 +109,7 @@ examples:
   - |
     #include <dt-bindings/gpio/gpio.h>
     #include <dt-bindings/interrupt-controller/arm-gic.h>
-    i2c@00000000 {
+    i2c {
       #address-cells = <1>;
       #size-cells = <0>;
       edt-ft5x06@38 {
index 9c6b91fee477acd5fca5b2124e56131a1edbadae..26f1fcf0857aa1348b03bfc0831e415dc83aa166 100644 (file)
@@ -56,9 +56,8 @@ properties:
       cell with zero.
     allOf:
       - $ref: /schemas/types.yaml#/definitions/uint32-array
-      - items:
-          minItems: 4
-          maxItems: 4
+      - minItems: 4
+        maxItems: 4
 
 
 required:
index 12516bd89cf9696812ed9298933177ce4ddf39ec..611bda38d1872b45282537f81e07c6027b7141ff 100644 (file)
@@ -97,30 +97,35 @@ examples:
     #include <dt-bindings/clock/tegra186-clock.h>
     #include <dt-bindings/interrupt-controller/arm-gic.h>
 
-    memory-controller@2c00000 {
-        compatible = "nvidia,tegra186-mc";
-        reg = <0x0 0x02c00000 0x0 0xb0000>;
-        interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
-
+    bus {
         #address-cells = <2>;
         #size-cells = <2>;
 
-        ranges = <0x0 0x02c00000 0x02c00000 0x0 0xb0000>;
+        memory-controller@2c00000 {
+            compatible = "nvidia,tegra186-mc";
+            reg = <0x0 0x02c00000 0x0 0xb0000>;
+            interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
+
+            #address-cells = <2>;
+            #size-cells = <2>;
+
+            ranges = <0x0 0x02c00000 0x0 0x02c00000 0x0 0xb0000>;
 
-        /*
-         * Memory clients have access to all 40 bits that the memory
-         * controller can address.
-         */
-        dma-ranges = <0x0 0x0 0x0 0x0 0x100 0x0>;
+            /*
+             * Memory clients have access to all 40 bits that the memory
+             * controller can address.
+             */
+            dma-ranges = <0x0 0x0 0x0 0x0 0x100 0x0>;
 
-        external-memory-controller@2c60000 {
-            compatible = "nvidia,tegra186-emc";
-            reg = <0x0 0x02c60000 0x0 0x50000>;
-            interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>;
-            clocks = <&bpmp TEGRA186_CLK_EMC>;
-            clock-names = "emc";
+            external-memory-controller@2c60000 {
+                compatible = "nvidia,tegra186-emc";
+                reg = <0x0 0x02c60000 0x0 0x50000>;
+                interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>;
+                clocks = <&bpmp TEGRA186_CLK_EMC>;
+                clock-names = "emc";
 
-            nvidia,bpmp = <&bpmp>;
+                nvidia,bpmp = <&bpmp>;
+            };
         };
     };
 
index aa922c560fccbdf6041599d2ee6661cd5b95bd86..65018a019e1db316b442bfe32ac025e2225d33ff 100644 (file)
@@ -123,7 +123,9 @@ examples:
     #include <dt-bindings/leds/common.h>
 
     i2c {
-      pmic: pmic@4b {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        pmic: pmic@4b {
             compatible = "rohm,bd71837";
             reg = <0x4b>;
             interrupt-parent = <&gpio1>;
index 402e40dfe0b85b0200aca2b9534f4d5e9b56979c..77bcca2d414f8bda4ed4fe49c2ad183e0b1b3875 100644 (file)
@@ -128,7 +128,9 @@ examples:
     #include <dt-bindings/leds/common.h>
 
     i2c {
-      pmic: pmic@4b {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        pmic: pmic@4b {
             compatible = "rohm,bd71847";
             reg = <0x4b>;
             interrupt-parent = <&gpio1>;
index d9ad9260e348a826777ceed3d91b55b9feb86904..be7faa6dc055e3fcc494458033f42bd8a99de138 100644 (file)
@@ -259,8 +259,6 @@ properties:
 
     additionalProperties: false
 
-  additionalProperties: false
-
 additionalProperties: false
 
 required:
@@ -274,7 +272,7 @@ examples:
   - |
     #include <dt-bindings/mfd/st,stpmic1.h>
     #include <dt-bindings/interrupt-controller/arm-gic.h>
-    i2c@0 {
+    i2c {
       #address-cells = <1>;
       #size-cells = <0>;
       pmic@33 {
index 8927941c74bb836e87b70d7fba641ca993add157..5aa141ccc1137abd1780f84104a7c7c5d869141c 100644 (file)
@@ -43,6 +43,9 @@ properties:
           second group of digits is the Phy Identifier 2 register,
           this is the chip vendor OUI bits 19:24, followed by 10
           bits of a vendor specific ID.
+      - items:
+          - pattern: "^ethernet-phy-id[a-f0-9]{4}\\.[a-f0-9]{4}$"
+          - const: ethernet-phy-ieee802.3-c22
       - items:
           - pattern: "^ethernet-phy-id[a-f0-9]{4}\\.[a-f0-9]{4}$"
           - const: ethernet-phy-ieee802.3-c45
index 5b88fae0307d153e50a6faac33d6152bdf2711d4..ff8b0f211aa190ba24a42ec71e8d941e4d2f7f6f 100644 (file)
@@ -22,6 +22,8 @@ Optional properties:
 - fsl,err006687-workaround-present: If present indicates that the system has
   the hardware workaround for ERR006687 applied and does not need a software
   workaround.
+- gpr: phandle of SoC general purpose register mode. Required for wake on LAN
+  on some SoCs
  -interrupt-names:  names of the interrupts listed in interrupts property in
   the same order. The defaults if not specified are
   __Number of interrupts__   __Default__
index b9f90081046f76838c02fc2ff1d46aa30e7c1bc1..67df3fe861eed9dcc993eb54d66862f2d557d231 100644 (file)
@@ -48,6 +48,7 @@ examples:
 
         switch@10 {
             compatible = "qca,qca8337";
+            reg = <0x10>;
             /* ... */
         };
     };
index beca6466d59a9d7d1f9b6afaffa1e6d246c5352a..d2202791c1d4c0c57eb829ed389ddaf75e951792 100644 (file)
@@ -29,7 +29,7 @@ Required properties for compatible string qcom,wcn399x-bt:
 
 Optional properties for compatible string qcom,wcn399x-bt:
 
- - max-speed: see Documentation/devicetree/bindings/serial/slave-device.txt
+ - max-speed: see Documentation/devicetree/bindings/serial/serial.yaml
  - firmware-name: specify the name of nvm firmware to load
  - clocks: clock provided to the controller
 
index 144ae29e7141930221bddbda99d1631df07b79a3..f8bd28ff31c1fafd03468fa5bb4e3bdc712ca65a 100644 (file)
@@ -97,7 +97,7 @@ then:
         - $ref: /schemas/types.yaml#/definitions/uint32
         - minimum: 0
           maximum: 63
-          default: 0
+          default: 32
 
     qcom,charge-ctrl-value:
      description:
@@ -130,7 +130,7 @@ then:
         - $ref: /schemas/types.yaml#/definitions/uint32
         - minimum: 0
           maximum: 3
-          default: 2
+          default: 0
 
     qcom,preemphasis-width:
       description:
@@ -152,7 +152,7 @@ then:
         - $ref: /schemas/types.yaml#/definitions/uint32
         - minimum: 0
           maximum: 3
-          default: 0
+          default: 1
 
 required:
   - compatible
index fd1982c5610467aa7753ee0af2e35d6576bbdab5..3f913d6d1c3d8beec2b6e8a9764d76094e05bab2 100644 (file)
@@ -146,7 +146,7 @@ patternProperties:
       bindings specified in
       Documentation/devicetree/bindings/phy/phy-cadence-sierra.txt
       Torrent SERDES should follow the bindings specified in
-      Documentation/devicetree/bindings/phy/phy-cadence-dp.txt
+      Documentation/devicetree/bindings/phy/phy-cadence-torrent.yaml
 
 required:
   - compatible
index 24c217b7658032867bcf9cf8da55f0ca5ba12f69..41ece1d853152efcc30ddbc28dfa36c0deb036f0 100644 (file)
@@ -31,10 +31,17 @@ additionalProperties: false
 
 examples:
   - |
-    cros-ec@0 {
-        compatible = "google,cros-ec-spi";
-        cros_ec_pwm: ec-pwm {
-            compatible = "google,cros-ec-pwm";
-            #pwm-cells = <1>;
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        cros-ec@0 {
+            compatible = "google,cros-ec-spi";
+            reg = <0>;
+
+            cros_ec_pwm: ec-pwm {
+                compatible = "google,cros-ec-pwm";
+                #pwm-cells = <1>;
+            };
         };
     };
index f0acce2029fde0e9f10e6335ab563fb1d88ee544..3b019fa6db31788380d9122a643e602a8b03ac69 100644 (file)
@@ -37,7 +37,6 @@ properties:
         type: object
 
     additionalProperties: false
-  additionalProperties: false
 
 required:
   - compatible
index a682af0dc67ed129a394ca61e08f119a9fc0df3a..ae6e7ab36c58658c47a8cf82cc217e34bb2beb5b 100644 (file)
@@ -75,7 +75,8 @@ properties:
             description: |
               disables over voltage protection of this buck
 
-      additionalProperties: false
+        unevaluatedProperties: false
+
     additionalProperties: false
 
 required:
index 71ce032b8cf8b87659fe035a7e30a3061a4df858..1e52dafcb5c9a4e8080450bb64daeb08cc0d2f83 100644 (file)
@@ -35,6 +35,8 @@ patternProperties:
         description:
           should be "ldo1", ..., "ldo7"
 
+    unevaluatedProperties: false
+
   "^BUCK[1-7]$":
     type: object
     allOf:
@@ -103,5 +105,7 @@ patternProperties:
 
     required:
       - regulator-name
-  additionalProperties: false
+
+    unevaluatedProperties: false
+
 additionalProperties: false
index a323b1696eee8597c37a792ad0e36c818f3a8e96..543d4b52397e2572db019c3660b95a4b0e59b866 100644 (file)
@@ -41,6 +41,8 @@ patternProperties:
         description:
           should be "ldo1", ..., "ldo7"
 
+    unevaluatedProperties: false
+
   "^BUCK[1-8]$":
     type: object
     allOf:
@@ -99,5 +101,7 @@ patternProperties:
 
     required:
       - regulator-name
-  additionalProperties: false
+
+    unevaluatedProperties: false
+
 additionalProperties: false
index 526fd00bcb162b2642dc962313502b5717a4e6b8..d797cc23406f897b3ff1bb40989b278b34ca28e0 100644 (file)
@@ -40,6 +40,8 @@ patternProperties:
         description:
           should be "ldo1", ..., "ldo6"
 
+    unevaluatedProperties: false
+
   "^BUCK[1-6]$":
     type: object
     allOf:
@@ -93,5 +95,7 @@ patternProperties:
 
     required:
       - regulator-name
-  additionalProperties: false
+
+    unevaluatedProperties: false
+
 additionalProperties: false
index 89ab67f20a7fe9a57834785229b58b2461551eea..c147900f9041ab93ed9ba0031551456fa8ee9ed6 100644 (file)
@@ -39,7 +39,7 @@ additionalProperties: false
 
 examples:
   - |
-    rng {
+    rng@7e104000 {
         compatible = "brcm,bcm2835-rng";
         reg = <0x7e104000 0x10>;
         interrupts = <2 29>;
index 7cd0e278ed85a1a09e9bd290ab0a0ae00ef5cfa0..a3ba2186d6a184ee3f98f9199623305b3f851211 100644 (file)
@@ -56,6 +56,9 @@ properties:
       - const: tx
       - const: rx
 
+  power-domains:
+    maxItems: 1
+
   rockchip,capture-channels:
     allOf:
       - $ref: /schemas/types.yaml#/definitions/uint32
diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.txt b/Documentation/devicetree/bindings/sound/rockchip-spdif.txt
deleted file mode 100644 (file)
index ec20c12..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-* Rockchip SPDIF transceiver
-
-The S/PDIF audio block is a stereo transceiver that allows the
-processor to receive and transmit digital audio via an coaxial cable or
-a fibre cable.
-
-Required properties:
-
-- compatible: should be one of the following:
-   - "rockchip,rk3066-spdif"
-   - "rockchip,rk3188-spdif"
-   - "rockchip,rk3228-spdif"
-   - "rockchip,rk3288-spdif"
-   - "rockchip,rk3328-spdif"
-   - "rockchip,rk3366-spdif"
-   - "rockchip,rk3368-spdif"
-   - "rockchip,rk3399-spdif"
-- reg: physical base address of the controller and length of memory mapped
-  region.
-- interrupts: should contain the SPDIF interrupt.
-- dmas: DMA specifiers for tx dma. See the DMA client binding,
-  Documentation/devicetree/bindings/dma/dma.txt
-- dma-names: should be "tx"
-- clocks: a list of phandle + clock-specifier pairs, one for each entry
-  in clock-names.
-- clock-names: should contain following:
-   - "hclk": clock for SPDIF controller
-   - "mclk" : clock for SPDIF bus
-
-Required properties on RK3288:
-  - rockchip,grf: the phandle of the syscon node for the general register
-                   file (GRF)
-
-Example for the rk3188 SPDIF controller:
-
-spdif: spdif@1011e000 {
-       compatible = "rockchip,rk3188-spdif", "rockchip,rk3066-spdif";
-       reg = <0x1011e000 0x2000>;
-       interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
-       dmas = <&dmac1_s 8>;
-       dma-names = "tx";
-       clock-names = "hclk", "mclk";
-       clocks = <&cru HCLK_SPDIF>, <&cru SCLK_SPDIF>;
-       #sound-dai-cells = <0>;
-};
diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml b/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml
new file mode 100644 (file)
index 0000000..c467152
--- /dev/null
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/rockchip-spdif.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip SPDIF transceiver
+
+description:
+  The S/PDIF audio block is a stereo transceiver that allows the
+  processor to receive and transmit digital audio via a coaxial or
+  fibre cable.
+
+maintainers:
+  - Heiko Stuebner <heiko@sntech.de>
+
+properties:
+  compatible:
+    oneOf:
+      - const: rockchip,rk3066-spdif
+      - const: rockchip,rk3228-spdif
+      - const: rockchip,rk3328-spdif
+      - const: rockchip,rk3366-spdif
+      - const: rockchip,rk3368-spdif
+      - const: rockchip,rk3399-spdif
+      - items:
+          - enum:
+            - rockchip,rk3188-spdif
+            - rockchip,rk3288-spdif
+          - const: rockchip,rk3066-spdif
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: clock for SPDIF bus
+      - description: clock for SPDIF controller
+
+  clock-names:
+    items:
+      - const: mclk
+      - const: hclk
+
+  dmas:
+    maxItems: 1
+
+  dma-names:
+    const: tx
+
+  power-domains:
+    maxItems: 1
+
+  rockchip,grf:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      The phandle of the syscon node for the GRF register.
+      Required property on RK3288.
+
+  "#sound-dai-cells":
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - dmas
+  - dma-names
+  - "#sound-dai-cells"
+
+if:
+  properties:
+    compatible:
+      contains:
+        const: rockchip,rk3288-spdif
+
+then:
+  required:
+    - rockchip,grf
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/rk3188-cru.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    spdif: spdif@1011e000 {
+      compatible = "rockchip,rk3188-spdif", "rockchip,rk3066-spdif";
+      reg = <0x1011e000 0x2000>;
+      interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+      clocks = <&cru SCLK_SPDIF>, <&cru HCLK_SPDIF>;
+      clock-names = "mclk", "hclk";
+      dmas = <&dmac1_s 8>;
+      dma-names = "tx";
+      #sound-dai-cells = <0>;
+    };
index 0cf470eaf2a07e62d9a6fab26f2f2a6ccc33693d..5c16cf59ca00523582247a0a70001b140e16492c 100644 (file)
@@ -61,7 +61,7 @@ examples:
     #include <dt-bindings/clock/qcom,gcc-sdm845.h>
     #include <dt-bindings/interrupt-controller/arm-gic.h>
 
-    soc: soc@0 {
+    soc: soc {
         #address-cells = <2>;
         #size-cells = <2>;
 
index 1d687787507734fcffece11bfac717da5e9fe39d..c2d2ee43ba67e4c02c69525ac4bae5b9448cba0b 100644 (file)
@@ -56,7 +56,7 @@ additionalProperties: false
 examples:
   - |
     #include <dt-bindings/clock/jz4740-cgu.h>
-    usb_phy: usb-phy@0 {
+    usb_phy: usb-phy {
       compatible = "usb-nop-xceiv";
       #phy-cells = <0>;
     };
index cb695aa3fba4ccdc13988514949a84d51b9abe7c..fbdd0175675209bb58267bc0fee2d5365d917e33 100644 (file)
@@ -52,8 +52,8 @@ A child node must exist to represent the core DWC3 IP block. The name of
 the node is not important. The content of the node is defined in dwc3.txt.
 
 Phy documentation is provided in the following places:
-Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt   - USB3 QMP PHY
-Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt - USB2 QUSB2 PHY
+Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt    - USB3 QMP PHY
+Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml - USB2 QUSB2 PHY
 
 Example device nodes:
 
index 92d8631b9aa60c6968d074100d4a98b62e310ce7..031452aa25bc2a94c24cab8281e8762be76947e9 100644 (file)
@@ -18,6 +18,7 @@ properties:
           - renesas,r8a774c0-usb3-peri # RZ/G2E
           - renesas,r8a7795-usb3-peri  # R-Car H3
           - renesas,r8a7796-usb3-peri  # R-Car M3-W
+          - renesas,r8a77961-usb3-peri # R-Car M3-W+
           - renesas,r8a77965-usb3-peri # R-Car M3-N
           - renesas,r8a77990-usb3-peri # R-Car E3
       - const: renesas,rcar-gen3-usb3-peri
index 469affa872d34ba7662dde2f1778b1d70136923d..a7ae95598ccb1056182b471d627610e64d68904c 100644 (file)
@@ -40,6 +40,7 @@ properties:
               - renesas,usbhs-r8a774c0 # RZ/G2E
               - renesas,usbhs-r8a7795  # R-Car H3
               - renesas,usbhs-r8a7796  # R-Car M3-W
+              - renesas,usbhs-r8a77961 # R-Car M3-W+
               - renesas,usbhs-r8a77965 # R-Car M3-N
               - renesas,usbhs-r8a77990 # R-Car E3
               - renesas,usbhs-r8a77995 # R-Car D3
index c8c4b00ecb941fe85144fb3efd8c5cfa4ec0e5e4..94520493233bb51ae663cc3b30f6ea1816474bd2 100644 (file)
@@ -16,7 +16,7 @@ A child node must exist to represent the core DWC3 IP block. The name of
 the node is not important. The content of the node is defined in dwc3.txt.
 
 Phy documentation is provided in the following places:
-Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt - USB2.0 PHY
+Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.yaml - USB2.0 PHY
 Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt     - Type-C PHY
 
 Example device nodes:
index 3f378951d624bfc6b45035a23e77dc0c42a33b62..dc025f126d717b4b8471080ee03f09278a1b9a3d 100644 (file)
@@ -16,7 +16,8 @@ Required properties:
     - "renesas,xhci-r8a7791" for r8a7791 SoC
     - "renesas,xhci-r8a7793" for r8a7793 SoC
     - "renesas,xhci-r8a7795" for r8a7795 SoC
-    - "renesas,xhci-r8a7796" for r8a7796 SoC
+    - "renesas,xhci-r8a7796" for r8a77960 SoC
+    - "renesas,xhci-r8a77961" for r8a77961 SoC
     - "renesas,xhci-r8a77965" for r8a77965 SoC
     - "renesas,xhci-r8a77990" for r8a77990 SoC
     - "renesas,rcar-gen2-xhci" for a generic R-Car Gen2 or RZ/G1 compatible
index db9ea085404033d7723ccd2ba02c4abdab8b0712..6c032db235a5efa2e4745485d4a22cdb3ffe503a 100644 (file)
@@ -79,8 +79,8 @@ created with any of::
                           struct dentry *parent, u8 *value);
     void debugfs_create_u16(const char *name, umode_t mode,
                            struct dentry *parent, u16 *value);
-    struct dentry *debugfs_create_u32(const char *name, umode_t mode,
-                                     struct dentry *parent, u32 *value);
+    void debugfs_create_u32(const char *name, umode_t mode,
+                           struct dentry *parent, u32 *value);
     void debugfs_create_u64(const char *name, umode_t mode,
                            struct dentry *parent, u64 *value);
 
index cc4b61447b63b135394a084742d70b24630eed57..0e71b22047f897b6510e52b56d6065c38d1523f1 100644 (file)
@@ -16,7 +16,7 @@ Supported chips:
 
   * Renesas ISL68220
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl68220'
 
     Addresses scanned: -
 
@@ -26,7 +26,7 @@ Supported chips:
 
   * Renesas ISL68221
 
-    Prefix: 'raa_dmpvr2_3rail'
+    Prefix: 'isl68221'
 
     Addresses scanned: -
 
@@ -36,7 +36,7 @@ Supported chips:
 
   * Renesas ISL68222
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl68222'
 
     Addresses scanned: -
 
@@ -46,7 +46,7 @@ Supported chips:
 
   * Renesas ISL68223
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl68223'
 
     Addresses scanned: -
 
@@ -56,7 +56,7 @@ Supported chips:
 
   * Renesas ISL68224
 
-    Prefix: 'raa_dmpvr2_3rail'
+    Prefix: 'isl68224'
 
     Addresses scanned: -
 
@@ -66,7 +66,7 @@ Supported chips:
 
   * Renesas ISL68225
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl68225'
 
     Addresses scanned: -
 
@@ -76,7 +76,7 @@ Supported chips:
 
   * Renesas ISL68226
 
-    Prefix: 'raa_dmpvr2_3rail'
+    Prefix: 'isl68226'
 
     Addresses scanned: -
 
@@ -86,7 +86,7 @@ Supported chips:
 
   * Renesas ISL68227
 
-    Prefix: 'raa_dmpvr2_1rail'
+    Prefix: 'isl68227'
 
     Addresses scanned: -
 
@@ -96,7 +96,7 @@ Supported chips:
 
   * Renesas ISL68229
 
-    Prefix: 'raa_dmpvr2_3rail'
+    Prefix: 'isl68229'
 
     Addresses scanned: -
 
@@ -106,7 +106,7 @@ Supported chips:
 
   * Renesas ISL68233
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl68233'
 
     Addresses scanned: -
 
@@ -116,7 +116,7 @@ Supported chips:
 
   * Renesas ISL68239
 
-    Prefix: 'raa_dmpvr2_3rail'
+    Prefix: 'isl68239'
 
     Addresses scanned: -
 
@@ -126,7 +126,7 @@ Supported chips:
 
   * Renesas ISL69222
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl69222'
 
     Addresses scanned: -
 
@@ -136,7 +136,7 @@ Supported chips:
 
   * Renesas ISL69223
 
-    Prefix: 'raa_dmpvr2_3rail'
+    Prefix: 'isl69223'
 
     Addresses scanned: -
 
@@ -146,7 +146,7 @@ Supported chips:
 
   * Renesas ISL69224
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl69224'
 
     Addresses scanned: -
 
@@ -156,7 +156,7 @@ Supported chips:
 
   * Renesas ISL69225
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl69225'
 
     Addresses scanned: -
 
@@ -166,7 +166,7 @@ Supported chips:
 
   * Renesas ISL69227
 
-    Prefix: 'raa_dmpvr2_3rail'
+    Prefix: 'isl69227'
 
     Addresses scanned: -
 
@@ -176,7 +176,7 @@ Supported chips:
 
   * Renesas ISL69228
 
-    Prefix: 'raa_dmpvr2_3rail'
+    Prefix: 'isl69228'
 
     Addresses scanned: -
 
@@ -186,7 +186,7 @@ Supported chips:
 
   * Renesas ISL69234
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl69234'
 
     Addresses scanned: -
 
@@ -196,7 +196,7 @@ Supported chips:
 
   * Renesas ISL69236
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl69236'
 
     Addresses scanned: -
 
@@ -206,7 +206,7 @@ Supported chips:
 
   * Renesas ISL69239
 
-    Prefix: 'raa_dmpvr2_3rail'
+    Prefix: 'isl69239'
 
     Addresses scanned: -
 
@@ -216,7 +216,7 @@ Supported chips:
 
   * Renesas ISL69242
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl69242'
 
     Addresses scanned: -
 
@@ -226,7 +226,7 @@ Supported chips:
 
   * Renesas ISL69243
 
-    Prefix: 'raa_dmpvr2_1rail'
+    Prefix: 'isl69243'
 
     Addresses scanned: -
 
@@ -236,7 +236,7 @@ Supported chips:
 
   * Renesas ISL69247
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl69247'
 
     Addresses scanned: -
 
@@ -246,7 +246,7 @@ Supported chips:
 
   * Renesas ISL69248
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl69248'
 
     Addresses scanned: -
 
@@ -256,7 +256,7 @@ Supported chips:
 
   * Renesas ISL69254
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl69254'
 
     Addresses scanned: -
 
@@ -266,7 +266,7 @@ Supported chips:
 
   * Renesas ISL69255
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl69255'
 
     Addresses scanned: -
 
@@ -276,7 +276,7 @@ Supported chips:
 
   * Renesas ISL69256
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl69256'
 
     Addresses scanned: -
 
@@ -286,7 +286,7 @@ Supported chips:
 
   * Renesas ISL69259
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl69259'
 
     Addresses scanned: -
 
@@ -296,7 +296,7 @@ Supported chips:
 
   * Renesas ISL69260
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl69260'
 
     Addresses scanned: -
 
@@ -306,7 +306,7 @@ Supported chips:
 
   * Renesas ISL69268
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl69268'
 
     Addresses scanned: -
 
@@ -316,7 +316,7 @@ Supported chips:
 
   * Renesas ISL69269
 
-    Prefix: 'raa_dmpvr2_3rail'
+    Prefix: 'isl69269'
 
     Addresses scanned: -
 
@@ -326,7 +326,7 @@ Supported chips:
 
   * Renesas ISL69298
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'isl69298'
 
     Addresses scanned: -
 
@@ -336,7 +336,7 @@ Supported chips:
 
   * Renesas RAA228000
 
-    Prefix: 'raa_dmpvr2_hv'
+    Prefix: 'raa228000'
 
     Addresses scanned: -
 
@@ -346,7 +346,7 @@ Supported chips:
 
   * Renesas RAA228004
 
-    Prefix: 'raa_dmpvr2_hv'
+    Prefix: 'raa228004'
 
     Addresses scanned: -
 
@@ -356,7 +356,7 @@ Supported chips:
 
   * Renesas RAA228006
 
-    Prefix: 'raa_dmpvr2_hv'
+    Prefix: 'raa228006'
 
     Addresses scanned: -
 
@@ -366,7 +366,7 @@ Supported chips:
 
   * Renesas RAA228228
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'raa228228'
 
     Addresses scanned: -
 
@@ -376,7 +376,7 @@ Supported chips:
 
   * Renesas RAA229001
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'raa229001'
 
     Addresses scanned: -
 
@@ -386,7 +386,7 @@ Supported chips:
 
   * Renesas RAA229004
 
-    Prefix: 'raa_dmpvr2_2rail'
+    Prefix: 'raa229004'
 
     Addresses scanned: -
 
index 04d5c01a2e998db16fa8ca7846a5d8e0034c41a0..b80257a0383030fc7f5383f3a37cc37ee8df2179 100644 (file)
@@ -1241,7 +1241,8 @@ When kbuild executes, the following steps are followed (roughly):
        will be displayed with "make KBUILD_VERBOSE=0".
 
 
---- 6.9 Preprocessing linker scripts
+6.9 Preprocessing linker scripts
+--------------------------------
 
        When the vmlinux image is built, the linker script
        arch/$(ARCH)/kernel/vmlinux.lds is used.
index a09971c2115cd27355542dba40c16213068448ac..fe089acb7783ea5b2079dceac16da6c7c5dc4cf3 100644 (file)
@@ -257,6 +257,8 @@ drivers:
   * :doc:`netdevsim`
   * :doc:`mlxsw`
 
+.. _Generic-Packet-Trap-Groups:
+
 Generic Packet Trap Groups
 ==========================
 
index 5b58fc4e1268ce92bb852765e2403dc4d6cf227e..4574352d6ff4e8b9ab90bd51449bb59f5d4c01cb 100644 (file)
@@ -61,8 +61,8 @@ The ``ice`` driver reports the following versions
       - running
       - ICE OS Default Package
       - The name of the DDP package that is active in the device. The DDP
-        package is loaded by the driver during initialization. Each varation
-        of DDP package shall have a unique name.
+        package is loaded by the driver during initialization. Each
+        variation of the DDP package has a unique name.
     * - ``fw.app``
       - running
       - 1.3.1.0
index 50133d9761c992bee565d9415d4758e66e45c028..6538ede29661e802ac6e826a688ed03e5d41ed70 100644 (file)
@@ -22,6 +22,7 @@ Contents:
    z8530book
    msg_zerocopy
    failover
+   net_dim
    net_failover
    phy
    sfp-phylink
index ee961d322d931213745e5d4abbc27d400b1420b8..9375324aa8e1630c373098842c05f8d3b38715d9 100644 (file)
@@ -812,7 +812,7 @@ tcp_limit_output_bytes - INTEGER
 tcp_challenge_ack_limit - INTEGER
        Limits number of Challenge ACK sent per second, as recommended
        in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks)
-       Default: 100
+       Default: 1000
 
 tcp_rx_skb_cache - BOOLEAN
        Controls a per TCP socket cache of one skb, that might help
@@ -983,6 +983,13 @@ ip_early_demux - BOOLEAN
        reduces overall throughput, in such case you should disable it.
        Default: 1
 
+ping_group_range - 2 INTEGERS
+       Restrict ICMP_PROTO datagram sockets to users in the group range.
+       The default is "1 0", meaning, that nobody (not even root) may
+       create ping sockets.  Setting it to "100 100" would grant permissions
+       to the single group. "0 4294967295" would enable it for the world, "100
+       4294967295" would enable it for the users, but not daemons.
+
 tcp_early_demux - BOOLEAN
        Enable early demux for established TCP sockets.
        Default: 1
similarity index 78%
rename from Documentation/networking/net_dim.txt
rename to Documentation/networking/net_dim.rst
index 9bdb7d5a3ba3ae4974a4a5875313707d23476abf..3bed9fd953360d3ceb92f0a74a17fbad2ddd256a 100644 (file)
@@ -1,28 +1,20 @@
+======================================================
 Net DIM - Generic Network Dynamic Interrupt Moderation
 ======================================================
 
-Author:
-       Tal Gilboa <talgi@mellanox.com>
-
-
-Contents
-=========
+:Author: Tal Gilboa <talgi@mellanox.com>
 
-- Assumptions
-- Introduction
-- The Net DIM Algorithm
-- Registering a Network Device to DIM
-- Example
+.. contents:: :depth: 2
 
-Part 0: Assumptions
-======================
+Assumptions
+===========
 
 This document assumes the reader has basic knowledge in network drivers
 and in general interrupt moderation.
 
 
-Part I: Introduction
-======================
+Introduction
+============
 
 Dynamic Interrupt Moderation (DIM) (in networking) refers to changing the
 interrupt moderation configuration of a channel in order to optimize packet
@@ -41,14 +33,15 @@ number of wanted packets per event. The Net DIM algorithm ascribes importance to
 increase bandwidth over reducing interrupt rate.
 
 
-Part II: The Net DIM Algorithm
-===============================
+Net DIM Algorithm
+=================
 
 Each iteration of the Net DIM algorithm follows these steps:
-1. Calculates new data sample.
-2. Compares it to previous sample.
-3. Makes a decision - suggests interrupt moderation configuration fields.
-4. Applies a schedule work function, which applies suggested configuration.
+
+#. Calculates new data sample.
+#. Compares it to previous sample.
+#. Makes a decision - suggests interrupt moderation configuration fields.
+#. Applies a schedule work function, which applies suggested configuration.
 
 The first two steps are straightforward, both the new and the previous data are
 supplied by the driver registered to Net DIM. The previous data is the new data
@@ -89,19 +82,21 @@ manoeuvre as it may provide partial data or ignore the algorithm suggestion
 under some conditions.
 
 
-Part III: Registering a Network Device to DIM
-==============================================
+Registering a Network Device to DIM
+===================================
 
-Net DIM API exposes the main function net_dim(struct dim *dim,
-struct dim_sample end_sample). This function is the entry point to the Net
+Net DIM API exposes the main function net_dim().
+This function is the entry point to the Net
 DIM algorithm and has to be called every time the driver would like to check if
 it should change interrupt moderation parameters. The driver should provide two
-data structures: struct dim and struct dim_sample. Struct dim
+data structures: :c:type:`struct dim <dim>` and
+:c:type:`struct dim_sample <dim_sample>`. :c:type:`struct dim <dim>`
 describes the state of DIM for a specific object (RX queue, TX queue,
 other queues, etc.). This includes the current selected profile, previous data
 samples, the callback function provided by the driver and more.
-Struct dim_sample describes a data sample, which will be compared to the
-data sample stored in struct dim in order to decide on the algorithm's next
+:c:type:`struct dim_sample <dim_sample>` describes a data sample,
+which will be compared to the data sample stored in :c:type:`struct dim <dim>`
+in order to decide on the algorithm's next
 step. The sample should include bytes, packets and interrupts, measured by
 the driver.
 
@@ -110,9 +105,10 @@ main net_dim() function. The recommended method is to call net_dim() on each
 interrupt. Since Net DIM has a built-in moderation and it might decide to skip
 iterations under certain conditions, there is no need to moderate the net_dim()
 calls as well. As mentioned above, the driver needs to provide an object of type
-struct dim to the net_dim() function call. It is advised for each entity
-using Net DIM to hold a struct dim as part of its data structure and use it
-as the main Net DIM API object. The struct dim_sample should hold the latest
+:c:type:`struct dim <dim>` to the net_dim() function call. It is advised for
+each entity using Net DIM to hold a :c:type:`struct dim <dim>` as part of its
+data structure and use it as the main Net DIM API object.
+The :c:type:`struct dim_sample <dim_sample>` should hold the latest
 bytes, packets and interrupts count. No need to perform any calculations, just
 include the raw data.
 
@@ -124,19 +120,19 @@ the data flow. After the work is done, Net DIM algorithm needs to be set to
 the proper state in order to move to the next iteration.
 
 
-Part IV: Example
-=================
+Example
+=======
 
 The following code demonstrates how to register a driver to Net DIM. The actual
 usage is not complete but it should make the outline of the usage clear.
 
-my_driver.c:
+.. code-block:: c
 
-#include <linux/dim.h>
+  #include <linux/dim.h>
 
-/* Callback for net DIM to schedule on a decision to change moderation */
-void my_driver_do_dim_work(struct work_struct *work)
-{
+  /* Callback for net DIM to schedule on a decision to change moderation */
+  void my_driver_do_dim_work(struct work_struct *work)
+  {
        /* Get struct dim from struct work_struct */
        struct dim *dim = container_of(work, struct dim,
                                       work);
@@ -145,11 +141,11 @@ void my_driver_do_dim_work(struct work_struct *work)
 
        /* Signal net DIM work is done and it should move to next iteration */
        dim->state = DIM_START_MEASURE;
-}
+  }
 
-/* My driver's interrupt handler */
-int my_driver_handle_interrupt(struct my_driver_entity *my_entity, ...)
-{
+  /* My driver's interrupt handler */
+  int my_driver_handle_interrupt(struct my_driver_entity *my_entity, ...)
+  {
        ...
        /* A struct to hold current measured data */
        struct dim_sample dim_sample;
@@ -162,13 +158,19 @@ int my_driver_handle_interrupt(struct my_driver_entity *my_entity, ...)
        /* Call net DIM */
        net_dim(&my_entity->dim, dim_sample);
        ...
-}
+  }
 
-/* My entity's initialization function (my_entity was already allocated) */
-int my_driver_init_my_entity(struct my_driver_entity *my_entity, ...)
-{
+  /* My entity's initialization function (my_entity was already allocated) */
+  int my_driver_init_my_entity(struct my_driver_entity *my_entity, ...)
+  {
        ...
        /* Initiate struct work_struct with my driver's callback function */
        INIT_WORK(&my_entity->dim.work, my_driver_do_dim_work);
        ...
-}
+  }
+
+Dynamic Interrupt Moderation (DIM) library API
+==============================================
+
+.. kernel-doc:: include/linux/dim.h
+    :internal:
index dcc252634cf96f09d8f02da4b30afb36b924308a..b6833c7bb474192b1ac78b26ab073c9bfee5ada1 100644 (file)
@@ -28,3 +28,5 @@ KVM
    arm/index
 
    devices/index
+
+   running-nested-guests
diff --git a/Documentation/virt/kvm/running-nested-guests.rst b/Documentation/virt/kvm/running-nested-guests.rst
new file mode 100644 (file)
index 0000000..d0a1fc7
--- /dev/null
@@ -0,0 +1,276 @@
+==============================
+Running nested guests with KVM
+==============================
+
+A nested guest is the ability to run a guest inside another guest (it
+can be KVM-based or a different hypervisor).  The straightforward
+example is a KVM guest that in turn runs on a KVM guest (the rest of
+this document is built on this example)::
+
+              .----------------.  .----------------.
+              |                |  |                |
+              |      L2        |  |      L2        |
+              | (Nested Guest) |  | (Nested Guest) |
+              |                |  |                |
+              |----------------'--'----------------|
+              |                                    |
+              |       L1 (Guest Hypervisor)        |
+              |          KVM (/dev/kvm)            |
+              |                                    |
+      .------------------------------------------------------.
+      |                 L0 (Host Hypervisor)                 |
+      |                    KVM (/dev/kvm)                    |
+      |------------------------------------------------------|
+      |        Hardware (with virtualization extensions)     |
+      '------------------------------------------------------'
+
+Terminology:
+
+- L0 – level-0; the bare metal host, running KVM
+
+- L1 – level-1 guest; a VM running on L0; also called the "guest
+  hypervisor", as it itself is capable of running KVM.
+
+- L2 – level-2 guest; a VM running on L1, this is the "nested guest"
+
+.. note:: The above diagram is modelled after the x86 architecture;
+          s390x, ppc64 and other architectures are likely to have
+          a different design for nesting.
+
+          For example, s390x always has an LPAR (LogicalPARtition)
+          hypervisor running on bare metal, adding another layer and
+          resulting in at least four levels in a nested setup — L0 (bare
+          metal, running the LPAR hypervisor), L1 (host hypervisor), L2
+          (guest hypervisor), L3 (nested guest).
+
+          This document will stick with the three-level terminology (L0,
+          L1, and L2) for all architectures; and will largely focus on
+          x86.
+
+
+Use Cases
+---------
+
+There are several scenarios where nested KVM can be useful, to name a
+few:
+
+- As a developer, you want to test your software on different operating
+  systems (OSes).  Instead of renting multiple VMs from a Cloud
+  Provider, using nested KVM lets you rent a large enough "guest
+  hypervisor" (level-1 guest).  This in turn allows you to create
+  multiple nested guests (level-2 guests), running different OSes, on
+  which you can develop and test your software.
+
+- Live migration of "guest hypervisors" and their nested guests, for
+  load balancing, disaster recovery, etc.
+
+- VM image creation tools (e.g. ``virt-install``,  etc) often run
+  their own VM, and users expect these to work inside a VM.
+
+- Some OSes use virtualization internally for security (e.g. to let
+  applications run safely in isolation).
+
+
+Enabling "nested" (x86)
+-----------------------
+
+From Linux kernel v4.19 onwards, the ``nested`` KVM parameter is enabled
+by default for Intel and AMD.  (Though your Linux distribution might
+override this default.)
+
+In case you are running a Linux kernel older than v4.19, to enable
+nesting, set the ``nested`` KVM module parameter to ``Y`` or ``1``.  To
+persist this setting across reboots, you can add it in a config file, as
+shown below:
+
+1. On the bare metal host (L0), list the kernel modules and ensure that
+   the KVM modules::
+
+    $ lsmod | grep -i kvm
+    kvm_intel             133627  0
+    kvm                   435079  1 kvm_intel
+
+2. Show information for ``kvm_intel`` module::
+
+    $ modinfo kvm_intel | grep -i nested
+    parm:           nested:bool
+
+3. For the nested KVM configuration to persist across reboots, place the
+   below in ``/etc/modprobed/kvm_intel.conf`` (create the file if it
+   doesn't exist)::
+
+    $ cat /etc/modprobe.d/kvm_intel.conf
+    options kvm-intel nested=y
+
+4. Unload and re-load the KVM Intel module::
+
+    $ sudo rmmod kvm-intel
+    $ sudo modprobe kvm-intel
+
+5. Verify if the ``nested`` parameter for KVM is enabled::
+
+    $ cat /sys/module/kvm_intel/parameters/nested
+    Y
+
+For AMD hosts, the process is the same as above, except that the module
+name is ``kvm-amd``.
+
+
+Additional nested-related kernel parameters (x86)
+-------------------------------------------------
+
+If your hardware is sufficiently advanced (Intel Haswell processor or
+higher, which has newer hardware virt extensions), the following
+additional features will also be enabled by default: "Shadow VMCS
+(Virtual Machine Control Structure)", APIC Virtualization on your bare
+metal host (L0).  Parameters for Intel hosts::
+
+    $ cat /sys/module/kvm_intel/parameters/enable_shadow_vmcs
+    Y
+
+    $ cat /sys/module/kvm_intel/parameters/enable_apicv
+    Y
+
+    $ cat /sys/module/kvm_intel/parameters/ept
+    Y
+
+.. note:: If you suspect your L2 (i.e. nested guest) is running slower,
+          ensure the above are enabled (particularly
+          ``enable_shadow_vmcs`` and ``ept``).
+
+
+Starting a nested guest (x86)
+-----------------------------
+
+Once your bare metal host (L0) is configured for nesting, you should be
+able to start an L1 guest with::
+
+    $ qemu-kvm -cpu host [...]
+
+The above will pass through the host CPU's capabilities as-is to the
+gues); or for better live migration compatibility, use a named CPU
+model supported by QEMU. e.g.::
+
+    $ qemu-kvm -cpu Haswell-noTSX-IBRS,vmx=on
+
+then the guest hypervisor will subsequently be capable of running a
+nested guest with accelerated KVM.
+
+
+Enabling "nested" (s390x)
+-------------------------
+
+1. On the host hypervisor (L0), enable the ``nested`` parameter on
+   s390x::
+
+    $ rmmod kvm
+    $ modprobe kvm nested=1
+
+.. note:: On s390x, the kernel parameter ``hpage`` is mutually exclusive
+          with the ``nested`` paramter — i.e. to be able to enable
+          ``nested``, the ``hpage`` parameter *must* be disabled.
+
+2. The guest hypervisor (L1) must be provided with the ``sie`` CPU
+   feature — with QEMU, this can be done by using "host passthrough"
+   (via the command-line ``-cpu host``).
+
+3. Now the KVM module can be loaded in the L1 (guest hypervisor)::
+
+    $ modprobe kvm
+
+
+Live migration with nested KVM
+------------------------------
+
+Migrating an L1 guest, with a  *live* nested guest in it, to another
+bare metal host, works as of Linux kernel 5.3 and QEMU 4.2.0 for
+Intel x86 systems, and even on older versions for s390x.
+
+On AMD systems, once an L1 guest has started an L2 guest, the L1 guest
+should no longer be migrated or saved (refer to QEMU documentation on
+"savevm"/"loadvm") until the L2 guest shuts down.  Attempting to migrate
+or save-and-load an L1 guest while an L2 guest is running will result in
+undefined behavior.  You might see a ``kernel BUG!`` entry in ``dmesg``, a
+kernel 'oops', or an outright kernel panic.  Such a migrated or loaded L1
+guest can no longer be considered stable or secure, and must be restarted.
+Migrating an L1 guest merely configured to support nesting, while not
+actually running L2 guests, is expected to function normally even on AMD
+systems but may fail once guests are started.
+
+Migrating an L2 guest is always expected to succeed, so all the following
+scenarios should work even on AMD systems:
+
+- Migrating a nested guest (L2) to another L1 guest on the *same* bare
+  metal host.
+
+- Migrating a nested guest (L2) to another L1 guest on a *different*
+  bare metal host.
+
+- Migrating a nested guest (L2) to a bare metal host.
+
+Reporting bugs from nested setups
+-----------------------------------
+
+Debugging "nested" problems can involve sifting through log files across
+L0, L1 and L2; this can result in tedious back-n-forth between the bug
+reporter and the bug fixer.
+
+- Mention that you are in a "nested" setup.  If you are running any kind
+  of "nesting" at all, say so.  Unfortunately, this needs to be called
+  out because when reporting bugs, people tend to forget to even
+  *mention* that they're using nested virtualization.
+
+- Ensure you are actually running KVM on KVM.  Sometimes people do not
+  have KVM enabled for their guest hypervisor (L1), which results in
+  them running with pure emulation or what QEMU calls it as "TCG", but
+  they think they're running nested KVM.  Thus confusing "nested Virt"
+  (which could also mean, QEMU on KVM) with "nested KVM" (KVM on KVM).
+
+Information to collect (generic)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following is not an exhaustive list, but a very good starting point:
+
+  - Kernel, libvirt, and QEMU version from L0
+
+  - Kernel, libvirt and QEMU version from L1
+
+  - QEMU command-line of L1 -- when using libvirt, you'll find it here:
+    ``/var/log/libvirt/qemu/instance.log``
+
+  - QEMU command-line of L2 -- as above, when using libvirt, get the
+    complete libvirt-generated QEMU command-line
+
+  - ``cat /sys/cpuinfo`` from L0
+
+  - ``cat /sys/cpuinfo`` from L1
+
+  - ``lscpu`` from L0
+
+  - ``lscpu`` from L1
+
+  - Full ``dmesg`` output from L0
+
+  - Full ``dmesg`` output from L1
+
+x86-specific info to collect
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Both the below commands, ``x86info`` and ``dmidecode``, should be
+available on most Linux distributions with the same name:
+
+  - Output of: ``x86info -a`` from L0
+
+  - Output of: ``x86info -a`` from L1
+
+  - Output of: ``dmidecode`` from L0
+
+  - Output of: ``dmidecode`` from L1
+
+s390x-specific info to collect
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Along with the earlier mentioned generic details, the below is
+also recommended:
+
+  - ``/proc/sysinfo`` from L1; this will also include the info from L0
index fa7ddc0428c871cb57cfcce50960f0f1af639631..5325c71ca877a66615bae86efd34bad3025fce08 100644 (file)
@@ -1399,8 +1399,8 @@ must have read/write permission; CS must be __BOOT_CS and DS, ES, SS
 must be __BOOT_DS; interrupt must be disabled; %rsi must hold the base
 address of the struct boot_params.
 
-EFI Handover Protocol
-=====================
+EFI Handover Protocol (deprecated)
+==================================
 
 This protocol allows boot loaders to defer initialisation to the EFI
 boot stub. The boot loader is required to load the kernel/initrd(s)
@@ -1408,6 +1408,12 @@ from the boot media and jump to the EFI handover protocol entry point
 which is hdr->handover_offset bytes from the beginning of
 startup_{32,64}.
 
+The boot loader MUST respect the kernel's PE/COFF metadata when it comes
+to section alignment, the memory footprint of the executable image beyond
+the size of the file itself, and any other aspect of the PE/COFF header
+that may affect correct operation of the image as a PE/COFF binary in the
+execution context provided by the EFI firmware.
+
 The function prototype for the handover entry point looks like this::
 
     efi_main(void *handle, efi_system_table_t *table, struct boot_params *bp)
@@ -1419,9 +1425,18 @@ UEFI specification. 'bp' is the boot loader-allocated boot params.
 
 The boot loader *must* fill out the following fields in bp::
 
-  - hdr.code32_start
   - hdr.cmd_line_ptr
   - hdr.ramdisk_image (if applicable)
   - hdr.ramdisk_size  (if applicable)
 
 All other fields should be zero.
+
+NOTE: The EFI Handover Protocol is deprecated in favour of the ordinary PE/COFF
+      entry point, combined with the LINUX_EFI_INITRD_MEDIA_GUID based initrd
+      loading protocol (refer to [0] for an example of the bootloader side of
+      this), which removes the need for any knowledge on the part of the EFI
+      bootloader regarding the internal representation of boot_params or any
+      requirements/limitations regarding the placement of the command line
+      and ramdisk in memory, or the placement of the kernel image itself.
+
+[0] https://github.com/u-boot/u-boot/commit/ec80b4735a593961fe701cc3a5d717d4739b0fd0
index e64e5db314976dc9f73107c9bd616aeaa3dd9c70..091ec22c1a23f174ef376bdd953b30096661ff03 100644 (file)
@@ -189,7 +189,7 @@ F:  drivers/net/hamradio/6pack.c
 M:     Johannes Berg <johannes@sipsolutions.net>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
-W:     http://wireless.kernel.org/
+W:     https://wireless.wiki.kernel.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
 F:     Documentation/driver-api/80211/cfg80211.rst
@@ -505,7 +505,7 @@ F:  drivers/hwmon/adm1029.c
 ADM8211 WIRELESS DRIVER
 L:     linux-wireless@vger.kernel.org
 S:     Orphan
-W:     http://wireless.kernel.org/
+W:     https://wireless.wiki.kernel.org/
 F:     drivers/net/wireless/admtek/adm8211.*
 
 ADP1653 FLASH CONTROLLER DRIVER
@@ -570,7 +570,7 @@ F:  Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml
 F:     drivers/input/misc/adxl34x.c
 
 ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
-M:     Stefan Popa <stefan.popa@analog.com>
+M:     Michael Hennerich <michael.hennerich@analog.com>
 S:     Supported
 W:     http://ez.analog.com/community/linux-device-drivers
 F:     Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml
@@ -922,7 +922,7 @@ F:  arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi
 F:     drivers/net/ethernet/amd/xgbe/
 
 ANALOG DEVICES INC AD5686 DRIVER
-M:     Stefan Popa <stefan.popa@analog.com>
+M:     Michael Hennerich <Michael.Hennerich@analog.com>
 L:     linux-pm@vger.kernel.org
 S:     Supported
 W:     http://ez.analog.com/community/linux-device-drivers
@@ -930,7 +930,7 @@ F:  drivers/iio/dac/ad5686*
 F:     drivers/iio/dac/ad5696*
 
 ANALOG DEVICES INC AD5758 DRIVER
-M:     Stefan Popa <stefan.popa@analog.com>
+M:     Michael Hennerich <Michael.Hennerich@analog.com>
 L:     linux-iio@vger.kernel.org
 S:     Supported
 W:     http://ez.analog.com/community/linux-device-drivers
@@ -946,7 +946,7 @@ F:  Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml
 F:     drivers/iio/adc/ad7091r5.c
 
 ANALOG DEVICES INC AD7124 DRIVER
-M:     Stefan Popa <stefan.popa@analog.com>
+M:     Michael Hennerich <Michael.Hennerich@analog.com>
 L:     linux-iio@vger.kernel.org
 S:     Supported
 W:     http://ez.analog.com/community/linux-device-drivers
@@ -970,7 +970,7 @@ F:  Documentation/devicetree/bindings/iio/adc/adi,ad7292.yaml
 F:     drivers/iio/adc/ad7292.c
 
 ANALOG DEVICES INC AD7606 DRIVER
-M:     Stefan Popa <stefan.popa@analog.com>
+M:     Michael Hennerich <Michael.Hennerich@analog.com>
 M:     Beniamin Bia <beniamin.bia@analog.com>
 L:     linux-iio@vger.kernel.org
 S:     Supported
@@ -979,7 +979,7 @@ F:  Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml
 F:     drivers/iio/adc/ad7606.c
 
 ANALOG DEVICES INC AD7768-1 DRIVER
-M:     Stefan Popa <stefan.popa@analog.com>
+M:     Michael Hennerich <Michael.Hennerich@analog.com>
 L:     linux-iio@vger.kernel.org
 S:     Supported
 W:     http://ez.analog.com/community/linux-device-drivers
@@ -1040,7 +1040,7 @@ F:        Documentation/devicetree/bindings/hwmon/adi,adm1177.yaml
 F:     drivers/hwmon/adm1177.c
 
 ANALOG DEVICES INC ADP5061 DRIVER
-M:     Stefan Popa <stefan.popa@analog.com>
+M:     Michael Hennerich <Michael.Hennerich@analog.com>
 L:     linux-pm@vger.kernel.org
 S:     Supported
 W:     http://ez.analog.com/community/linux-device-drivers
@@ -1109,7 +1109,6 @@ F:        drivers/iio/amplifiers/hmc425a.c
 ANALOG DEVICES INC IIO DRIVERS
 M:     Lars-Peter Clausen <lars@metafoo.de>
 M:     Michael Hennerich <Michael.Hennerich@analog.com>
-M:     Stefan Popa <stefan.popa@analog.com>
 S:     Supported
 W:     http://wiki.analog.com/
 W:     http://ez.analog.com/community/linux-device-drivers
@@ -1323,7 +1322,10 @@ ARM INTEGRATOR, VERSATILE AND REALVIEW SUPPORT
 M:     Linus Walleij <linus.walleij@linaro.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-F:     Documentation/devicetree/bindings/arm/arm-boards
+F:     Documentation/devicetree/bindings/arm/arm,integrator.yaml
+F:     Documentation/devicetree/bindings/arm/arm,realview.yaml
+F:     Documentation/devicetree/bindings/arm/arm,versatile.yaml
+F:     Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml
 F:     Documentation/devicetree/bindings/auxdisplay/arm-charlcd.txt
 F:     Documentation/devicetree/bindings/clock/arm,syscon-icst.yaml
 F:     Documentation/devicetree/bindings/i2c/i2c-versatile.txt
@@ -2847,14 +2849,14 @@ M:      Nick Kossifidis <mickflemm@gmail.com>
 M:     Luis Chamberlain <mcgrof@kernel.org>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
-W:     http://wireless.kernel.org/en/users/Drivers/ath5k
+W:     https://wireless.wiki.kernel.org/en/users/Drivers/ath5k
 F:     drivers/net/wireless/ath/ath5k/
 
 ATHEROS ATH6KL WIRELESS DRIVER
 M:     Kalle Valo <kvalo@codeaurora.org>
 L:     linux-wireless@vger.kernel.org
 S:     Supported
-W:     http://wireless.kernel.org/en/users/Drivers/ath6kl
+W:     https://wireless.wiki.kernel.org/en/users/Drivers/ath6kl
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
 F:     drivers/net/wireless/ath/ath6kl/
 
@@ -3017,7 +3019,7 @@ B43 WIRELESS DRIVER
 L:     linux-wireless@vger.kernel.org
 L:     b43-dev@lists.infradead.org
 S:     Odd Fixes
-W:     http://wireless.kernel.org/en/users/Drivers/b43
+W:     https://wireless.wiki.kernel.org/en/users/Drivers/b43
 F:     drivers/net/wireless/broadcom/b43/
 
 B43LEGACY WIRELESS DRIVER
@@ -3025,7 +3027,7 @@ M:        Larry Finger <Larry.Finger@lwfinger.net>
 L:     linux-wireless@vger.kernel.org
 L:     b43-dev@lists.infradead.org
 S:     Maintained
-W:     http://wireless.kernel.org/en/users/Drivers/b43
+W:     https://wireless.wiki.kernel.org/en/users/Drivers/b43
 F:     drivers/net/wireless/broadcom/b43legacy/
 
 BACKLIGHT CLASS/SUBSYSTEM
@@ -3655,7 +3657,7 @@ L:        linux-btrfs@vger.kernel.org
 S:     Maintained
 W:     http://btrfs.wiki.kernel.org/
 Q:     http://patchwork.kernel.org/project/linux-btrfs/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git
 F:     Documentation/filesystems/btrfs.rst
 F:     fs/btrfs/
 F:     include/linux/btrfs*
@@ -3840,7 +3842,7 @@ CARL9170 LINUX COMMUNITY WIRELESS DRIVER
 M:     Christian Lamparter <chunkeey@googlemail.com>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
-W:     http://wireless.kernel.org/en/users/Drivers/carl9170
+W:     https://wireless.wiki.kernel.org/en/users/Drivers/carl9170
 F:     drivers/net/wireless/ath/carl9170/
 
 CAVIUM I2C DRIVER
@@ -3934,11 +3936,9 @@ F:       arch/powerpc/platforms/cell/
 CEPH COMMON CODE (LIBCEPH)
 M:     Ilya Dryomov <idryomov@gmail.com>
 M:     Jeff Layton <jlayton@kernel.org>
-M:     Sage Weil <sage@redhat.com>
 L:     ceph-devel@vger.kernel.org
 S:     Supported
 W:     http://ceph.com/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
 T:     git git://github.com/ceph/ceph-client.git
 F:     include/linux/ceph/
 F:     include/linux/crush/
@@ -3946,12 +3946,10 @@ F:      net/ceph/
 
 CEPH DISTRIBUTED FILE SYSTEM CLIENT (CEPH)
 M:     Jeff Layton <jlayton@kernel.org>
-M:     Sage Weil <sage@redhat.com>
 M:     Ilya Dryomov <idryomov@gmail.com>
 L:     ceph-devel@vger.kernel.org
 S:     Supported
 W:     http://ceph.com/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
 T:     git git://github.com/ceph/ceph-client.git
 F:     Documentation/filesystems/ceph.rst
 F:     fs/ceph/
@@ -5173,6 +5171,7 @@ S:        Maintained
 F:     drivers/soc/fsl/dpio
 
 DPAA2 ETHERNET DRIVER
+M:     Ioana Ciornei <ioana.ciornei@nxp.com>
 M:     Ioana Radulescu <ruxandra.radulescu@nxp.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
@@ -5552,7 +5551,7 @@ M:        Chen-Yu Tsai <wens@csie.org>
 L:     dri-devel@lists.freedesktop.org
 S:     Supported
 T:     git git://anongit.freedesktop.org/drm/drm-misc
-F:     Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+F:     Documentation/devicetree/bindings/display/allwinner*
 F:     drivers/gpu/drm/sun4i/
 
 DRM DRIVERS FOR AMLOGIC SOCS
@@ -5932,6 +5931,7 @@ F:        lib/dynamic_debug.c
 DYNAMIC INTERRUPT MODERATION
 M:     Tal Gilboa <talgi@mellanox.com>
 S:     Maintained
+F:     Documentation/networking/net_dim.rst
 F:     include/linux/dim.h
 F:     lib/dim/
 
@@ -7115,9 +7115,10 @@ F:       include/uapi/asm-generic/
 
 GENERIC PHY FRAMEWORK
 M:     Kishon Vijay Abraham I <kishon@ti.com>
+M:     Vinod Koul <vkoul@kernel.org>
 L:     linux-kernel@vger.kernel.org
 S:     Supported
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy.git
 F:     Documentation/devicetree/bindings/phy/
 F:     drivers/phy/
 F:     include/linux/phy/
@@ -7742,11 +7743,6 @@ L:       platform-driver-x86@vger.kernel.org
 S:     Orphan
 F:     drivers/platform/x86/tc1100-wmi.c
 
-HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series
-M:     Jaroslav Kysela <perex@perex.cz>
-S:     Obsolete
-F:     drivers/staging/hp/hp100.*
-
 HPET:  High Precision Event Timers driver
 M:     Clemens Ladisch <clemens@ladisch.de>
 S:     Maintained
@@ -9325,6 +9321,7 @@ M:        Christian Borntraeger <borntraeger@de.ibm.com>
 M:     Janosch Frank <frankja@linux.ibm.com>
 R:     David Hildenbrand <david@redhat.com>
 R:     Cornelia Huck <cohuck@redhat.com>
+R:     Claudio Imbrenda <imbrenda@linux.ibm.com>
 L:     kvm@vger.kernel.org
 S:     Supported
 W:     http://www.ibm.com/developerworks/linux/linux390/
@@ -9412,6 +9409,13 @@ F:       include/linux/keyctl.h
 F:     include/uapi/linux/keyctl.h
 F:     security/keys/
 
+KFIFO
+M:     Stefani Seibold <stefani@seibold.net>
+S:     Maintained
+F:     include/linux/kfifo.h
+F:     lib/kfifo.c
+F:     samples/kfifo/
+
 KGDB / KDB /debug_core
 M:     Jason Wessel <jason.wessel@windriver.com>
 M:     Daniel Thompson <daniel.thompson@linaro.org>
@@ -10063,7 +10067,7 @@ MAC80211
 M:     Johannes Berg <johannes@sipsolutions.net>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
-W:     http://wireless.kernel.org/
+W:     https://wireless.wiki.kernel.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
 F:     Documentation/networking/mac80211-injection.txt
@@ -10693,7 +10697,6 @@ MEDIATEK MT76 WIRELESS LAN DRIVER
 M:     Felix Fietkau <nbd@nbd.name>
 M:     Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
 R:     Ryder Lee <ryder.lee@mediatek.com>
-R:     Roy Luo <royluo@google.com>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
 F:     drivers/net/wireless/mediatek/mt76/
@@ -12644,7 +12647,7 @@ F:      fs/orangefs/
 ORINOCO DRIVER
 L:     linux-wireless@vger.kernel.org
 S:     Orphan
-W:     http://wireless.kernel.org/en/users/Drivers/orinoco
+W:     https://wireless.wiki.kernel.org/en/users/Drivers/orinoco
 W:     http://www.nongnu.org/orinoco/
 F:     drivers/net/wireless/intersil/orinoco/
 
@@ -12670,7 +12673,7 @@ P54 WIRELESS DRIVER
 M:     Christian Lamparter <chunkeey@googlemail.com>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
-W:     http://wireless.kernel.org/en/users/Drivers/p54
+W:     https://wireless.wiki.kernel.org/en/users/Drivers/p54
 F:     drivers/net/wireless/intersil/p54/
 
 PACKING
@@ -13038,7 +13041,7 @@ F:      drivers/pci/controller/pci-xgene-msi.c
 
 PCI NATIVE HOST BRIDGE AND ENDPOINT DRIVERS
 M:     Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-R:     Andrew Murray <amurray@thegoodpenguin.co.uk>
+R:     Rob Herring <robh@kernel.org>
 L:     linux-pci@vger.kernel.org
 S:     Supported
 Q:     http://patchwork.ozlabs.org/project/linux-pci/list/
@@ -13591,7 +13594,7 @@ PRISM54 WIRELESS DRIVER
 M:     Luis Chamberlain <mcgrof@kernel.org>
 L:     linux-wireless@vger.kernel.org
 S:     Obsolete
-W:     http://wireless.kernel.org/en/users/Drivers/p54
+W:     https://wireless.wiki.kernel.org/en/users/Drivers/p54
 F:     drivers/net/wireless/intersil/prism54/
 
 PROC FILESYSTEM
@@ -13853,7 +13856,8 @@ S:      Maintained
 F:     drivers/scsi/qla1280.[ch]
 
 QLOGIC QLA2XXX FC-SCSI DRIVER
-M:     hmadhani@marvell.com
+M:     Nilesh Javali <njavali@marvell.com>
+M:     GR-QLogic-Storage-Upstream@marvell.com
 L:     linux-scsi@vger.kernel.org
 S:     Supported
 F:     Documentation/scsi/LICENSE.qla2xxx
@@ -13931,7 +13935,7 @@ QUALCOMM ATHEROS ATH10K WIRELESS DRIVER
 M:     Kalle Valo <kvalo@codeaurora.org>
 L:     ath10k@lists.infradead.org
 S:     Supported
-W:     http://wireless.kernel.org/en/users/Drivers/ath10k
+W:     https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
 F:     drivers/net/wireless/ath/ath10k/
 
@@ -13946,7 +13950,7 @@ QUALCOMM ATHEROS ATH9K WIRELESS DRIVER
 M:     QCA ath9k Development <ath9k-devel@qca.qualcomm.com>
 L:     linux-wireless@vger.kernel.org
 S:     Supported
-W:     http://wireless.kernel.org/en/users/Drivers/ath9k
+W:     https://wireless.wiki.kernel.org/en/users/Drivers/ath9k
 F:     drivers/net/wireless/ath/ath9k/
 
 QUALCOMM CAMERA SUBSYSTEM DRIVER
@@ -14043,13 +14047,12 @@ QUALCOMM WCN36XX WIRELESS DRIVER
 M:     Kalle Valo <kvalo@codeaurora.org>
 L:     wcn36xx@lists.infradead.org
 S:     Supported
-W:     http://wireless.kernel.org/en/users/Drivers/wcn36xx
+W:     https://wireless.wiki.kernel.org/en/users/Drivers/wcn36xx
 T:     git git://github.com/KrasnikovEugene/wcn36xx.git
 F:     drivers/net/wireless/ath/wcn36xx/
 
 QUANTENNA QTNFMAC WIRELESS DRIVER
 M:     Igor Mitsyanko <imitsyanko@quantenna.com>
-M:     Avinash Patil <avinashp@quantenna.com>
 M:     Sergey Matyukevich <smatyukevich@quantenna.com>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
@@ -14091,12 +14094,10 @@ F:    drivers/media/radio/radio-tea5777.c
 
 RADOS BLOCK DEVICE (RBD)
 M:     Ilya Dryomov <idryomov@gmail.com>
-M:     Sage Weil <sage@redhat.com>
 R:     Dongsheng Yang <dongsheng.yang@easystack.cn>
 L:     ceph-devel@vger.kernel.org
 S:     Supported
 W:     http://ceph.com/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
 T:     git git://github.com/ceph/ceph-client.git
 F:     Documentation/ABI/testing/sysfs-bus-rbd
 F:     drivers/block/rbd.c
@@ -14271,7 +14272,7 @@ REALTEK WIRELESS DRIVER (rtlwifi family)
 M:     Ping-Ke Shih <pkshih@realtek.com>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
-W:     http://wireless.kernel.org/
+W:     https://wireless.wiki.kernel.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
 F:     drivers/net/wireless/realtek/rtlwifi/
 
@@ -14406,7 +14407,7 @@ RFKILL
 M:     Johannes Berg <johannes@sipsolutions.net>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
-W:     http://wireless.kernel.org/
+W:     https://wireless.wiki.kernel.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
 F:     Documentation/ABI/stable/sysfs-class-rfkill
@@ -14555,7 +14556,7 @@ F:      drivers/media/dvb-frontends/rtl2832_sdr*
 RTL8180 WIRELESS DRIVER
 L:     linux-wireless@vger.kernel.org
 S:     Orphan
-W:     http://wireless.kernel.org/
+W:     https://wireless.wiki.kernel.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
 F:     drivers/net/wireless/realtek/rtl818x/rtl8180/
 
@@ -14565,7 +14566,7 @@ M:      Hin-Tak Leung <htl10@users.sourceforge.net>
 M:     Larry Finger <Larry.Finger@lwfinger.net>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
-W:     http://wireless.kernel.org/
+W:     https://wireless.wiki.kernel.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
 F:     drivers/net/wireless/realtek/rtl818x/rtl8187/
 
@@ -16920,8 +16921,8 @@ F:      drivers/media/platform/ti-vpe/
 TI WILINK WIRELESS DRIVERS
 L:     linux-wireless@vger.kernel.org
 S:     Orphan
-W:     http://wireless.kernel.org/en/users/Drivers/wl12xx
-W:     http://wireless.kernel.org/en/users/Drivers/wl1251
+W:     https://wireless.wiki.kernel.org/en/users/Drivers/wl12xx
+W:     https://wireless.wiki.kernel.org/en/users/Drivers/wl1251
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
 F:     drivers/net/wireless/ti/
 F:     include/linux/wl12xx.h
@@ -18203,7 +18204,7 @@ M:      Maya Erez <merez@codeaurora.org>
 L:     linux-wireless@vger.kernel.org
 L:     wil6210@qti.qualcomm.com
 S:     Supported
-W:     http://wireless.kernel.org/en/users/Drivers/wil6210
+W:     https://wireless.wiki.kernel.org/en/users/Drivers/wil6210
 F:     drivers/net/wireless/ath/wil6210/
 
 WIMAX STACK
index 70def4907036c7c0adfd73fc863ec972cc078e32..11fe9b1535de529e994b861a1bab1675f3348d34 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 7
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc5
 NAME = Kleptomaniac Octopus
 
 # *DOCUMENTATION*
@@ -729,10 +729,6 @@ else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
 KBUILD_CFLAGS += -Os
 endif
 
-ifdef CONFIG_CC_DISABLE_WARN_MAYBE_UNINITIALIZED
-KBUILD_CFLAGS   += -Wno-maybe-uninitialized
-endif
-
 # Tell gcc to never replace conditional load with a non-conditional one
 KBUILD_CFLAGS  += $(call cc-option,--param=allow-store-data-races=0)
 KBUILD_CFLAGS  += $(call cc-option,-fno-allow-store-data-races)
@@ -881,6 +877,17 @@ KBUILD_CFLAGS += -Wno-pointer-sign
 # disable stringop warnings in gcc 8+
 KBUILD_CFLAGS += $(call cc-disable-warning, stringop-truncation)
 
+# We'll want to enable this eventually, but it's not going away for 5.7 at least
+KBUILD_CFLAGS += $(call cc-disable-warning, zero-length-bounds)
+KBUILD_CFLAGS += $(call cc-disable-warning, array-bounds)
+KBUILD_CFLAGS += $(call cc-disable-warning, stringop-overflow)
+
+# Another good warning that we'll want to enable eventually
+KBUILD_CFLAGS += $(call cc-disable-warning, restrict)
+
+# Enabled with W=2, disabled by default as noisy
+KBUILD_CFLAGS += $(call cc-disable-warning, maybe-uninitialized)
+
 # disable invalid "can't wrap" optimizations for signed / pointers
 KBUILD_CFLAGS  += $(call cc-option,-fno-strict-overflow)
 
index 48f13a4ace4b3fcb07d5cbaf5e64e72ac359fcfa..f534a1fef070fb13ed0e94ebf2768d51158759ae 100644 (file)
@@ -3,7 +3,6 @@
  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  *
  * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
-
  */
 
 #ifndef _ASM_ARC_MODULE_H
@@ -19,8 +18,4 @@ struct mod_arch_specific {
        const char *secstr;
 };
 
-#define MODULE_PROC_FAMILY "ARC700"
-
-#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
-
 #endif /* _ASM_ARC_MODULE_H */
diff --git a/arch/arc/include/asm/vermagic.h b/arch/arc/include/asm/vermagic.h
new file mode 100644 (file)
index 0000000..a10257d
--- /dev/null
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _ASM_VERMAGIC_H
+#define _ASM_VERMAGIC_H
+
+#define MODULE_ARCH_VERMAGIC "ARC700"
+
+#endif /* _ASM_VERMAGIC_H */
index cabdd8f4a2482e2b2362794b3071173c87431b3a..e8e1c866e413a287924656851a202f1c480613b7 100644 (file)
@@ -1450,7 +1450,8 @@ ENTRY(efi_enter_kernel)
                @ running beyond the PoU, and so calling cache_off below from
                @ inside the PE/COFF loader allocated region is unsafe unless
                @ we explicitly clean it to the PoC.
-               adr     r0, call_cache_fn               @ region of code we will
+ ARM(          adrl    r0, call_cache_fn       )
+ THUMB(                adr     r0, call_cache_fn       )       @ region of code we will
                adr     r1, 0f                          @ run with MMU off
                bl      cache_clean_flush
                bl      cache_off
index fd2c766e0f7108973b771660e368d66cef3a5bc4..f7ae5a4530b8807e4ad3f6b90c7c8205bcd9b2c2 100644 (file)
@@ -14,6 +14,9 @@
        soc {
                firmware: firmware {
                        compatible = "raspberrypi,bcm2835-firmware", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
                        mboxes = <&mailbox>;
                        dma-ranges;
                };
index e1abe8c730cefca16e942eb5f89a16d4f8cad45d..b83a864e2e8ba1a8326cadce40bfd6cac15830a2 100644 (file)
                                             "dsi0_ddr2",
                                             "dsi0_ddr";
 
+                       status = "disabled";
                };
 
                aux: aux@7e215000 {
index 47982889d7747a6e37f0e92db187ac7b77efa66a..98da446aa0f27ceb994264f684004d2cc39bcaef 100644 (file)
                                compatible = "fsl,imx6q-fec";
                                reg = <0x02188000 0x4000>;
                                interrupt-names = "int0", "pps";
-                               interrupts-extended =
-                                       <&intc 0 118 IRQ_TYPE_LEVEL_HIGH>,
-                                       <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 119 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6QDL_CLK_ENET>,
                                         <&clks IMX6QDL_CLK_ENET>,
                                         <&clks IMX6QDL_CLK_ENET_REF>;
                                clock-names = "ipg", "ahb", "ptp";
+                               gpr = <&gpr>;
                                status = "disabled";
                        };
 
index 93b89dc1f53b5b20c1044ceead90f821b112c2fb..b310f13a53f22eb6c59ab2d3ca21b2803b5d7921 100644 (file)
@@ -77,7 +77,6 @@
 };
 
 &fec {
-       /delete-property/interrupts-extended;
        interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>,
                     <0 119 IRQ_TYPE_LEVEL_HIGH>;
 };
index a075b63f3087d110a709d3dbfbe3186e513dfb4e..11d41e86f814d26e42249d9ff96ea4c0745d3955 100644 (file)
        status = "disabled";
 };
 
+/* RNG not directly accessible on N950/N9. */
+&rng_target {
+       status = "disabled";
+};
+
 &usb_otg_hs {
        interface-type = <0>;
        usb-phy = <&usb2_phy>;
index 6fdb0ac62b3d85076824ecbb93eae1139bd79a57..59da6c0b63b62bc0e6015fa1b1ccfc8d74e8b9d6 100644 (file)
@@ -91,9 +91,17 @@ void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src, unsigned int bytes,
                return;
        }
 
-       kernel_neon_begin();
-       chacha_doneon(state, dst, src, bytes, nrounds);
-       kernel_neon_end();
+       do {
+               unsigned int todo = min_t(unsigned int, bytes, SZ_4K);
+
+               kernel_neon_begin();
+               chacha_doneon(state, dst, src, todo, nrounds);
+               kernel_neon_end();
+
+               bytes -= todo;
+               src += todo;
+               dst += todo;
+       } while (bytes);
 }
 EXPORT_SYMBOL(chacha_crypt_arch);
 
index ae5aefc44a4d766531118102f1f836394e4a7b12..ffa8d73fe722c231720e86d3d6aeb91ab283754b 100644 (file)
@@ -30,7 +30,7 @@ static int nhpoly1305_neon_update(struct shash_desc *desc,
                return crypto_nhpoly1305_update(desc, src, srclen);
 
        do {
-               unsigned int n = min_t(unsigned int, srclen, PAGE_SIZE);
+               unsigned int n = min_t(unsigned int, srclen, SZ_4K);
 
                kernel_neon_begin();
                crypto_nhpoly1305_update_helper(desc, src, n, _nh_neon);
index ceec04ec2f4054eed9f2d8eea12dd87ce0585e72..13cfef4ae22e312dcb9f6b032f9d5c6bfbb27ee9 100644 (file)
@@ -160,13 +160,20 @@ void poly1305_update_arch(struct poly1305_desc_ctx *dctx, const u8 *src,
                unsigned int len = round_down(nbytes, POLY1305_BLOCK_SIZE);
 
                if (static_branch_likely(&have_neon) && do_neon) {
-                       kernel_neon_begin();
-                       poly1305_blocks_neon(&dctx->h, src, len, 1);
-                       kernel_neon_end();
+                       do {
+                               unsigned int todo = min_t(unsigned int, len, SZ_4K);
+
+                               kernel_neon_begin();
+                               poly1305_blocks_neon(&dctx->h, src, todo, 1);
+                               kernel_neon_end();
+
+                               len -= todo;
+                               src += todo;
+                       } while (len);
                } else {
                        poly1305_blocks_arm(&dctx->h, src, len, 1);
+                       src += len;
                }
-               src += len;
                nbytes %= POLY1305_BLOCK_SIZE;
        }
 
index e133da303a988b6235f4f60be24025c91f7af340..a9151884bc85976231178b2612422f0d5a8cc03d 100644 (file)
@@ -165,8 +165,13 @@ arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
        preempt_enable();
 #endif
 
-       if (!ret)
-               *oval = oldval;
+       /*
+        * Store unconditionally. If ret != 0 the extra store is the least
+        * of the worries but GCC cannot figure out that __futex_atomic_op()
+        * is either setting ret to -EFAULT or storing the old value in
+        * oldval which results in a uninitialized warning at the call site.
+        */
+       *oval = oldval;
 
        return ret;
 }
index 182163b55546c973767ad8687b6ee4e362465b70..4b0df09cbe678dc5aa33e97a46972c9de40fef72 100644 (file)
@@ -37,30 +37,6 @@ struct mod_arch_specific {
 struct module;
 u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val);
 
-/*
- * Add the ARM architecture version to the version magic string
- */
-#define MODULE_ARCH_VERMAGIC_ARMVSN "ARMv" __stringify(__LINUX_ARM_ARCH__) " "
-
-/* Add __virt_to_phys patching state as well */
-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
-#define MODULE_ARCH_VERMAGIC_P2V "p2v8 "
-#else
-#define MODULE_ARCH_VERMAGIC_P2V ""
-#endif
-
-/* Add instruction set architecture tag to distinguish ARM/Thumb kernels */
-#ifdef CONFIG_THUMB2_KERNEL
-#define MODULE_ARCH_VERMAGIC_ARMTHUMB "thumb2 "
-#else
-#define MODULE_ARCH_VERMAGIC_ARMTHUMB ""
-#endif
-
-#define MODULE_ARCH_VERMAGIC \
-       MODULE_ARCH_VERMAGIC_ARMVSN \
-       MODULE_ARCH_VERMAGIC_ARMTHUMB \
-       MODULE_ARCH_VERMAGIC_P2V
-
 #ifdef CONFIG_THUMB2_KERNEL
 #define HAVE_ARCH_KALLSYMS_SYMBOL_VALUE
 static inline unsigned long kallsyms_symbol_value(const Elf_Sym *sym)
diff --git a/arch/arm/include/asm/vermagic.h b/arch/arm/include/asm/vermagic.h
new file mode 100644 (file)
index 0000000..62ce94e
--- /dev/null
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_VERMAGIC_H
+#define _ASM_VERMAGIC_H
+
+#include <linux/stringify.h>
+
+/*
+ * Add the ARM architecture version to the version magic string
+ */
+#define MODULE_ARCH_VERMAGIC_ARMVSN "ARMv" __stringify(__LINUX_ARM_ARCH__) " "
+
+/* Add __virt_to_phys patching state as well */
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
+#define MODULE_ARCH_VERMAGIC_P2V "p2v8 "
+#else
+#define MODULE_ARCH_VERMAGIC_P2V ""
+#endif
+
+/* Add instruction set architecture tag to distinguish ARM/Thumb kernels */
+#ifdef CONFIG_THUMB2_KERNEL
+#define MODULE_ARCH_VERMAGIC_ARMTHUMB "thumb2 "
+#else
+#define MODULE_ARCH_VERMAGIC_ARMTHUMB ""
+#endif
+
+#define MODULE_ARCH_VERMAGIC \
+       MODULE_ARCH_VERMAGIC_ARMVSN \
+       MODULE_ARCH_VERMAGIC_ARMTHUMB \
+       MODULE_ARCH_VERMAGIC_P2V
+
+#endif /* _ASM_VERMAGIC_H */
index 03506ce4614934675e772cce4a74386ead086fae..e7364e6c8c6b0229186c434ef78cba884ddb251b 100644 (file)
@@ -91,8 +91,10 @@ AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a
 obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o
 obj-$(CONFIG_SOC_IMX53) += suspend-imx53.o
 endif
+ifeq ($(CONFIG_ARM_CPU_SUSPEND),y)
 AFLAGS_resume-imx6.o :=-Wa,-march=armv7-a
 obj-$(CONFIG_SOC_IMX6) += resume-imx6.o
+endif
 obj-$(CONFIG_SOC_IMX6) += pm-imx6.o
 
 obj-$(CONFIG_SOC_IMX1) += mach-imx1.o
index cc29869d12a3ecb7bbb1fd4212355963b654952b..bf85d6db493158499f172c3e2730c8b2d339ec2f 100644 (file)
@@ -929,7 +929,11 @@ static inline void emit_a32_rsh_i64(const s8 dst[],
        rd = arm_bpf_get_reg64(dst, tmp, ctx);
 
        /* Do LSR operation */
-       if (val < 32) {
+       if (val == 0) {
+               /* An immediate value of 0 encodes a shift amount of 32
+                * for LSR. To shift by 0, don't do anything.
+                */
+       } else if (val < 32) {
                emit(ARM_MOV_SI(tmp2[1], rd[1], SRTYPE_LSR, val), ctx);
                emit(ARM_ORR_SI(rd[1], tmp2[1], rd[0], SRTYPE_ASL, 32 - val), ctx);
                emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_LSR, val), ctx);
@@ -955,7 +959,11 @@ static inline void emit_a32_arsh_i64(const s8 dst[],
        rd = arm_bpf_get_reg64(dst, tmp, ctx);
 
        /* Do ARSH operation */
-       if (val < 32) {
+       if (val == 0) {
+               /* An immediate value of 0 encodes a shift amount of 32
+                * for ASR. To shift by 0, don't do anything.
+                */
+       } else if (val < 32) {
                emit(ARM_MOV_SI(tmp2[1], rd[1], SRTYPE_LSR, val), ctx);
                emit(ARM_ORR_SI(rd[1], tmp2[1], rd[0], SRTYPE_ASL, 32 - val), ctx);
                emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_ASR, val), ctx);
@@ -992,21 +1000,35 @@ static inline void emit_a32_mul_r64(const s8 dst[], const s8 src[],
        arm_bpf_put_reg32(dst_hi, rd[0], ctx);
 }
 
+static bool is_ldst_imm(s16 off, const u8 size)
+{
+       s16 off_max = 0;
+
+       switch (size) {
+       case BPF_B:
+       case BPF_W:
+               off_max = 0xfff;
+               break;
+       case BPF_H:
+               off_max = 0xff;
+               break;
+       case BPF_DW:
+               /* Need to make sure off+4 does not overflow. */
+               off_max = 0xfff - 4;
+               break;
+       }
+       return -off_max <= off && off <= off_max;
+}
+
 /* *(size *)(dst + off) = src */
 static inline void emit_str_r(const s8 dst, const s8 src[],
-                             s32 off, struct jit_ctx *ctx, const u8 sz){
+                             s16 off, struct jit_ctx *ctx, const u8 sz){
        const s8 *tmp = bpf2a32[TMP_REG_1];
-       s32 off_max;
        s8 rd;
 
        rd = arm_bpf_get_reg32(dst, tmp[1], ctx);
 
-       if (sz == BPF_H)
-               off_max = 0xff;
-       else
-               off_max = 0xfff;
-
-       if (off < 0 || off > off_max) {
+       if (!is_ldst_imm(off, sz)) {
                emit_a32_mov_i(tmp[0], off, ctx);
                emit(ARM_ADD_R(tmp[0], tmp[0], rd), ctx);
                rd = tmp[0];
@@ -1035,18 +1057,12 @@ static inline void emit_str_r(const s8 dst, const s8 src[],
 
 /* dst = *(size*)(src + off) */
 static inline void emit_ldx_r(const s8 dst[], const s8 src,
-                             s32 off, struct jit_ctx *ctx, const u8 sz){
+                             s16 off, struct jit_ctx *ctx, const u8 sz){
        const s8 *tmp = bpf2a32[TMP_REG_1];
        const s8 *rd = is_stacked(dst_lo) ? tmp : dst;
        s8 rm = src;
-       s32 off_max;
-
-       if (sz == BPF_H)
-               off_max = 0xff;
-       else
-               off_max = 0xfff;
 
-       if (off < 0 || off > off_max) {
+       if (!is_ldst_imm(off, sz)) {
                emit_a32_mov_i(tmp[0], off, ctx);
                emit(ARM_ADD_R(tmp[0], tmp[0], src), ctx);
                rm = tmp[0];
index dd6804a64f1a041935e80919678be6c8f22594e6..fd4e1ce1daf96ae57aa70c84305781325252ec94 100644 (file)
@@ -36,7 +36,7 @@
 
 #include <linux/mm.h>
 
-struct start_info _xen_start_info;
+static struct start_info _xen_start_info;
 struct start_info *xen_start_info = &_xen_start_info;
 EXPORT_SYMBOL(xen_start_info);
 
index 37ca3e8898484572d37ae0222cf13100c4dce952..af2bbca38e70fb3514bf594cafffbf907c8eeffa 100644 (file)
@@ -87,9 +87,17 @@ void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src, unsigned int bytes,
            !crypto_simd_usable())
                return chacha_crypt_generic(state, dst, src, bytes, nrounds);
 
-       kernel_neon_begin();
-       chacha_doneon(state, dst, src, bytes, nrounds);
-       kernel_neon_end();
+       do {
+               unsigned int todo = min_t(unsigned int, bytes, SZ_4K);
+
+               kernel_neon_begin();
+               chacha_doneon(state, dst, src, todo, nrounds);
+               kernel_neon_end();
+
+               bytes -= todo;
+               src += todo;
+               dst += todo;
+       } while (bytes);
 }
 EXPORT_SYMBOL(chacha_crypt_arch);
 
index 895d3727c1fbcf3691293d5bf700623068a149c7..c5405e6a6db76f7cbbbccda47cc3a116c1c11e45 100644 (file)
@@ -30,7 +30,7 @@ static int nhpoly1305_neon_update(struct shash_desc *desc,
                return crypto_nhpoly1305_update(desc, src, srclen);
 
        do {
-               unsigned int n = min_t(unsigned int, srclen, PAGE_SIZE);
+               unsigned int n = min_t(unsigned int, srclen, SZ_4K);
 
                kernel_neon_begin();
                crypto_nhpoly1305_update_helper(desc, src, n, _nh_neon);
index e97b092f56b8fcae5531be3db610737b22f7a057..f33ada70c4ed8f84171b202e3f447880e0e7696f 100644 (file)
@@ -143,13 +143,20 @@ void poly1305_update_arch(struct poly1305_desc_ctx *dctx, const u8 *src,
                unsigned int len = round_down(nbytes, POLY1305_BLOCK_SIZE);
 
                if (static_branch_likely(&have_neon) && crypto_simd_usable()) {
-                       kernel_neon_begin();
-                       poly1305_blocks_neon(&dctx->h, src, len, 1);
-                       kernel_neon_end();
+                       do {
+                               unsigned int todo = min_t(unsigned int, len, SZ_4K);
+
+                               kernel_neon_begin();
+                               poly1305_blocks_neon(&dctx->h, src, todo, 1);
+                               kernel_neon_end();
+
+                               len -= todo;
+                               src += todo;
+                       } while (len);
                } else {
                        poly1305_blocks(&dctx->h, src, len, 1);
+                       src += len;
                }
-               src += len;
                nbytes %= POLY1305_BLOCK_SIZE;
        }
 
index 1e93de68c04418851dd0ab33d5406a9e759b565c..4e7fa2623896b008afb775c2cd4d41f7a72491c5 100644 (file)
@@ -7,8 +7,6 @@
 
 #include <asm-generic/module.h>
 
-#define MODULE_ARCH_VERMAGIC   "aarch64"
-
 #ifdef CONFIG_ARM64_MODULE_PLTS
 struct mod_plt_sec {
        int                     plt_shndx;
index 70c47156e54b1791b268fc768166e574ce01625b..c6b4f0603024332948677b9ec9606d201ac32b28 100644 (file)
@@ -47,7 +47,7 @@ static inline void ptrauth_keys_init_user(struct ptrauth_keys_user *keys)
                get_random_bytes(&keys->apga, sizeof(keys->apga));
 }
 
-#define __ptrauth_key_install(k, v)                            \
+#define __ptrauth_key_install_nosync(k, v)                     \
 do {                                                           \
        struct ptrauth_key __pki_v = (v);                       \
        write_sysreg_s(__pki_v.lo, SYS_ ## k ## KEYLO_EL1);     \
@@ -62,8 +62,11 @@ static __always_inline void ptrauth_keys_init_kernel(struct ptrauth_keys_kernel
 
 static __always_inline void ptrauth_keys_switch_kernel(struct ptrauth_keys_kernel *keys)
 {
-       if (system_supports_address_auth())
-               __ptrauth_key_install(APIA, keys->apia);
+       if (!system_supports_address_auth())
+               return;
+
+       __ptrauth_key_install_nosync(APIA, keys->apia);
+       isb();
 }
 
 extern int ptrauth_prctl_reset_keys(struct task_struct *tsk, unsigned long arg);
index ebc62243283186169d504a05982fe4797f3ead9c..c4ac0ac25a00809bb36d45adcfcd00e5ff369eca 100644 (file)
@@ -49,7 +49,9 @@
 #ifndef CONFIG_BROKEN_GAS_INST
 
 #ifdef __ASSEMBLY__
-#define __emit_inst(x)                 .inst (x)
+// The space separator is omitted so that __emit_inst(x) can be parsed as
+// either an assembler directive or an assembler macro argument.
+#define __emit_inst(x)                 .inst(x)
 #else
 #define __emit_inst(x)                 ".inst " __stringify((x)) "\n\t"
 #endif
diff --git a/arch/arm64/include/asm/vermagic.h b/arch/arm64/include/asm/vermagic.h
new file mode 100644 (file)
index 0000000..a1eec6a
--- /dev/null
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ */
+#ifndef _ASM_VERMAGIC_H
+#define _ASM_VERMAGIC_H
+
+#define MODULE_ARCH_VERMAGIC   "aarch64"
+
+#endif /* _ASM_VERMAGIC_H */
index 354b11e27c07af0ea52787ad6dfcde6f9e3aa9fa..033a48f30dbb801a58dfe64998fe102eb663aecc 100644 (file)
@@ -260,18 +260,7 @@ static int __aarch32_alloc_vdso_pages(void)
        if (ret)
                return ret;
 
-       ret = aarch32_alloc_kuser_vdso_page();
-       if (ret) {
-               unsigned long c_vvar =
-                       (unsigned long)page_to_virt(aarch32_vdso_pages[C_VVAR]);
-               unsigned long c_vdso =
-                       (unsigned long)page_to_virt(aarch32_vdso_pages[C_VDSO]);
-
-               free_page(c_vvar);
-               free_page(c_vdso);
-       }
-
-       return ret;
+       return aarch32_alloc_kuser_vdso_page();
 }
 #else
 static int __aarch32_alloc_vdso_pages(void)
index dd2514bb1511fe4fa72271bb9af38564c4fe5607..3862cad2410cfab14a3d028882b7e856cffb344f 100644 (file)
@@ -32,7 +32,7 @@ UBSAN_SANITIZE                        := n
 OBJECT_FILES_NON_STANDARD      := y
 KCOV_INSTRUMENT                        := n
 
-CFLAGS_vgettimeofday.o = -O2 -mcmodel=tiny
+CFLAGS_vgettimeofday.o = -O2 -mcmodel=tiny -fasynchronous-unwind-tables
 
 ifneq ($(c-gettimeofday-y),)
   CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y)
index 23ebe51410f06a3435915bddaa98b688209d0819..50a279d3ddd783ad751fefa4790b26aeb4adcfdb 100644 (file)
@@ -200,6 +200,13 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
        }
 
        memcpy((u32 *)regs + off, valp, KVM_REG_SIZE(reg->id));
+
+       if (*vcpu_cpsr(vcpu) & PSR_MODE32_BIT) {
+               int i;
+
+               for (i = 0; i < 16; i++)
+                       *vcpu_reg32(vcpu, i) = (u32)*vcpu_reg32(vcpu, i);
+       }
 out:
        return err;
 }
index d22d0534dd600e24651e9e067894f0ddf88824e6..90186cf6473e0223ab965b24d5df0d1f7e677a5f 100644 (file)
@@ -18,6 +18,7 @@
 
 #define CPU_GP_REG_OFFSET(x)   (CPU_GP_REGS + x)
 #define CPU_XREG_OFFSET(x)     CPU_GP_REG_OFFSET(CPU_USER_PT_REGS + 8*x)
+#define CPU_SP_EL0_OFFSET      (CPU_XREG_OFFSET(30) + 8)
 
        .text
        .pushsection    .hyp.text, "ax"
        ldp     x29, lr,  [\ctxt, #CPU_XREG_OFFSET(29)]
 .endm
 
+.macro save_sp_el0 ctxt, tmp
+       mrs     \tmp,   sp_el0
+       str     \tmp,   [\ctxt, #CPU_SP_EL0_OFFSET]
+.endm
+
+.macro restore_sp_el0 ctxt, tmp
+       ldr     \tmp,     [\ctxt, #CPU_SP_EL0_OFFSET]
+       msr     sp_el0, \tmp
+.endm
+
 /*
  * u64 __guest_enter(struct kvm_vcpu *vcpu,
  *                  struct kvm_cpu_context *host_ctxt);
@@ -60,6 +71,9 @@ SYM_FUNC_START(__guest_enter)
        // Store the host regs
        save_callee_saved_regs x1
 
+       // Save the host's sp_el0
+       save_sp_el0     x1, x2
+
        // Now the host state is stored if we have a pending RAS SError it must
        // affect the host. If any asynchronous exception is pending we defer
        // the guest entry. The DSB isn't necessary before v8.2 as any SError
@@ -83,6 +97,9 @@ alternative_else_nop_endif
        // when this feature is enabled for kernel code.
        ptrauth_switch_to_guest x29, x0, x1, x2
 
+       // Restore the guest's sp_el0
+       restore_sp_el0 x29, x0
+
        // Restore guest regs x0-x17
        ldp     x0, x1,   [x29, #CPU_XREG_OFFSET(0)]
        ldp     x2, x3,   [x29, #CPU_XREG_OFFSET(2)]
@@ -130,6 +147,9 @@ SYM_INNER_LABEL(__guest_exit, SYM_L_GLOBAL)
        // Store the guest regs x18-x29, lr
        save_callee_saved_regs x1
 
+       // Store the guest's sp_el0
+       save_sp_el0     x1, x2
+
        get_host_ctxt   x2, x3
 
        // Macro ptrauth_switch_to_guest format:
@@ -139,6 +159,9 @@ SYM_INNER_LABEL(__guest_exit, SYM_L_GLOBAL)
        // when this feature is enabled for kernel code.
        ptrauth_switch_to_host x1, x2, x3, x4, x5
 
+       // Restore the hosts's sp_el0
+       restore_sp_el0 x2, x3
+
        // Now restore the host regs
        restore_callee_saved_regs x2
 
index c2a13ab3c471241012188b80aac24298cd4cd186..9c5cfb04170ee531c2f3e3fd80a8ab77f6fe4174 100644 (file)
@@ -198,7 +198,6 @@ SYM_CODE_END(__hyp_panic)
 .macro invalid_vector  label, target = __hyp_panic
        .align  2
 SYM_CODE_START(\label)
-\label:
        b \target
 SYM_CODE_END(\label)
 .endm
index 75b1925763f16ef89ede0c53c4eea9e567bc234a..6d2df9fe0b5d2dcc2e1c9b98229079da666c0c50 100644 (file)
@@ -15,8 +15,9 @@
 /*
  * Non-VHE: Both host and guest must save everything.
  *
- * VHE: Host and guest must save mdscr_el1 and sp_el0 (and the PC and pstate,
- * which are handled as part of the el2 return state) on every switch.
+ * VHE: Host and guest must save mdscr_el1 and sp_el0 (and the PC and
+ * pstate, which are handled as part of the el2 return state) on every
+ * switch (sp_el0 is being dealt with in the assembly code).
  * tpidr_el0 and tpidrro_el0 only need to be switched when going
  * to host userspace or a different VCPU.  EL1 registers only need to be
  * switched when potentially going to run a different VCPU.  The latter two
 static void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt)
 {
        ctxt->sys_regs[MDSCR_EL1]       = read_sysreg(mdscr_el1);
-
-       /*
-        * The host arm64 Linux uses sp_el0 to point to 'current' and it must
-        * therefore be saved/restored on every entry/exit to/from the guest.
-        */
-       ctxt->gp_regs.regs.sp           = read_sysreg(sp_el0);
 }
 
 static void __hyp_text __sysreg_save_user_state(struct kvm_cpu_context *ctxt)
@@ -99,12 +94,6 @@ NOKPROBE_SYMBOL(sysreg_save_guest_state_vhe);
 static void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctxt)
 {
        write_sysreg(ctxt->sys_regs[MDSCR_EL1],   mdscr_el1);
-
-       /*
-        * The host arm64 Linux uses sp_el0 to point to 'current' and it must
-        * therefore be saved/restored on every entry/exit to/from the guest.
-        */
-       write_sysreg(ctxt->gp_regs.regs.sp,       sp_el0);
 }
 
 static void __hyp_text __sysreg_restore_user_state(struct kvm_cpu_context *ctxt)
index bbeb6a5a6ba6dea94c69e85413ec94534bd3985f..0be3355e34997544aa43cd652c733a996b9e3ff6 100644 (file)
@@ -230,6 +230,8 @@ pte_t *huge_pte_alloc(struct mm_struct *mm,
                ptep = (pte_t *)pudp;
        } else if (sz == (CONT_PTE_SIZE)) {
                pmdp = pmd_alloc(mm, pudp, addr);
+               if (!pmdp)
+                       return NULL;
 
                WARN_ON(addr & (sz - 1));
                /*
diff --git a/arch/h8300/kernel/.gitignore b/arch/h8300/kernel/.gitignore
new file mode 100644 (file)
index 0000000..bbb90f9
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+vmlinux.lds
similarity index 64%
rename from arch/hexagon/include/asm/module.h
rename to arch/hexagon/include/asm/vermagic.h
index e8de4fe035438ed9ed20c6b01588175b6fd75cce..0e8dedc8c486dec4f7cd9255c0e0232960b65dca 100644 (file)
@@ -3,11 +3,11 @@
  * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  */
 
-#ifndef _ASM_MODULE_H
-#define _ASM_MODULE_H
+#ifndef _ASM_VERMAGIC_H
+#define _ASM_VERMAGIC_H
 
-#include <asm-generic/module.h>
+#include <linux/stringify.h>
 
 #define MODULE_ARCH_VERMAGIC __stringify(PROCESSOR_MODEL_NAME) " "
 
-#endif
+#endif /* _ASM_VERMAGIC_H */
index f319144260ce13fcb316e1d0b40715f9a6f427b2..5a29652e6defcb2885591b00c72086cee28d8372 100644 (file)
@@ -26,10 +26,6 @@ struct mod_arch_specific {
        unsigned int next_got_entry;    /* index of next available got entry */
 };
 
-#define MODULE_PROC_FAMILY     "ia64"
-#define MODULE_ARCH_VERMAGIC   MODULE_PROC_FAMILY \
-       "gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__)
-
 #define ARCH_SHF_SMALL SHF_IA_64_SHORT
 
 #endif /* _ASM_IA64_MODULE_H */
diff --git a/arch/ia64/include/asm/vermagic.h b/arch/ia64/include/asm/vermagic.h
new file mode 100644 (file)
index 0000000..29c7424
--- /dev/null
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2003 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#ifndef _ASM_VERMAGIC_H
+#define _ASM_VERMAGIC_H
+
+#include <linux/stringify.h>
+
+#define MODULE_ARCH_VERMAGIC   "ia64" \
+       "gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__)
+
+#endif /* _ASM_VERMAGIC_H */
index a0765aa60ea9aa8dc069387aaece1b3c6a1a24fa..1bff55aa2d54e2ce8dd312da3c7f8d426a78540f 100644 (file)
@@ -1,7 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 generated-y += syscall_table.h
 generic-y += extable.h
-generic-y += hardirq.h
 generic-y += kvm_para.h
 generic-y += local64.h
 generic-y += mcs_spinlock.h
index 9846047b3d3d31e303d2927e7c2b275ac562a945..724a0882576b3cf1760ff8811be45ae69778b84e 100644 (file)
@@ -83,65 +83,4 @@ search_module_dbetables(unsigned long addr)
 }
 #endif
 
-#ifdef CONFIG_CPU_BMIPS
-#define MODULE_PROC_FAMILY "BMIPS "
-#elif defined CONFIG_CPU_MIPS32_R1
-#define MODULE_PROC_FAMILY "MIPS32_R1 "
-#elif defined CONFIG_CPU_MIPS32_R2
-#define MODULE_PROC_FAMILY "MIPS32_R2 "
-#elif defined CONFIG_CPU_MIPS32_R6
-#define MODULE_PROC_FAMILY "MIPS32_R6 "
-#elif defined CONFIG_CPU_MIPS64_R1
-#define MODULE_PROC_FAMILY "MIPS64_R1 "
-#elif defined CONFIG_CPU_MIPS64_R2
-#define MODULE_PROC_FAMILY "MIPS64_R2 "
-#elif defined CONFIG_CPU_MIPS64_R6
-#define MODULE_PROC_FAMILY "MIPS64_R6 "
-#elif defined CONFIG_CPU_R3000
-#define MODULE_PROC_FAMILY "R3000 "
-#elif defined CONFIG_CPU_TX39XX
-#define MODULE_PROC_FAMILY "TX39XX "
-#elif defined CONFIG_CPU_VR41XX
-#define MODULE_PROC_FAMILY "VR41XX "
-#elif defined CONFIG_CPU_R4X00
-#define MODULE_PROC_FAMILY "R4X00 "
-#elif defined CONFIG_CPU_TX49XX
-#define MODULE_PROC_FAMILY "TX49XX "
-#elif defined CONFIG_CPU_R5000
-#define MODULE_PROC_FAMILY "R5000 "
-#elif defined CONFIG_CPU_R5500
-#define MODULE_PROC_FAMILY "R5500 "
-#elif defined CONFIG_CPU_NEVADA
-#define MODULE_PROC_FAMILY "NEVADA "
-#elif defined CONFIG_CPU_R10000
-#define MODULE_PROC_FAMILY "R10000 "
-#elif defined CONFIG_CPU_RM7000
-#define MODULE_PROC_FAMILY "RM7000 "
-#elif defined CONFIG_CPU_SB1
-#define MODULE_PROC_FAMILY "SB1 "
-#elif defined CONFIG_CPU_LOONGSON32
-#define MODULE_PROC_FAMILY "LOONGSON32 "
-#elif defined CONFIG_CPU_LOONGSON2EF
-#define MODULE_PROC_FAMILY "LOONGSON2EF "
-#elif defined CONFIG_CPU_LOONGSON64
-#define MODULE_PROC_FAMILY "LOONGSON64 "
-#elif defined CONFIG_CPU_CAVIUM_OCTEON
-#define MODULE_PROC_FAMILY "OCTEON "
-#elif defined CONFIG_CPU_XLR
-#define MODULE_PROC_FAMILY "XLR "
-#elif defined CONFIG_CPU_XLP
-#define MODULE_PROC_FAMILY "XLP "
-#else
-#error MODULE_PROC_FAMILY undefined for your processor configuration
-#endif
-
-#ifdef CONFIG_32BIT
-#define MODULE_KERNEL_TYPE "32BIT "
-#elif defined CONFIG_64BIT
-#define MODULE_KERNEL_TYPE "64BIT "
-#endif
-
-#define MODULE_ARCH_VERMAGIC \
-       MODULE_PROC_FAMILY MODULE_KERNEL_TYPE
-
 #endif /* _ASM_MODULE_H */
diff --git a/arch/mips/include/asm/vermagic.h b/arch/mips/include/asm/vermagic.h
new file mode 100644 (file)
index 0000000..24dc3d3
--- /dev/null
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_VERMAGIC_H
+#define _ASM_VERMAGIC_H
+
+#ifdef CONFIG_CPU_BMIPS
+#define MODULE_PROC_FAMILY "BMIPS "
+#elif defined CONFIG_CPU_MIPS32_R1
+#define MODULE_PROC_FAMILY "MIPS32_R1 "
+#elif defined CONFIG_CPU_MIPS32_R2
+#define MODULE_PROC_FAMILY "MIPS32_R2 "
+#elif defined CONFIG_CPU_MIPS32_R6
+#define MODULE_PROC_FAMILY "MIPS32_R6 "
+#elif defined CONFIG_CPU_MIPS64_R1
+#define MODULE_PROC_FAMILY "MIPS64_R1 "
+#elif defined CONFIG_CPU_MIPS64_R2
+#define MODULE_PROC_FAMILY "MIPS64_R2 "
+#elif defined CONFIG_CPU_MIPS64_R6
+#define MODULE_PROC_FAMILY "MIPS64_R6 "
+#elif defined CONFIG_CPU_R3000
+#define MODULE_PROC_FAMILY "R3000 "
+#elif defined CONFIG_CPU_TX39XX
+#define MODULE_PROC_FAMILY "TX39XX "
+#elif defined CONFIG_CPU_VR41XX
+#define MODULE_PROC_FAMILY "VR41XX "
+#elif defined CONFIG_CPU_R4X00
+#define MODULE_PROC_FAMILY "R4X00 "
+#elif defined CONFIG_CPU_TX49XX
+#define MODULE_PROC_FAMILY "TX49XX "
+#elif defined CONFIG_CPU_R5000
+#define MODULE_PROC_FAMILY "R5000 "
+#elif defined CONFIG_CPU_R5500
+#define MODULE_PROC_FAMILY "R5500 "
+#elif defined CONFIG_CPU_NEVADA
+#define MODULE_PROC_FAMILY "NEVADA "
+#elif defined CONFIG_CPU_R10000
+#define MODULE_PROC_FAMILY "R10000 "
+#elif defined CONFIG_CPU_RM7000
+#define MODULE_PROC_FAMILY "RM7000 "
+#elif defined CONFIG_CPU_SB1
+#define MODULE_PROC_FAMILY "SB1 "
+#elif defined CONFIG_CPU_LOONGSON32
+#define MODULE_PROC_FAMILY "LOONGSON32 "
+#elif defined CONFIG_CPU_LOONGSON2EF
+#define MODULE_PROC_FAMILY "LOONGSON2EF "
+#elif defined CONFIG_CPU_LOONGSON64
+#define MODULE_PROC_FAMILY "LOONGSON64 "
+#elif defined CONFIG_CPU_CAVIUM_OCTEON
+#define MODULE_PROC_FAMILY "OCTEON "
+#elif defined CONFIG_CPU_XLR
+#define MODULE_PROC_FAMILY "XLR "
+#elif defined CONFIG_CPU_XLP
+#define MODULE_PROC_FAMILY "XLP "
+#else
+#error MODULE_PROC_FAMILY undefined for your processor configuration
+#endif
+
+#ifdef CONFIG_32BIT
+#define MODULE_KERNEL_TYPE "32BIT "
+#elif defined CONFIG_64BIT
+#define MODULE_KERNEL_TYPE "64BIT "
+#endif
+
+#define MODULE_ARCH_VERMAGIC \
+       MODULE_PROC_FAMILY MODULE_KERNEL_TYPE
+
+#endif /* _ASM_VERMAGIC_H */
similarity index 52%
rename from arch/nds32/include/asm/module.h
rename to arch/nds32/include/asm/vermagic.h
index a3a08e993c65924cb3537bb3848701a15e4b33b7..f772e7ba33f1fa71674c9c5584ed532843f9f8a9 100644 (file)
@@ -1,11 +1,9 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 // Copyright (C) 2005-2017 Andes Technology Corporation
 
-#ifndef _ASM_NDS32_MODULE_H
-#define _ASM_NDS32_MODULE_H
-
-#include <asm-generic/module.h>
+#ifndef _ASM_VERMAGIC_H
+#define _ASM_VERMAGIC_H
 
 #define MODULE_ARCH_VERMAGIC   "NDS32v3"
 
-#endif /* _ASM_NDS32_MODULE_H */
+#endif /* _ASM_VERMAGIC_H */
index 356658711a864e0587aead0ebd7c5f9e030cda02..5398bfc465b4859e2641569272daa72b758a74ed 100644 (file)
@@ -3,28 +3,10 @@
 #define _ASM_POWERPC_MODULE_H
 #ifdef __KERNEL__
 
-/*
- */
-
 #include <linux/list.h>
 #include <asm/bug.h>
 #include <asm-generic/module.h>
 
-
-#ifdef CONFIG_MPROFILE_KERNEL
-#define MODULE_ARCH_VERMAGIC_FTRACE    "mprofile-kernel "
-#else
-#define MODULE_ARCH_VERMAGIC_FTRACE    ""
-#endif
-
-#ifdef CONFIG_RELOCATABLE
-#define MODULE_ARCH_VERMAGIC_RELOCATABLE       "relocatable "
-#else
-#define MODULE_ARCH_VERMAGIC_RELOCATABLE       ""
-#endif
-
-#define MODULE_ARCH_VERMAGIC MODULE_ARCH_VERMAGIC_FTRACE MODULE_ARCH_VERMAGIC_RELOCATABLE
-
 #ifndef __powerpc64__
 /*
  * Thanks to Paul M for explaining this.
diff --git a/arch/powerpc/include/asm/vermagic.h b/arch/powerpc/include/asm/vermagic.h
new file mode 100644 (file)
index 0000000..b054a85
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_VERMAGIC_H
+#define _ASM_VERMAGIC_H
+
+#ifdef CONFIG_MPROFILE_KERNEL
+#define MODULE_ARCH_VERMAGIC_FTRACE    "mprofile-kernel "
+#else
+#define MODULE_ARCH_VERMAGIC_FTRACE    ""
+#endif
+
+#ifdef CONFIG_RELOCATABLE
+#define MODULE_ARCH_VERMAGIC_RELOCATABLE       "relocatable "
+#else
+#define MODULE_ARCH_VERMAGIC_RELOCATABLE       ""
+#endif
+
+#define MODULE_ARCH_VERMAGIC \
+               MODULE_ARCH_VERMAGIC_FTRACE MODULE_ARCH_VERMAGIC_RELOCATABLE
+
+#endif /* _ASM_VERMAGIC_H */
index a6371fb8f7612caec0111171bbf23d90b7efee39..8420abd4ea1ce8bf7400bf3b68389bc85ff562ea 100644 (file)
@@ -732,7 +732,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_SPE)
        stw     r10,_CCR(r1)
        stw     r1,KSP(r3)      /* Set old stack pointer */
 
-       kuap_check r2, r4
+       kuap_check r2, r0
 #ifdef CONFIG_SMP
        /* We need a sync somewhere here to make sure that if the
         * previous task gets rescheduled on another CPU, it sees all
index 438a9befce4159e53f27de6c136d7ccdd3533dba..8105010b0e76fb179f7939a5d41ce534f4b9c87d 100644 (file)
@@ -534,6 +534,8 @@ static bool __init parse_cache_info(struct device_node *np,
        lsizep = of_get_property(np, propnames[3], NULL);
        if (bsizep == NULL)
                bsizep = lsizep;
+       if (lsizep == NULL)
+               lsizep = bsizep;
        if (lsizep != NULL)
                lsize = be32_to_cpu(*lsizep);
        if (bsizep != NULL)
index 6404df613ea36a0783609b45df72fde12cf9c7ed..2b35f9bcf8928f8404d4b9781bcbb2d6c2503b62 100644 (file)
@@ -604,18 +604,19 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
         */
        local_irq_disable();
        ptep = __find_linux_pte(vcpu->arch.pgdir, hva, NULL, &shift);
+       pte = __pte(0);
+       if (ptep)
+               pte = *ptep;
+       local_irq_enable();
        /*
         * If the PTE disappeared temporarily due to a THP
         * collapse, just return and let the guest try again.
         */
-       if (!ptep) {
-               local_irq_enable();
+       if (!pte_present(pte)) {
                if (page)
                        put_page(page);
                return RESUME_GUEST;
        }
-       pte = *ptep;
-       local_irq_enable();
        hpa = pte_pfn(pte) << PAGE_SHIFT;
        pte_size = PAGE_SIZE;
        if (shift)
index 9f050064d2a2d7523ff0d89222d7bc6e8f3f2bc3..aa12cd4078b3205e85d4cdf2d8746229377bd937 100644 (file)
@@ -815,18 +815,19 @@ int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu,
         */
        local_irq_disable();
        ptep = __find_linux_pte(vcpu->arch.pgdir, hva, NULL, &shift);
+       pte = __pte(0);
+       if (ptep)
+               pte = *ptep;
+       local_irq_enable();
        /*
         * If the PTE disappeared temporarily due to a THP
         * collapse, just return and let the guest try again.
         */
-       if (!ptep) {
-               local_irq_enable();
+       if (!pte_present(pte)) {
                if (page)
                        put_page(page);
                return RESUME_GUEST;
        }
-       pte = *ptep;
-       local_irq_enable();
 
        /* If we're logging dirty pages, always map single pages */
        large_enable = !(memslot->flags & KVM_MEM_LOG_DIRTY_PAGES);
index e15166b0a16db0fc805e1c1193e81bf83ee73d94..ad2f172c26a6c61100c7fc104fbbc75ae5177042 100644 (file)
@@ -521,6 +521,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_IOEVENTFD:
        case KVM_CAP_DEVICE_CTRL:
        case KVM_CAP_IMMEDIATE_EXIT:
+       case KVM_CAP_SET_GUEST_DEBUG:
                r = 1;
                break;
        case KVM_CAP_PPC_GUEST_DEBUG_SSTEP:
index 3189308dece4c9a09b5f32d332a307945679ce62..d83a12c5bc7f4343d154f60dabb73c8cfa519442 100644 (file)
@@ -185,6 +185,7 @@ void mmu_mark_initmem_nx(void)
                        mmu_mapin_ram_chunk(etext8, einittext8, PAGE_KERNEL);
                }
        }
+       _tlbil_all();
 }
 
 #ifdef CONFIG_STRICT_KERNEL_RWX
@@ -199,6 +200,8 @@ void mmu_mark_rodata_ro(void)
                                      ~(LARGE_PAGE_SIZE_8M - 1)));
        mmu_patch_addis(&patch__dtlbmiss_romem_top, -__pa(_sinittext));
 
+       _tlbil_all();
+
        /* Update page tables for PTDUMP and BDI */
        mmu_mapin_ram_chunk(0, sinittext, __pgprot(0));
        mmu_mapin_ram_chunk(0, etext, PAGE_KERNEL_ROX);
index 0c3c1902135c4f430e076e50213e6eefc9552521..27a81c291be8403e3b3c8f851e168fb9b96a648e 100644 (file)
@@ -397,7 +397,7 @@ config PPC_KUAP
 
 config PPC_KUAP_DEBUG
        bool "Extra debugging for Kernel Userspace Access Protection"
-       depends on PPC_KUAP && (PPC_RADIX_MMU || PPC_32)
+       depends on PPC_KUAP && (PPC_RADIX_MMU || PPC32)
        help
          Add extra debugging for Kernel Userspace Access Protection (KUAP)
          If you're unsure, say N.
index a197258595ef6e025429182e8529b5f8084f05c8..74f82cf4f7816b99fc54155fd40dcf4d40cbf956 100644 (file)
@@ -55,12 +55,12 @@ config RISCV
        select ARCH_HAS_PTE_SPECIAL
        select ARCH_HAS_MMIOWB
        select ARCH_HAS_DEBUG_VIRTUAL
-       select HAVE_EBPF_JIT
+       select HAVE_EBPF_JIT if MMU
        select EDAC_SUPPORT
        select ARCH_HAS_GIGANTIC_PAGE
        select ARCH_HAS_SET_DIRECT_MAP
        select ARCH_HAS_SET_MEMORY
-       select ARCH_HAS_STRICT_KERNEL_RWX
+       select ARCH_HAS_STRICT_KERNEL_RWX if MMU
        select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
        select SPARSEMEM_STATIC if 32BIT
        select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
index 8e18d2c64399df91e0619852bfd5c9a4757cdc37..cec462e198ced58c82ecf530115fb079d06b03b1 100644 (file)
 #define CAUSE_IRQ_FLAG         (_AC(1, UL) << (__riscv_xlen - 1))
 
 /* Interrupt causes (minus the high bit) */
-#define IRQ_U_SOFT             0
 #define IRQ_S_SOFT             1
 #define IRQ_M_SOFT             3
-#define IRQ_U_TIMER            4
 #define IRQ_S_TIMER            5
 #define IRQ_M_TIMER            7
-#define IRQ_U_EXT              8
 #define IRQ_S_EXT              9
 #define IRQ_M_EXT              11
 
index 1bb0cd04aec386d5462f7a2eb0f8cd3dbb36c467..5ce50468aff13f0af68bf7a615944bb0e8b7e341 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef _ASM_RISCV_HWCAP_H
 #define _ASM_RISCV_HWCAP_H
 
+#include <linux/bits.h>
 #include <uapi/asm/hwcap.h>
 
 #ifndef __ASSEMBLY__
@@ -22,6 +23,27 @@ enum {
 };
 
 extern unsigned long elf_hwcap;
+
+#define RISCV_ISA_EXT_a                ('a' - 'a')
+#define RISCV_ISA_EXT_c                ('c' - 'a')
+#define RISCV_ISA_EXT_d                ('d' - 'a')
+#define RISCV_ISA_EXT_f                ('f' - 'a')
+#define RISCV_ISA_EXT_h                ('h' - 'a')
+#define RISCV_ISA_EXT_i                ('i' - 'a')
+#define RISCV_ISA_EXT_m                ('m' - 'a')
+#define RISCV_ISA_EXT_s                ('s' - 'a')
+#define RISCV_ISA_EXT_u                ('u' - 'a')
+
+#define RISCV_ISA_EXT_MAX      64
+
+unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
+
+#define riscv_isa_extension_mask(ext) BIT_MASK(RISCV_ISA_EXT_##ext)
+
+bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit);
+#define riscv_isa_extension_available(isa_bitmap, ext) \
+       __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
+
 #endif
 
 #endif /* _ASM_RISCV_HWCAP_H */
index 46202dad365d0631175998eec030194354cd4d57..76aa96a9fc08165783566100155776862b780ad9 100644 (file)
@@ -6,8 +6,6 @@
 
 #include <asm-generic/module.h>
 
-#define MODULE_ARCH_VERMAGIC    "riscv"
-
 struct module;
 unsigned long module_emit_got_entry(struct module *mod, unsigned long val);
 unsigned long module_emit_plt_entry(struct module *mod, unsigned long val);
index c38df4771c095d1c03dba34d6c51bdf4dac374c2..4c5bae7ca01c8ab1b03634658894200b4a8d70bf 100644 (file)
@@ -22,14 +22,6 @@ static inline int set_memory_x(unsigned long addr, int numpages) { return 0; }
 static inline int set_memory_nx(unsigned long addr, int numpages) { return 0; }
 #endif
 
-#ifdef CONFIG_STRICT_KERNEL_RWX
-void set_kernel_text_ro(void);
-void set_kernel_text_rw(void);
-#else
-static inline void set_kernel_text_ro(void) { }
-static inline void set_kernel_text_rw(void) { }
-#endif
-
 int set_direct_map_invalid_noflush(struct page *page);
 int set_direct_map_default_noflush(struct page *page);
 
diff --git a/arch/riscv/include/asm/vermagic.h b/arch/riscv/include/asm/vermagic.h
new file mode 100644 (file)
index 0000000..7b9441a
--- /dev/null
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2017 Andes Technology Corporation */
+
+#ifndef _ASM_VERMAGIC_H
+#define _ASM_VERMAGIC_H
+
+#define MODULE_ARCH_VERMAGIC    "riscv"
+
+#endif /* _ASM_VERMAGIC_H */
index c4c33bf02369740cb2e653b4c81b1119b5fad43a..0ec22354018ce33481ff39caa3b224d36d50ee12 100644 (file)
@@ -15,8 +15,8 @@
 
 const struct cpu_operations *cpu_ops[NR_CPUS] __ro_after_init;
 
-void *__cpu_up_stack_pointer[NR_CPUS];
-void *__cpu_up_task_pointer[NR_CPUS];
+void *__cpu_up_stack_pointer[NR_CPUS] __section(.data);
+void *__cpu_up_task_pointer[NR_CPUS] __section(.data);
 
 extern const struct cpu_operations cpu_ops_sbi;
 extern const struct cpu_operations cpu_ops_spinwait;
index a5ad00043104d3c16275f271649af64755c8de0e..ac202f44a67024291c0afda96b2568c3d004f75e 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) 2017 SiFive
  */
 
+#include <linux/bitmap.h>
 #include <linux/of.h>
 #include <asm/processor.h>
 #include <asm/hwcap.h>
 #include <asm/switch_to.h>
 
 unsigned long elf_hwcap __read_mostly;
+
+/* Host ISA bitmap */
+static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly;
+
 #ifdef CONFIG_FPU
 bool has_fpu __read_mostly;
 #endif
 
+/**
+ * riscv_isa_extension_base() - Get base extension word
+ *
+ * @isa_bitmap: ISA bitmap to use
+ * Return: base extension word as unsigned long value
+ *
+ * NOTE: If isa_bitmap is NULL then Host ISA bitmap will be used.
+ */
+unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap)
+{
+       if (!isa_bitmap)
+               return riscv_isa[0];
+       return isa_bitmap[0];
+}
+EXPORT_SYMBOL_GPL(riscv_isa_extension_base);
+
+/**
+ * __riscv_isa_extension_available() - Check whether given extension
+ * is available or not
+ *
+ * @isa_bitmap: ISA bitmap to use
+ * @bit: bit position of the desired extension
+ * Return: true or false
+ *
+ * NOTE: If isa_bitmap is NULL then Host ISA bitmap will be used.
+ */
+bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit)
+{
+       const unsigned long *bmap = (isa_bitmap) ? isa_bitmap : riscv_isa;
+
+       if (bit >= RISCV_ISA_EXT_MAX)
+               return false;
+
+       return test_bit(bit, bmap) ? true : false;
+}
+EXPORT_SYMBOL_GPL(__riscv_isa_extension_available);
+
 void riscv_fill_hwcap(void)
 {
        struct device_node *node;
        const char *isa;
-       size_t i;
+       char print_str[BITS_PER_LONG + 1];
+       size_t i, j, isa_len;
        static unsigned long isa2hwcap[256] = {0};
 
        isa2hwcap['i'] = isa2hwcap['I'] = COMPAT_HWCAP_ISA_I;
@@ -33,8 +76,11 @@ void riscv_fill_hwcap(void)
 
        elf_hwcap = 0;
 
+       bitmap_zero(riscv_isa, RISCV_ISA_EXT_MAX);
+
        for_each_of_cpu_node(node) {
                unsigned long this_hwcap = 0;
+               unsigned long this_isa = 0;
 
                if (riscv_of_processor_hartid(node) < 0)
                        continue;
@@ -44,8 +90,24 @@ void riscv_fill_hwcap(void)
                        continue;
                }
 
-               for (i = 0; i < strlen(isa); ++i)
+               i = 0;
+               isa_len = strlen(isa);
+#if IS_ENABLED(CONFIG_32BIT)
+               if (!strncmp(isa, "rv32", 4))
+                       i += 4;
+#elif IS_ENABLED(CONFIG_64BIT)
+               if (!strncmp(isa, "rv64", 4))
+                       i += 4;
+#endif
+               for (; i < isa_len; ++i) {
                        this_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
+                       /*
+                        * TODO: X, Y and Z extension parsing for Host ISA
+                        * bitmap will be added in-future.
+                        */
+                       if ('a' <= isa[i] && isa[i] < 'x')
+                               this_isa |= (1UL << (isa[i] - 'a'));
+               }
 
                /*
                 * All "okay" hart should have same isa. Set HWCAP based on
@@ -56,6 +118,11 @@ void riscv_fill_hwcap(void)
                        elf_hwcap &= this_hwcap;
                else
                        elf_hwcap = this_hwcap;
+
+               if (riscv_isa[0])
+                       riscv_isa[0] &= this_isa;
+               else
+                       riscv_isa[0] = this_isa;
        }
 
        /* We don't support systems with F but without D, so mask those out
@@ -65,7 +132,17 @@ void riscv_fill_hwcap(void)
                elf_hwcap &= ~COMPAT_HWCAP_ISA_F;
        }
 
-       pr_info("elf_hwcap is 0x%lx\n", elf_hwcap);
+       memset(print_str, 0, sizeof(print_str));
+       for (i = 0, j = 0; i < BITS_PER_LONG; i++)
+               if (riscv_isa[0] & BIT_MASK(i))
+                       print_str[j++] = (char)('a' + i);
+       pr_info("riscv: ISA extensions %s\n", print_str);
+
+       memset(print_str, 0, sizeof(print_str));
+       for (i = 0, j = 0; i < BITS_PER_LONG; i++)
+               if (elf_hwcap & BIT_MASK(i))
+                       print_str[j++] = (char)('a' + i);
+       pr_info("riscv: ELF capabilities %s\n", print_str);
 
 #ifdef CONFIG_FPU
        if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
index 7c24da59bccf619ee4b5c3725290a68c6f531440..f383ef5672b20f1a43c90a33aa06d955f34d5482 100644 (file)
@@ -102,7 +102,7 @@ void sbi_shutdown(void)
 {
        sbi_ecall(SBI_EXT_0_1_SHUTDOWN, 0, 0, 0, 0, 0, 0, 0);
 }
-EXPORT_SYMBOL(sbi_set_timer);
+EXPORT_SYMBOL(sbi_shutdown);
 
 /**
  * sbi_clear_ipi() - Clear any pending IPIs for the calling hart.
@@ -113,7 +113,7 @@ void sbi_clear_ipi(void)
 {
        sbi_ecall(SBI_EXT_0_1_CLEAR_IPI, 0, 0, 0, 0, 0, 0, 0);
 }
-EXPORT_SYMBOL(sbi_shutdown);
+EXPORT_SYMBOL(sbi_clear_ipi);
 
 /**
  * sbi_set_timer_v01() - Program the timer for next timer event.
@@ -167,6 +167,11 @@ static int __sbi_rfence_v01(int fid, const unsigned long *hart_mask,
 
        return result;
 }
+
+static void sbi_set_power_off(void)
+{
+       pm_power_off = sbi_shutdown;
+}
 #else
 static void __sbi_set_timer_v01(uint64_t stime_value)
 {
@@ -191,6 +196,8 @@ static int __sbi_rfence_v01(int fid, const unsigned long *hart_mask,
 
        return 0;
 }
+
+static void sbi_set_power_off(void) {}
 #endif /* CONFIG_RISCV_SBI_V01 */
 
 static void __sbi_set_timer_v02(uint64_t stime_value)
@@ -540,16 +547,12 @@ static inline long sbi_get_firmware_version(void)
        return __sbi_base_ecall(SBI_EXT_BASE_GET_IMP_VERSION);
 }
 
-static void sbi_power_off(void)
-{
-       sbi_shutdown();
-}
 
 int __init sbi_init(void)
 {
        int ret;
 
-       pm_power_off = sbi_power_off;
+       sbi_set_power_off();
        ret = sbi_get_spec_version();
        if (ret > 0)
                sbi_spec_version = ret;
index e0a6293093f12ad51919842de90d47030547eea8..a65a8fa0c22d690f600afd5404bd519d48034808 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 #include <linux/profile.h>
 #include <linux/smp.h>
 #include <linux/sched.h>
@@ -63,6 +64,7 @@ void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out)
        for_each_cpu(cpu, in)
                cpumask_set_cpu(cpuid_to_hartid_map(cpu), out);
 }
+EXPORT_SYMBOL_GPL(riscv_cpuid_to_hartid_mask);
 
 bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
 {
index 02087fe539c61514b6e276029231e717b31126b6..6c854875ac74c6c0bed1dd0abfbe466697c074e7 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/stacktrace.h>
 #include <linux/ftrace.h>
 
+register unsigned long sp_in_global __asm__("sp");
+
 #ifdef CONFIG_FRAME_POINTER
 
 struct stackframe {
@@ -19,8 +21,6 @@ struct stackframe {
        unsigned long ra;
 };
 
-register unsigned long sp_in_global __asm__("sp");
-
 void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
                             bool (*fn)(unsigned long, void *), void *arg)
 {
index 33b16f4212f7a5fceb7feeff0a462e295bb4c0c0..4c8b2a4a6a7096bbaaa4d67b8ea1cfafbcb7eaf1 100644 (file)
@@ -12,7 +12,7 @@ vdso-syms += getcpu
 vdso-syms += flush_icache
 
 # Files to link into the vdso
-obj-vdso = $(patsubst %, %.o, $(vdso-syms))
+obj-vdso = $(patsubst %, %.o, $(vdso-syms)) note.o
 
 # Build rules
 targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds vdso-dummy.o
@@ -33,15 +33,15 @@ $(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) FORCE
        $(call if_changed,vdsold)
 
 # We also create a special relocatable object that should mirror the symbol
-# table and layout of the linked DSO.  With ld -R we can then refer to
-# these symbols in the kernel code rather than hand-coded addresses.
+# table and layout of the linked DSO. With ld --just-symbols we can then
+# refer to these symbols in the kernel code rather than hand-coded addresses.
 
 SYSCFLAGS_vdso.so.dbg = -shared -s -Wl,-soname=linux-vdso.so.1 \
        -Wl,--build-id -Wl,--hash-style=both
 $(obj)/vdso-dummy.o: $(src)/vdso.lds $(obj)/rt_sigreturn.o FORCE
        $(call if_changed,vdsold)
 
-LDFLAGS_vdso-syms.o := -r -R
+LDFLAGS_vdso-syms.o := -r --just-symbols
 $(obj)/vdso-syms.o: $(obj)/vdso-dummy.o FORCE
        $(call if_changed,ld)
 
diff --git a/arch/riscv/kernel/vdso/note.S b/arch/riscv/kernel/vdso/note.S
new file mode 100644 (file)
index 0000000..2a956c9
--- /dev/null
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ */
+
+#include <linux/elfnote.h>
+#include <linux/version.h>
+
+ELFNOTE_START(Linux, 0, "a")
+       .long LINUX_VERSION_CODE
+ELFNOTE_END
index b55be44ff9bdf3ebad11a952b56b366ab2310ed7..27a334106708f46d5a4ae8b14175220932552d17 100644 (file)
@@ -150,7 +150,8 @@ void __init setup_bootmem(void)
        memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);
 
        set_max_mapnr(PFN_DOWN(mem_size));
-       max_low_pfn = PFN_DOWN(memblock_end_of_DRAM());
+       max_pfn = PFN_DOWN(memblock_end_of_DRAM());
+       max_low_pfn = max_pfn;
 
 #ifdef CONFIG_BLK_DEV_INITRD
        setup_initrd();
@@ -501,22 +502,6 @@ static inline void setup_vm_final(void)
 #endif /* CONFIG_MMU */
 
 #ifdef CONFIG_STRICT_KERNEL_RWX
-void set_kernel_text_rw(void)
-{
-       unsigned long text_start = (unsigned long)_text;
-       unsigned long text_end = (unsigned long)_etext;
-
-       set_memory_rw(text_start, (text_end - text_start) >> PAGE_SHIFT);
-}
-
-void set_kernel_text_ro(void)
-{
-       unsigned long text_start = (unsigned long)_text;
-       unsigned long text_end = (unsigned long)_etext;
-
-       set_memory_ro(text_start, (text_end - text_start) >> PAGE_SHIFT);
-}
-
 void mark_rodata_ro(void)
 {
        unsigned long text_start = (unsigned long)_text;
index cc1985d8750a1fd7ba12825553a0cfc60bfc91b9..d208a9fd6c528e4599cfc6aecf12151f03372e87 100644 (file)
@@ -110,6 +110,16 @@ static bool is_32b_int(s64 val)
        return -(1L << 31) <= val && val < (1L << 31);
 }
 
+static bool in_auipc_jalr_range(s64 val)
+{
+       /*
+        * auipc+jalr can reach any signed PC-relative offset in the range
+        * [-2^31 - 2^11, 2^31 - 2^11).
+        */
+       return (-(1L << 31) - (1L << 11)) <= val &&
+               val < ((1L << 31) - (1L << 11));
+}
+
 static void emit_imm(u8 rd, s64 val, struct rv_jit_context *ctx)
 {
        /* Note that the immediate from the add is sign-extended,
@@ -380,20 +390,24 @@ static void emit_sext_32_rd(u8 *rd, struct rv_jit_context *ctx)
        *rd = RV_REG_T2;
 }
 
-static void emit_jump_and_link(u8 rd, s64 rvoff, bool force_jalr,
-                              struct rv_jit_context *ctx)
+static int emit_jump_and_link(u8 rd, s64 rvoff, bool force_jalr,
+                             struct rv_jit_context *ctx)
 {
        s64 upper, lower;
 
        if (rvoff && is_21b_int(rvoff) && !force_jalr) {
                emit(rv_jal(rd, rvoff >> 1), ctx);
-               return;
+               return 0;
+       } else if (in_auipc_jalr_range(rvoff)) {
+               upper = (rvoff + (1 << 11)) >> 12;
+               lower = rvoff & 0xfff;
+               emit(rv_auipc(RV_REG_T1, upper), ctx);
+               emit(rv_jalr(rd, RV_REG_T1, lower), ctx);
+               return 0;
        }
 
-       upper = (rvoff + (1 << 11)) >> 12;
-       lower = rvoff & 0xfff;
-       emit(rv_auipc(RV_REG_T1, upper), ctx);
-       emit(rv_jalr(rd, RV_REG_T1, lower), ctx);
+       pr_err("bpf-jit: target offset 0x%llx is out of range\n", rvoff);
+       return -ERANGE;
 }
 
 static bool is_signed_bpf_cond(u8 cond)
@@ -407,18 +421,16 @@ static int emit_call(bool fixed, u64 addr, struct rv_jit_context *ctx)
        s64 off = 0;
        u64 ip;
        u8 rd;
+       int ret;
 
        if (addr && ctx->insns) {
                ip = (u64)(long)(ctx->insns + ctx->ninsns);
                off = addr - ip;
-               if (!is_32b_int(off)) {
-                       pr_err("bpf-jit: target call addr %pK is out of range\n",
-                              (void *)addr);
-                       return -ERANGE;
-               }
        }
 
-       emit_jump_and_link(RV_REG_RA, off, !fixed, ctx);
+       ret = emit_jump_and_link(RV_REG_RA, off, !fixed, ctx);
+       if (ret)
+               return ret;
        rd = bpf_to_rv_reg(BPF_REG_0, ctx);
        emit(rv_addi(rd, RV_REG_A0, 0), ctx);
        return 0;
@@ -429,7 +441,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 {
        bool is64 = BPF_CLASS(insn->code) == BPF_ALU64 ||
                    BPF_CLASS(insn->code) == BPF_JMP;
-       int s, e, rvoff, i = insn - ctx->prog->insnsi;
+       int s, e, rvoff, ret, i = insn - ctx->prog->insnsi;
        struct bpf_prog_aux *aux = ctx->prog->aux;
        u8 rd = -1, rs = -1, code = insn->code;
        s16 off = insn->off;
@@ -699,7 +711,9 @@ out_be:
        /* JUMP off */
        case BPF_JMP | BPF_JA:
                rvoff = rv_offset(i, off, ctx);
-               emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
+               ret = emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
+               if (ret)
+                       return ret;
                break;
 
        /* IF (dst COND src) JUMP off */
@@ -801,7 +815,6 @@ out_be:
        case BPF_JMP | BPF_CALL:
        {
                bool fixed;
-               int ret;
                u64 addr;
 
                mark_call(ctx);
@@ -826,7 +839,9 @@ out_be:
                        break;
 
                rvoff = epilogue_offset(ctx);
-               emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
+               ret = emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
+               if (ret)
+                       return ret;
                break;
 
        /* dst = imm64 */
index 8fde561f1d07e3e905446c8f9b25d38f79f0b7b8..f887a479cdc7ec13b8058481011ad3a7b7781fdb 100644 (file)
@@ -7,9 +7,7 @@
 #ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
 int __bootdata_preserved(prot_virt_guest);
 #endif
-#if IS_ENABLED(CONFIG_KVM)
 struct uv_info __bootdata_preserved(uv_info);
-#endif
 
 void uv_query_info(void)
 {
index 61f2b0412345afc7c42e22361fa41e0054cbf24b..ccba63aaeb470ba64c073dd6f0d71ff8d3b4a784 100644 (file)
@@ -133,7 +133,7 @@ void diag_stat_inc(enum diag_stat_enum nr)
 }
 EXPORT_SYMBOL(diag_stat_inc);
 
-void diag_stat_inc_norecursion(enum diag_stat_enum nr)
+void notrace diag_stat_inc_norecursion(enum diag_stat_enum nr)
 {
        this_cpu_inc(diag_stat.counter[nr]);
        trace_s390_diagnose_norecursion(diag_map[nr].code);
index 7eaabbab22134aa4be336e8461997569b90e84c9..10dbb12eb14d2677b964037d0e99fe1ccfd3ecd1 100644 (file)
@@ -403,7 +403,7 @@ int smp_find_processor_id(u16 address)
        return -1;
 }
 
-bool arch_vcpu_is_preempted(int cpu)
+bool notrace arch_vcpu_is_preempted(int cpu)
 {
        if (test_cpu_flag_of(CIF_ENABLED_WAIT, cpu))
                return false;
@@ -413,7 +413,7 @@ bool arch_vcpu_is_preempted(int cpu)
 }
 EXPORT_SYMBOL(arch_vcpu_is_preempted);
 
-void smp_yield_cpu(int cpu)
+void notrace smp_yield_cpu(int cpu)
 {
        if (!MACHINE_HAS_DIAG9C)
                return;
index 490b52e85014538937d0c67e73a8bf6bf11c7cf9..11a669f3cc93c17d5f69f281296e04c2a39cc2bb 100644 (file)
@@ -14,7 +14,7 @@ EXPORT_TRACEPOINT_SYMBOL(s390_diagnose);
 
 static DEFINE_PER_CPU(unsigned int, diagnose_trace_depth);
 
-void trace_s390_diagnose_norecursion(int diag_nr)
+void notrace trace_s390_diagnose_norecursion(int diag_nr)
 {
        unsigned long flags;
        unsigned int *depth;
index c86d654351d1615f18f62caf4a501e5322513e8a..4c0677fc8904ba6a2925a4d0f983c3aea1afa6d0 100644 (file)
 int __bootdata_preserved(prot_virt_guest);
 #endif
 
+struct uv_info __bootdata_preserved(uv_info);
+
 #if IS_ENABLED(CONFIG_KVM)
 int prot_virt_host;
 EXPORT_SYMBOL(prot_virt_host);
-struct uv_info __bootdata_preserved(uv_info);
 EXPORT_SYMBOL(uv_info);
 
 static int __init prot_virt_setup(char *val)
index 8191106bf7b92dcf99caec72516b18b8c9212691..bfb4811349944d5662138b3f7f4889505ed85899 100644 (file)
@@ -393,7 +393,7 @@ static unsigned long deliverable_irqs(struct kvm_vcpu *vcpu)
        if (psw_mchk_disabled(vcpu))
                active_mask &= ~IRQ_PEND_MCHK_MASK;
        /* PV guest cpus can have a single interruption injected at a time. */
-       if (kvm_s390_pv_cpu_is_protected(vcpu) &&
+       if (kvm_s390_pv_cpu_get_handle(vcpu) &&
            vcpu->arch.sie_block->iictl != IICTL_CODE_NONE)
                active_mask &= ~(IRQ_PEND_EXT_II_MASK |
                                 IRQ_PEND_IO_MASK |
index 19a81024fe16b0cedf8d78a4d7d6410cedff5ba7..d05bb040fd427c1b25e1c9693930aa2ec01f0412 100644 (file)
@@ -545,6 +545,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_S390_AIS:
        case KVM_CAP_S390_AIS_MIGRATION:
        case KVM_CAP_S390_VCPU_RESETS:
+       case KVM_CAP_SET_GUEST_DEBUG:
                r = 1;
                break;
        case KVM_CAP_S390_HPAGE_1M:
@@ -1939,6 +1940,9 @@ static int gfn_to_memslot_approx(struct kvm_memslots *slots, gfn_t gfn)
                        start = slot + 1;
        }
 
+       if (start >= slots->used_slots)
+               return slots->used_slots - 1;
+
        if (gfn >= memslots[start].base_gfn &&
            gfn < memslots[start].base_gfn + memslots[start].npages) {
                atomic_set(&slots->lru_slot, start);
index 69a824f9ef0b46638cf0c921ca5bf0a0aba28be3..8938936424150569eb1bcd78ce1fa0e54e1eacec 100644 (file)
@@ -626,10 +626,12 @@ static int handle_pqap(struct kvm_vcpu *vcpu)
         * available for the guest are AQIC and TAPQ with the t bit set
         * since we do not set IC.3 (FIII) we currently will only intercept
         * the AQIC function code.
+        * Note: running nested under z/VM can result in intercepts for other
+        * function codes, e.g. PQAP(QCI). We do not support this and bail out.
         */
        reg0 = vcpu->run->s.regs.gprs[0];
        fc = (reg0 >> 24) & 0xff;
-       if (WARN_ON_ONCE(fc != 0x03))
+       if (fc != 0x03)
                return -EOPNOTSUPP;
 
        /* PQAP instruction is allowed for guest kernel only */
index c4f8039a35e8dda0bc20999b7db089e3ab09b613..0267405ab7c69fec93f73df3ed35f381b03c7f38 100644 (file)
@@ -64,10 +64,13 @@ mm_segment_t enable_sacf_uaccess(void)
 {
        mm_segment_t old_fs;
        unsigned long asce, cr;
+       unsigned long flags;
 
        old_fs = current->thread.mm_segment;
        if (old_fs & 1)
                return old_fs;
+       /* protect against a concurrent page table upgrade */
+       local_irq_save(flags);
        current->thread.mm_segment |= 1;
        asce = S390_lowcore.kernel_asce;
        if (likely(old_fs == USER_DS)) {
@@ -83,6 +86,7 @@ mm_segment_t enable_sacf_uaccess(void)
                __ctl_load(asce, 7, 7);
                set_cpu_flag(CIF_ASCE_SECONDARY);
        }
+       local_irq_restore(flags);
        return old_fs;
 }
 EXPORT_SYMBOL(enable_sacf_uaccess);
index 498c98a312f44c0318d3a0ee051b0a65fd5078f6..fff169d6471188cd8f58669316848e34969d12cd 100644 (file)
@@ -70,8 +70,20 @@ static void __crst_table_upgrade(void *arg)
 {
        struct mm_struct *mm = arg;
 
-       if (current->active_mm == mm)
-               set_user_asce(mm);
+       /* we must change all active ASCEs to avoid the creation of new TLBs */
+       if (current->active_mm == mm) {
+               S390_lowcore.user_asce = mm->context.asce;
+               if (current->thread.mm_segment == USER_DS) {
+                       __ctl_load(S390_lowcore.user_asce, 1, 1);
+                       /* Mark user-ASCE present in CR1 */
+                       clear_cpu_flag(CIF_ASCE_PRIMARY);
+               }
+               if (current->thread.mm_segment == USER_DS_SACF) {
+                       __ctl_load(S390_lowcore.user_asce, 7, 7);
+                       /* enable_sacf_uaccess does all or nothing */
+                       WARN_ON(!test_cpu_flag(CIF_ASCE_SECONDARY));
+               }
+       }
        __tlb_flush_local();
 }
 
index fbe97ab2e22869a2e80c94ad6729363ba3d217ec..743f257cf2cbdd0cfa0aed3a935edded9ce0d513 100644 (file)
@@ -115,7 +115,6 @@ static struct irq_chip zpci_irq_chip = {
        .name = "PCI-MSI",
        .irq_unmask = pci_msi_unmask_irq,
        .irq_mask = pci_msi_mask_irq,
-       .irq_set_affinity = zpci_set_irq_affinity,
 };
 
 static void zpci_handle_cpu_local_irq(bool rescan)
@@ -276,7 +275,9 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                rc = -EIO;
                if (hwirq - bit >= msi_vecs)
                        break;
-               irq = __irq_alloc_descs(-1, 0, 1, 0, THIS_MODULE, msi->affinity);
+               irq = __irq_alloc_descs(-1, 0, 1, 0, THIS_MODULE,
+                               (irq_delivery == DIRECTED) ?
+                               msi->affinity : NULL);
                if (irq < 0)
                        return -ENOMEM;
                rc = irq_set_msi_desc(irq, msi);
index 9f38fb35fe96cae9672fb2bf0e579431403722c2..337663a028dbc01a100de90909496108d94dd0f2 100644 (file)
@@ -11,32 +11,4 @@ struct mod_arch_specific {
 };
 #endif
 
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
-# ifdef CONFIG_CPU_SH2
-#  define MODULE_PROC_FAMILY "SH2LE "
-# elif defined  CONFIG_CPU_SH3
-#  define MODULE_PROC_FAMILY "SH3LE "
-# elif defined  CONFIG_CPU_SH4
-#  define MODULE_PROC_FAMILY "SH4LE "
-# elif defined  CONFIG_CPU_SH5
-#  define MODULE_PROC_FAMILY "SH5LE "
-# else
-#  error unknown processor family
-# endif
-#else
-# ifdef CONFIG_CPU_SH2
-#  define MODULE_PROC_FAMILY "SH2BE "
-# elif defined  CONFIG_CPU_SH3
-#  define MODULE_PROC_FAMILY "SH3BE "
-# elif defined  CONFIG_CPU_SH4
-#  define MODULE_PROC_FAMILY "SH4BE "
-# elif defined  CONFIG_CPU_SH5
-#  define MODULE_PROC_FAMILY "SH5BE "
-# else
-#  error unknown processor family
-# endif
-#endif
-
-#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
-
 #endif /* _ASM_SH_MODULE_H */
diff --git a/arch/sh/include/asm/vermagic.h b/arch/sh/include/asm/vermagic.h
new file mode 100644 (file)
index 0000000..13d8eaa
--- /dev/null
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _ASM_VERMAGIC_H
+#define _ASM_VERMAGIC_H
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+# ifdef CONFIG_CPU_SH2
+#  define MODULE_PROC_FAMILY "SH2LE "
+# elif defined  CONFIG_CPU_SH3
+#  define MODULE_PROC_FAMILY "SH3LE "
+# elif defined  CONFIG_CPU_SH4
+#  define MODULE_PROC_FAMILY "SH4LE "
+# elif defined  CONFIG_CPU_SH5
+#  define MODULE_PROC_FAMILY "SH5LE "
+# else
+#  error unknown processor family
+# endif
+#else
+# ifdef CONFIG_CPU_SH2
+#  define MODULE_PROC_FAMILY "SH2BE "
+# elif defined  CONFIG_CPU_SH3
+#  define MODULE_PROC_FAMILY "SH3BE "
+# elif defined  CONFIG_CPU_SH4
+#  define MODULE_PROC_FAMILY "SH4BE "
+# elif defined  CONFIG_CPU_SH5
+#  define MODULE_PROC_FAMILY "SH5BE "
+# else
+#  error unknown processor family
+# endif
+#endif
+
+#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
+
+#endif /* _ASM_VERMAGIC_H */
index b9de2d4fa57e347a172c17c40435c9c5417f8333..8d2a68aea1fcbff018d074062868ea2d9fbff3f6 100644 (file)
@@ -412,7 +412,7 @@ int arch_add_memory(int nid, u64 start, u64 size,
        unsigned long nr_pages = size >> PAGE_SHIFT;
        int ret;
 
-       if (WARN_ON_ONCE(params->pgprot.pgprot != PAGE_KERNEL.pgprot)
+       if (WARN_ON_ONCE(params->pgprot.pgprot != PAGE_KERNEL.pgprot))
                return -EINVAL;
 
        /* We only have ZONE_NORMAL, so this is easy.. */
index d2daa206872da406408a2685f6659c312b9aa18b..275f5ffdf6f0ada4e1f5499d77bda066a99b1f83 100644 (file)
@@ -140,6 +140,7 @@ export CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE)
 # When cleaning we don't include .config, so we don't include
 # TT or skas makefiles and don't clean skas_ptregs.h.
 CLEAN_FILES += linux x.i gmon.out
+MRPROPER_DIRS += arch/$(SUBARCH)/include/generated
 
 archclean:
        @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
index 1d6104ea8af0309d437766a72657989f88b2d4d9..1197b5596d5ad8959d242bd5f1666690e368de7d 100644 (file)
@@ -149,7 +149,7 @@ config X86
        select HAVE_ARCH_TRACEHOOK
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if X86_64
-       select HAVE_ARCH_USERFAULTFD_WP         if USERFAULTFD
+       select HAVE_ARCH_USERFAULTFD_WP         if X86_64 && USERFAULTFD
        select HAVE_ARCH_VMAP_STACK             if X86_64
        select HAVE_ARCH_WITHIN_STACK_FRAMES
        select HAVE_ASM_MODVERSIONS
index 06ef2d4a470171aecc249d7bbddedccebf67e04e..6737bcea1fa148a129cbc334c92778889dc41963 100644 (file)
@@ -32,16 +32,16 @@ void blake2s_compress_arch(struct blake2s_state *state,
                           const u32 inc)
 {
        /* SIMD disables preemption, so relax after processing each page. */
-       BUILD_BUG_ON(PAGE_SIZE / BLAKE2S_BLOCK_SIZE < 8);
+       BUILD_BUG_ON(SZ_4K / BLAKE2S_BLOCK_SIZE < 8);
 
        if (!static_branch_likely(&blake2s_use_ssse3) || !crypto_simd_usable()) {
                blake2s_compress_generic(state, block, nblocks, inc);
                return;
        }
 
-       for (;;) {
+       do {
                const size_t blocks = min_t(size_t, nblocks,
-                                           PAGE_SIZE / BLAKE2S_BLOCK_SIZE);
+                                           SZ_4K / BLAKE2S_BLOCK_SIZE);
 
                kernel_fpu_begin();
                if (IS_ENABLED(CONFIG_AS_AVX512) &&
@@ -52,10 +52,8 @@ void blake2s_compress_arch(struct blake2s_state *state,
                kernel_fpu_end();
 
                nblocks -= blocks;
-               if (!nblocks)
-                       break;
                block += blocks * BLAKE2S_BLOCK_SIZE;
-       }
+       } while (nblocks);
 }
 EXPORT_SYMBOL(blake2s_compress_arch);
 
index b412c21ee06e29a7d29aa94b6ada32e4da09484d..22250091cdbec81e24d9a9e2345e2966b511a2a0 100644 (file)
@@ -153,9 +153,17 @@ void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src, unsigned int bytes,
            bytes <= CHACHA_BLOCK_SIZE)
                return chacha_crypt_generic(state, dst, src, bytes, nrounds);
 
-       kernel_fpu_begin();
-       chacha_dosimd(state, dst, src, bytes, nrounds);
-       kernel_fpu_end();
+       do {
+               unsigned int todo = min_t(unsigned int, bytes, SZ_4K);
+
+               kernel_fpu_begin();
+               chacha_dosimd(state, dst, src, todo, nrounds);
+               kernel_fpu_end();
+
+               bytes -= todo;
+               src += todo;
+               dst += todo;
+       } while (bytes);
 }
 EXPORT_SYMBOL(chacha_crypt_arch);
 
index f7567cbd35b6958dbac7e54f4a4406b98bf0fa79..80fcb85736e1d388830eb08dd6054c43d302c8d1 100644 (file)
@@ -29,7 +29,7 @@ static int nhpoly1305_avx2_update(struct shash_desc *desc,
                return crypto_nhpoly1305_update(desc, src, srclen);
 
        do {
-               unsigned int n = min_t(unsigned int, srclen, PAGE_SIZE);
+               unsigned int n = min_t(unsigned int, srclen, SZ_4K);
 
                kernel_fpu_begin();
                crypto_nhpoly1305_update_helper(desc, src, n, _nh_avx2);
index a661ede3b5cfac684f38249bf26ad3ca24e00b72..cc6b7c1a2705d48c9c39463e1362f178cc3c0b02 100644 (file)
@@ -29,7 +29,7 @@ static int nhpoly1305_sse2_update(struct shash_desc *desc,
                return crypto_nhpoly1305_update(desc, src, srclen);
 
        do {
-               unsigned int n = min_t(unsigned int, srclen, PAGE_SIZE);
+               unsigned int n = min_t(unsigned int, srclen, SZ_4K);
 
                kernel_fpu_begin();
                crypto_nhpoly1305_update_helper(desc, src, n, _nh_sse2);
index 6dfec19f7d579aa7b717dc511861324e3d3a86e8..dfe921efa9b25cf2816564a84bd50412a5d73770 100644 (file)
@@ -91,8 +91,8 @@ static void poly1305_simd_blocks(void *ctx, const u8 *inp, size_t len,
        struct poly1305_arch_internal *state = ctx;
 
        /* SIMD disables preemption, so relax after processing each page. */
-       BUILD_BUG_ON(PAGE_SIZE < POLY1305_BLOCK_SIZE ||
-                    PAGE_SIZE % POLY1305_BLOCK_SIZE);
+       BUILD_BUG_ON(SZ_4K < POLY1305_BLOCK_SIZE ||
+                    SZ_4K % POLY1305_BLOCK_SIZE);
 
        if (!static_branch_likely(&poly1305_use_avx) ||
            (len < (POLY1305_BLOCK_SIZE * 18) && !state->is_base2_26) ||
@@ -102,8 +102,8 @@ static void poly1305_simd_blocks(void *ctx, const u8 *inp, size_t len,
                return;
        }
 
-       for (;;) {
-               const size_t bytes = min_t(size_t, len, PAGE_SIZE);
+       do {
+               const size_t bytes = min_t(size_t, len, SZ_4K);
 
                kernel_fpu_begin();
                if (IS_ENABLED(CONFIG_AS_AVX512) && static_branch_likely(&poly1305_use_avx512))
@@ -113,11 +113,10 @@ static void poly1305_simd_blocks(void *ctx, const u8 *inp, size_t len,
                else
                        poly1305_blocks_avx(ctx, inp, bytes, padbit);
                kernel_fpu_end();
+
                len -= bytes;
-               if (!len)
-                       break;
                inp += bytes;
-       }
+       } while (len);
 }
 
 static void poly1305_simd_emit(void *ctx, u8 mac[POLY1305_DIGEST_SIZE],
index 0789e13ece905c1c8c006fe27d4df96ef98d98cf..1c7f13bb67286238cb555ff1238557b6458b179e 100644 (file)
@@ -98,13 +98,6 @@ For 32-bit we have the following conventions - kernel is built with
 #define SIZEOF_PTREGS  21*8
 
 .macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax save_ret=0
-       /*
-        * Push registers and sanitize registers of values that a
-        * speculation attack might otherwise want to exploit. The
-        * lower registers are likely clobbered well before they
-        * could be put to use in a speculative execution gadget.
-        * Interleave XOR with PUSH for better uop scheduling:
-        */
        .if \save_ret
        pushq   %rsi            /* pt_regs->si */
        movq    8(%rsp), %rsi   /* temporarily store the return address in %rsi */
@@ -114,34 +107,43 @@ For 32-bit we have the following conventions - kernel is built with
        pushq   %rsi            /* pt_regs->si */
        .endif
        pushq   \rdx            /* pt_regs->dx */
-       xorl    %edx, %edx      /* nospec   dx */
        pushq   %rcx            /* pt_regs->cx */
-       xorl    %ecx, %ecx      /* nospec   cx */
        pushq   \rax            /* pt_regs->ax */
        pushq   %r8             /* pt_regs->r8 */
-       xorl    %r8d, %r8d      /* nospec   r8 */
        pushq   %r9             /* pt_regs->r9 */
-       xorl    %r9d, %r9d      /* nospec   r9 */
        pushq   %r10            /* pt_regs->r10 */
-       xorl    %r10d, %r10d    /* nospec   r10 */
        pushq   %r11            /* pt_regs->r11 */
-       xorl    %r11d, %r11d    /* nospec   r11*/
        pushq   %rbx            /* pt_regs->rbx */
-       xorl    %ebx, %ebx      /* nospec   rbx*/
        pushq   %rbp            /* pt_regs->rbp */
-       xorl    %ebp, %ebp      /* nospec   rbp*/
        pushq   %r12            /* pt_regs->r12 */
-       xorl    %r12d, %r12d    /* nospec   r12*/
        pushq   %r13            /* pt_regs->r13 */
-       xorl    %r13d, %r13d    /* nospec   r13*/
        pushq   %r14            /* pt_regs->r14 */
-       xorl    %r14d, %r14d    /* nospec   r14*/
        pushq   %r15            /* pt_regs->r15 */
-       xorl    %r15d, %r15d    /* nospec   r15*/
        UNWIND_HINT_REGS
+
        .if \save_ret
        pushq   %rsi            /* return address on top of stack */
        .endif
+
+       /*
+        * Sanitize registers of values that a speculation attack might
+        * otherwise want to exploit. The lower registers are likely clobbered
+        * well before they could be put to use in a speculative execution
+        * gadget.
+        */
+       xorl    %edx,  %edx     /* nospec dx  */
+       xorl    %ecx,  %ecx     /* nospec cx  */
+       xorl    %r8d,  %r8d     /* nospec r8  */
+       xorl    %r9d,  %r9d     /* nospec r9  */
+       xorl    %r10d, %r10d    /* nospec r10 */
+       xorl    %r11d, %r11d    /* nospec r11 */
+       xorl    %ebx,  %ebx     /* nospec rbx */
+       xorl    %ebp,  %ebp     /* nospec rbp */
+       xorl    %r12d, %r12d    /* nospec r12 */
+       xorl    %r13d, %r13d    /* nospec r13 */
+       xorl    %r14d, %r14d    /* nospec r14 */
+       xorl    %r15d, %r15d    /* nospec r15 */
+
 .endm
 
 .macro POP_REGS pop_rdi=1 skip_r11rcx=0
index 0e9504fabe52609917c4aa3462f4faff1b1e32b5..3063aa9090f9a7927143fb929fde7ec7a8150d81 100644 (file)
@@ -249,7 +249,6 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_hwframe, SYM_L_GLOBAL)
         */
 syscall_return_via_sysret:
        /* rcx and r11 are already restored (see code above) */
-       UNWIND_HINT_EMPTY
        POP_REGS pop_rdi=0 skip_r11rcx=1
 
        /*
@@ -258,6 +257,7 @@ syscall_return_via_sysret:
         */
        movq    %rsp, %rdi
        movq    PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp
+       UNWIND_HINT_EMPTY
 
        pushq   RSP-RDI(%rdi)   /* RSP */
        pushq   (%rdi)          /* RDI */
@@ -279,8 +279,7 @@ SYM_CODE_END(entry_SYSCALL_64)
  * %rdi: prev task
  * %rsi: next task
  */
-SYM_CODE_START(__switch_to_asm)
-       UNWIND_HINT_FUNC
+SYM_FUNC_START(__switch_to_asm)
        /*
         * Save callee-saved registers
         * This must match the order in inactive_task_frame
@@ -321,7 +320,7 @@ SYM_CODE_START(__switch_to_asm)
        popq    %rbp
 
        jmp     __switch_to
-SYM_CODE_END(__switch_to_asm)
+SYM_FUNC_END(__switch_to_asm)
 
 /*
  * A newly forked process directly context switches into this address.
@@ -512,7 +511,7 @@ SYM_CODE_END(spurious_entries_start)
  * +----------------------------------------------------+
  */
 SYM_CODE_START(interrupt_entry)
-       UNWIND_HINT_FUNC
+       UNWIND_HINT_IRET_REGS offset=16
        ASM_CLAC
        cld
 
@@ -544,9 +543,9 @@ SYM_CODE_START(interrupt_entry)
        pushq   5*8(%rdi)               /* regs->eflags */
        pushq   4*8(%rdi)               /* regs->cs */
        pushq   3*8(%rdi)               /* regs->ip */
+       UNWIND_HINT_IRET_REGS
        pushq   2*8(%rdi)               /* regs->orig_ax */
        pushq   8(%rdi)                 /* return address */
-       UNWIND_HINT_FUNC
 
        movq    (%rdi), %rdi
        jmp     2f
@@ -637,6 +636,7 @@ SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL)
         */
        movq    %rsp, %rdi
        movq    PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp
+       UNWIND_HINT_EMPTY
 
        /* Copy the IRET frame to the trampoline stack. */
        pushq   6*8(%rdi)       /* SS */
@@ -1739,7 +1739,7 @@ SYM_CODE_START(rewind_stack_do_exit)
 
        movq    PER_CPU_VAR(cpu_current_top_of_stack), %rax
        leaq    -PTREGS_SIZE(%rax), %rsp
-       UNWIND_HINT_FUNC sp_offset=PTREGS_SIZE
+       UNWIND_HINT_REGS
 
        call    do_exit
 SYM_CODE_END(rewind_stack_do_exit)
index e4aa20c0426fcc31a87b8486ad5a2dfa8182dabb..442e1ed4acd49d62235dc1e42a2604ac669693dd 100644 (file)
@@ -643,6 +643,7 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = {
        X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS,  &glm_cstates),
        X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D,      &glm_cstates),
        X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT,        &glm_cstates),
+       X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L,      &glm_cstates),
 
        X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L,           &icl_cstates),
        X86_MATCH_INTEL_FAM6_MODEL(ICELAKE,             &icl_cstates),
index b0da5320bcff8420f00037468a17e61e353b5f49..fd51bac11b467d83e02d6156c310359ff70ac19e 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/mm.h>
 #include <linux/hyperv.h>
 #include <linux/slab.h>
+#include <linux/kernel.h>
 #include <linux/cpuhotplug.h>
 #include <linux/syscore_ops.h>
 #include <clocksource/hyperv_timer.h>
@@ -72,7 +73,8 @@ static int hv_cpu_init(unsigned int cpu)
        struct page *pg;
 
        input_arg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
-       pg = alloc_page(GFP_KERNEL);
+       /* hv_cpu_init() can be called with IRQs disabled from hv_resume() */
+       pg = alloc_page(irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
        if (unlikely(!pg))
                return -ENOMEM;
        *input_arg = page_address(pg);
@@ -253,6 +255,7 @@ static int __init hv_pci_init(void)
 static int hv_suspend(void)
 {
        union hv_x64_msr_hypercall_contents hypercall_msr;
+       int ret;
 
        /*
         * Reset the hypercall page as it is going to be invalidated
@@ -269,12 +272,17 @@ static int hv_suspend(void)
        hypercall_msr.enable = 0;
        wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
 
-       return 0;
+       ret = hv_cpu_die(0);
+       return ret;
 }
 
 static void hv_resume(void)
 {
        union hv_x64_msr_hypercall_contents hypercall_msr;
+       int ret;
+
+       ret = hv_cpu_init(0);
+       WARN_ON(ret);
 
        /* Re-enable the hypercall page */
        rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
@@ -287,6 +295,7 @@ static void hv_resume(void)
        hv_hypercall_pg_saved = NULL;
 }
 
+/* Note: when the ops are called, only CPU0 is online and IRQs are disabled. */
 static struct syscore_ops hv_syscore_ops = {
        .suspend        = hv_suspend,
        .resume         = hv_resume,
@@ -419,11 +428,14 @@ void hyperv_cleanup(void)
 }
 EXPORT_SYMBOL_GPL(hyperv_cleanup);
 
-void hyperv_report_panic(struct pt_regs *regs, long err)
+void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die)
 {
        static bool panic_reported;
        u64 guest_id;
 
+       if (in_die && !panic_on_oops)
+               return;
+
        /*
         * We prefer to report panic on 'die' chain as we have proper
         * registers to report, but if we miss it (e.g. on BUG()) we need
index cdcf48d52a128f7f647f4ee9d5a62d453394f5fc..8391c115c0ecd32da2c9ad856bdb28caf3319143 100644 (file)
@@ -178,8 +178,10 @@ extern void efi_free_boot_services(void);
 extern pgd_t * __init efi_uv1_memmap_phys_prolog(void);
 extern void __init efi_uv1_memmap_phys_epilog(pgd_t *save_pgd);
 
+/* kexec external ABI */
 struct efi_setup_data {
        u64 fw_vendor;
+       u64 __unused;
        u64 tables;
        u64 smbios;
        u64 reserved[8];
index 85be2f5062728f13f61e84ed9efa6d622e96f5dd..70b96cae5b42fb8ca1d565e9da0d96ba17e763ed 100644 (file)
@@ -61,11 +61,12 @@ static inline bool arch_syscall_match_sym_name(const char *sym, const char *name
 {
        /*
         * Compare the symbol name with the system call name. Skip the
-        * "__x64_sys", "__ia32_sys" or simple "sys" prefix.
+        * "__x64_sys", "__ia32_sys", "__do_sys" or simple "sys" prefix.
         */
        return !strcmp(sym + 3, name + 3) ||
                (!strncmp(sym, "__x64_", 6) && !strcmp(sym + 9, name + 3)) ||
-               (!strncmp(sym, "__ia32_", 7) && !strcmp(sym + 10, name + 3));
+               (!strncmp(sym, "__ia32_", 7) && !strcmp(sym + 10, name + 3)) ||
+               (!strncmp(sym, "__do_sys", 8) && !strcmp(sym + 8, name + 3));
 }
 
 #ifndef COMPILE_OFFSETS
index 42a2d0d3984ab43317d0e67ad227223699233621..0dea9f122bb9c21c2fa0dffa319c3000c144f3ce 100644 (file)
@@ -1663,8 +1663,8 @@ void kvm_set_msi_irq(struct kvm *kvm, struct kvm_kernel_irq_routing_entry *e,
 static inline bool kvm_irq_is_postable(struct kvm_lapic_irq *irq)
 {
        /* We can only post Fixed and LowPrio IRQs */
-       return (irq->delivery_mode == dest_Fixed ||
-               irq->delivery_mode == dest_LowestPrio);
+       return (irq->delivery_mode == APIC_DM_FIXED ||
+               irq->delivery_mode == APIC_DM_LOWEST);
 }
 
 static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
index 6685e1218959d21b2c93ceb56992ef291e427ac0..7063b5a43220a96a363f97e3567fabd0fbc8be70 100644 (file)
@@ -41,7 +41,7 @@ struct microcode_amd {
        unsigned int                    mpb[0];
 };
 
-#define PATCH_MAX_SIZE PAGE_SIZE
+#define PATCH_MAX_SIZE (3 * PAGE_SIZE)
 
 #ifdef CONFIG_MICROCODE_AMD
 extern void __init load_ucode_amd_bsp(unsigned int family);
index c215d276248844e0608ba0c880f1ddb15e7ba839..e988bac0a4a1c316fffac9525b2a094cde9b2a51 100644 (file)
@@ -13,64 +13,4 @@ struct mod_arch_specific {
 #endif
 };
 
-#ifdef CONFIG_X86_64
-/* X86_64 does not define MODULE_PROC_FAMILY */
-#elif defined CONFIG_M486SX
-#define MODULE_PROC_FAMILY "486SX "
-#elif defined CONFIG_M486
-#define MODULE_PROC_FAMILY "486 "
-#elif defined CONFIG_M586
-#define MODULE_PROC_FAMILY "586 "
-#elif defined CONFIG_M586TSC
-#define MODULE_PROC_FAMILY "586TSC "
-#elif defined CONFIG_M586MMX
-#define MODULE_PROC_FAMILY "586MMX "
-#elif defined CONFIG_MCORE2
-#define MODULE_PROC_FAMILY "CORE2 "
-#elif defined CONFIG_MATOM
-#define MODULE_PROC_FAMILY "ATOM "
-#elif defined CONFIG_M686
-#define MODULE_PROC_FAMILY "686 "
-#elif defined CONFIG_MPENTIUMII
-#define MODULE_PROC_FAMILY "PENTIUMII "
-#elif defined CONFIG_MPENTIUMIII
-#define MODULE_PROC_FAMILY "PENTIUMIII "
-#elif defined CONFIG_MPENTIUMM
-#define MODULE_PROC_FAMILY "PENTIUMM "
-#elif defined CONFIG_MPENTIUM4
-#define MODULE_PROC_FAMILY "PENTIUM4 "
-#elif defined CONFIG_MK6
-#define MODULE_PROC_FAMILY "K6 "
-#elif defined CONFIG_MK7
-#define MODULE_PROC_FAMILY "K7 "
-#elif defined CONFIG_MK8
-#define MODULE_PROC_FAMILY "K8 "
-#elif defined CONFIG_MELAN
-#define MODULE_PROC_FAMILY "ELAN "
-#elif defined CONFIG_MCRUSOE
-#define MODULE_PROC_FAMILY "CRUSOE "
-#elif defined CONFIG_MEFFICEON
-#define MODULE_PROC_FAMILY "EFFICEON "
-#elif defined CONFIG_MWINCHIPC6
-#define MODULE_PROC_FAMILY "WINCHIPC6 "
-#elif defined CONFIG_MWINCHIP3D
-#define MODULE_PROC_FAMILY "WINCHIP3D "
-#elif defined CONFIG_MCYRIXIII
-#define MODULE_PROC_FAMILY "CYRIXIII "
-#elif defined CONFIG_MVIAC3_2
-#define MODULE_PROC_FAMILY "VIAC3-2 "
-#elif defined CONFIG_MVIAC7
-#define MODULE_PROC_FAMILY "VIAC7 "
-#elif defined CONFIG_MGEODEGX1
-#define MODULE_PROC_FAMILY "GEODEGX1 "
-#elif defined CONFIG_MGEODE_LX
-#define MODULE_PROC_FAMILY "GEODE "
-#else
-#error unknown processor family
-#endif
-
-#ifdef CONFIG_X86_32
-# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
-#endif
-
 #endif /* _ASM_X86_MODULE_H */
index 1c42ecbe75cb4d2b430f12e4dfa6a95c7128739f..d30805ed323ef9d682fec37bdd9fc5a8e2f30cf6 100644 (file)
@@ -35,6 +35,8 @@ typedef int (*hyperv_fill_flush_list_func)(
        rdmsrl(HV_X64_MSR_SINT0 + int_num, val)
 #define hv_set_synint_state(int_num, val) \
        wrmsrl(HV_X64_MSR_SINT0 + int_num, val)
+#define hv_recommend_using_aeoi() \
+       (!(ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED))
 
 #define hv_get_crash_ctl(val) \
        rdmsrl(HV_X64_MSR_CRASH_CTL, val)
index 07e95dcb40ad5463b6e642c386e45cb6c5090cbe..7e9a281e266049b06668ec6f659f37f03f1052e9 100644 (file)
@@ -237,27 +237,6 @@ enum ssb_mitigation {
 extern char __indirect_thunk_start[];
 extern char __indirect_thunk_end[];
 
-/*
- * On VMEXIT we must ensure that no RSB predictions learned in the guest
- * can be followed in the host, by overwriting the RSB completely. Both
- * retpoline and IBRS mitigations for Spectre v2 need this; only on future
- * CPUs with IBRS_ALL *might* it be avoided.
- */
-static inline void vmexit_fill_RSB(void)
-{
-#ifdef CONFIG_RETPOLINE
-       unsigned long loops;
-
-       asm volatile (ANNOTATE_NOSPEC_ALTERNATIVE
-                     ALTERNATIVE("jmp 910f",
-                                 __stringify(__FILL_RETURN_BUFFER(%0, RSB_CLEAR_LOOPS, %1)),
-                                 X86_FEATURE_RETPOLINE)
-                     "910:"
-                     : "=r" (loops), ASM_CALL_CONSTRAINT
-                     : : "memory" );
-#endif
-}
-
 static __always_inline
 void alternative_msr_write(unsigned int msr, u64 val, unsigned int feature)
 {
index 499578f7e6d7bb5020fe0c503c70b1be0f5b95f1..70fc159ebe6959fead369c46d8a143812a1bc058 100644 (file)
@@ -19,7 +19,7 @@ struct unwind_state {
 #if defined(CONFIG_UNWINDER_ORC)
        bool signal, full_regs;
        unsigned long sp, bp, ip;
-       struct pt_regs *regs;
+       struct pt_regs *regs, *prev_regs;
 #elif defined(CONFIG_UNWINDER_FRAME_POINTER)
        bool got_irq;
        unsigned long *bp, *orig_sp, ip;
diff --git a/arch/x86/include/asm/vermagic.h b/arch/x86/include/asm/vermagic.h
new file mode 100644 (file)
index 0000000..75884d2
--- /dev/null
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _ASM_VERMAGIC_H
+#define _ASM_VERMAGIC_H
+
+#ifdef CONFIG_X86_64
+/* X86_64 does not define MODULE_PROC_FAMILY */
+#elif defined CONFIG_M486SX
+#define MODULE_PROC_FAMILY "486SX "
+#elif defined CONFIG_M486
+#define MODULE_PROC_FAMILY "486 "
+#elif defined CONFIG_M586
+#define MODULE_PROC_FAMILY "586 "
+#elif defined CONFIG_M586TSC
+#define MODULE_PROC_FAMILY "586TSC "
+#elif defined CONFIG_M586MMX
+#define MODULE_PROC_FAMILY "586MMX "
+#elif defined CONFIG_MCORE2
+#define MODULE_PROC_FAMILY "CORE2 "
+#elif defined CONFIG_MATOM
+#define MODULE_PROC_FAMILY "ATOM "
+#elif defined CONFIG_M686
+#define MODULE_PROC_FAMILY "686 "
+#elif defined CONFIG_MPENTIUMII
+#define MODULE_PROC_FAMILY "PENTIUMII "
+#elif defined CONFIG_MPENTIUMIII
+#define MODULE_PROC_FAMILY "PENTIUMIII "
+#elif defined CONFIG_MPENTIUMM
+#define MODULE_PROC_FAMILY "PENTIUMM "
+#elif defined CONFIG_MPENTIUM4
+#define MODULE_PROC_FAMILY "PENTIUM4 "
+#elif defined CONFIG_MK6
+#define MODULE_PROC_FAMILY "K6 "
+#elif defined CONFIG_MK7
+#define MODULE_PROC_FAMILY "K7 "
+#elif defined CONFIG_MK8
+#define MODULE_PROC_FAMILY "K8 "
+#elif defined CONFIG_MELAN
+#define MODULE_PROC_FAMILY "ELAN "
+#elif defined CONFIG_MCRUSOE
+#define MODULE_PROC_FAMILY "CRUSOE "
+#elif defined CONFIG_MEFFICEON
+#define MODULE_PROC_FAMILY "EFFICEON "
+#elif defined CONFIG_MWINCHIPC6
+#define MODULE_PROC_FAMILY "WINCHIPC6 "
+#elif defined CONFIG_MWINCHIP3D
+#define MODULE_PROC_FAMILY "WINCHIP3D "
+#elif defined CONFIG_MCYRIXIII
+#define MODULE_PROC_FAMILY "CYRIXIII "
+#elif defined CONFIG_MVIAC3_2
+#define MODULE_PROC_FAMILY "VIAC3-2 "
+#elif defined CONFIG_MVIAC7
+#define MODULE_PROC_FAMILY "VIAC7 "
+#elif defined CONFIG_MGEODEGX1
+#define MODULE_PROC_FAMILY "GEODEGX1 "
+#elif defined CONFIG_MGEODE_LX
+#define MODULE_PROC_FAMILY "GEODE "
+#else
+#error unknown processor family
+#endif
+
+#ifdef CONFIG_X86_32
+# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
+#else
+# define MODULE_ARCH_VERMAGIC ""
+#endif
+
+#endif /* _ASM_VERMAGIC_H */
index 81b9c63dae1bdee98a90701dbc9026d09bb1b359..e53dda210cd734235eace14d0deafb65bc5e8ec0 100644 (file)
@@ -352,8 +352,6 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
                 * According to Intel, MFENCE can do the serialization here.
                 */
                asm volatile("mfence" : : : "memory");
-
-               printk_once(KERN_DEBUG "TSC deadline timer enabled\n");
                return;
        }
 
@@ -546,7 +544,7 @@ static struct clock_event_device lapic_clockevent = {
 };
 static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
 
-static u32 hsx_deadline_rev(void)
+static __init u32 hsx_deadline_rev(void)
 {
        switch (boot_cpu_data.x86_stepping) {
        case 0x02: return 0x3a; /* EP */
@@ -556,7 +554,7 @@ static u32 hsx_deadline_rev(void)
        return ~0U;
 }
 
-static u32 bdx_deadline_rev(void)
+static __init u32 bdx_deadline_rev(void)
 {
        switch (boot_cpu_data.x86_stepping) {
        case 0x02: return 0x00000011;
@@ -568,7 +566,7 @@ static u32 bdx_deadline_rev(void)
        return ~0U;
 }
 
-static u32 skx_deadline_rev(void)
+static __init u32 skx_deadline_rev(void)
 {
        switch (boot_cpu_data.x86_stepping) {
        case 0x03: return 0x01000136;
@@ -581,7 +579,7 @@ static u32 skx_deadline_rev(void)
        return ~0U;
 }
 
-static const struct x86_cpu_id deadline_match[] = {
+static const struct x86_cpu_id deadline_match[] __initconst = {
        X86_MATCH_INTEL_FAM6_MODEL( HASWELL_X,          &hsx_deadline_rev),
        X86_MATCH_INTEL_FAM6_MODEL( BROADWELL_X,        0x0b000020),
        X86_MATCH_INTEL_FAM6_MODEL( BROADWELL_D,        &bdx_deadline_rev),
@@ -603,18 +601,19 @@ static const struct x86_cpu_id deadline_match[] = {
        {},
 };
 
-static void apic_check_deadline_errata(void)
+static __init bool apic_validate_deadline_timer(void)
 {
        const struct x86_cpu_id *m;
        u32 rev;
 
-       if (!boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER) ||
-           boot_cpu_has(X86_FEATURE_HYPERVISOR))
-               return;
+       if (!boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
+               return false;
+       if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
+               return true;
 
        m = x86_match_cpu(deadline_match);
        if (!m)
-               return;
+               return true;
 
        /*
         * Function pointers will have the MSB set due to address layout,
@@ -626,11 +625,12 @@ static void apic_check_deadline_errata(void)
                rev = (u32)m->driver_data;
 
        if (boot_cpu_data.microcode >= rev)
-               return;
+               return true;
 
        setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
        pr_err(FW_BUG "TSC_DEADLINE disabled due to Errata; "
               "please update microcode to version: 0x%x (or later)\n", rev);
+       return false;
 }
 
 /*
@@ -2092,7 +2092,8 @@ void __init init_apic_mappings(void)
 {
        unsigned int new_apicid;
 
-       apic_check_deadline_errata();
+       if (apic_validate_deadline_timer())
+               pr_debug("TSC deadline timer available\n");
 
        if (x2apic_mode) {
                boot_cpu_physical_apicid = read_apic_id();
index bf08d4508ecbafd3e5c355a581fd3cd2a1a89d4b..a19a680542ce736ce0f89c3621d0695a9481c6f8 100644 (file)
@@ -1119,35 +1119,53 @@ void switch_to_sld(unsigned long tifn)
        sld_update_msr(!(tifn & _TIF_SLD));
 }
 
-#define SPLIT_LOCK_CPU(model) {X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY}
-
 /*
- * The following processors have the split lock detection feature. But
- * since they don't have the IA32_CORE_CAPABILITIES MSR, the feature cannot
- * be enumerated. Enable it by family and model matching on these
- * processors.
+ * Bits in the IA32_CORE_CAPABILITIES are not architectural, so they should
+ * only be trusted if it is confirmed that a CPU model implements a
+ * specific feature at a particular bit position.
+ *
+ * The possible driver data field values:
+ *
+ * - 0: CPU models that are known to have the per-core split-lock detection
+ *     feature even though they do not enumerate IA32_CORE_CAPABILITIES.
+ *
+ * - 1: CPU models which may enumerate IA32_CORE_CAPABILITIES and if so use
+ *      bit 5 to enumerate the per-core split-lock detection feature.
  */
 static const struct x86_cpu_id split_lock_cpu_ids[] __initconst = {
-       SPLIT_LOCK_CPU(INTEL_FAM6_ICELAKE_X),
-       SPLIT_LOCK_CPU(INTEL_FAM6_ICELAKE_L),
+       X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X,           0),
+       X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L,           0),
+       X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT,        1),
+       X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D,      1),
+       X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L,      1),
        {}
 };
 
 void __init cpu_set_core_cap_bits(struct cpuinfo_x86 *c)
 {
-       u64 ia32_core_caps = 0;
+       const struct x86_cpu_id *m;
+       u64 ia32_core_caps;
+
+       if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
+               return;
 
-       if (c->x86_vendor != X86_VENDOR_INTEL)
+       m = x86_match_cpu(split_lock_cpu_ids);
+       if (!m)
                return;
-       if (cpu_has(c, X86_FEATURE_CORE_CAPABILITIES)) {
-               /* Enumerate features reported in IA32_CORE_CAPABILITIES MSR. */
+
+       switch (m->driver_data) {
+       case 0:
+               break;
+       case 1:
+               if (!cpu_has(c, X86_FEATURE_CORE_CAPABILITIES))
+                       return;
                rdmsrl(MSR_IA32_CORE_CAPS, ia32_core_caps);
-       } else if (!boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
-               /* Enumerate split lock detection by family and model. */
-               if (x86_match_cpu(split_lock_cpu_ids))
-                       ia32_core_caps |= MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT;
+               if (!(ia32_core_caps & MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT))
+                       return;
+               break;
+       default:
+               return;
        }
 
-       if (ia32_core_caps & MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT)
-               split_lock_setup();
+       split_lock_setup();
 }
index caa032ce3fe311507e6168f4ec0a0d742cf7a0b9..ebf34c7bc8bc0dfcb0cac217d522358c8c192b04 100644 (file)
@@ -227,8 +227,8 @@ static void __init ms_hyperv_init_platform(void)
        ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES);
        ms_hyperv.hints    = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);
 
-       pr_info("Hyper-V: features 0x%x, hints 0x%x\n",
-               ms_hyperv.features, ms_hyperv.hints);
+       pr_info("Hyper-V: features 0x%x, hints 0x%x, misc 0x%x\n",
+               ms_hyperv.features, ms_hyperv.hints, ms_hyperv.misc_features);
 
        ms_hyperv.max_vp_index = cpuid_eax(HYPERV_CPUID_IMPLEMENT_LIMITS);
        ms_hyperv.max_lp_index = cpuid_ebx(HYPERV_CPUID_IMPLEMENT_LIMITS);
@@ -263,6 +263,16 @@ static void __init ms_hyperv_init_platform(void)
                        cpuid_eax(HYPERV_CPUID_NESTED_FEATURES);
        }
 
+       /*
+        * Hyper-V expects to get crash register data or kmsg when
+        * crash enlightment is available and system crashes. Set
+        * crash_kexec_post_notifiers to be true to make sure that
+        * calling crash enlightment interface before running kdump
+        * kernel.
+        */
+       if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE)
+               crash_kexec_post_notifiers = true;
+
 #ifdef CONFIG_X86_LOCAL_APIC
        if (ms_hyperv.features & HV_X64_ACCESS_FREQUENCY_MSRS &&
            ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {
index 89049b343c7a8f27b0af635253c911d15f393f2b..d8cc5223b7ce89e8dc3703bc714b0fe5d29d1d8e 100644 (file)
@@ -578,6 +578,8 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
        d->id = id;
        cpumask_set_cpu(cpu, &d->cpu_mask);
 
+       rdt_domain_reconfigure_cdp(r);
+
        if (r->alloc_capable && domain_setup_ctrlval(r, d)) {
                kfree(d);
                return;
index 181c992f448c068b4cabf8880eb9cf20716475d6..3dd13f3a8b23187c2b3e0257873c434960b33bae 100644 (file)
@@ -601,5 +601,6 @@ bool has_busy_rmid(struct rdt_resource *r, struct rdt_domain *d);
 void __check_limbo(struct rdt_domain *d, bool force_free);
 bool cbm_validate_intel(char *buf, u32 *data, struct rdt_resource *r);
 bool cbm_validate_amd(char *buf, u32 *data, struct rdt_resource *r);
+void rdt_domain_reconfigure_cdp(struct rdt_resource *r);
 
 #endif /* _ASM_X86_RESCTRL_INTERNAL_H */
index 064e9ef44cd68ec5eaefc13ccde103c5fe89f565..5a359d9fcc055701956d36a4857f15853702e1c6 100644 (file)
@@ -1859,6 +1859,19 @@ static int set_cache_qos_cfg(int level, bool enable)
        return 0;
 }
 
+/* Restore the qos cfg state when a domain comes online */
+void rdt_domain_reconfigure_cdp(struct rdt_resource *r)
+{
+       if (!r->alloc_capable)
+               return;
+
+       if (r == &rdt_resources_all[RDT_RESOURCE_L2DATA])
+               l2_qos_cfg_update(&r->alloc_enabled);
+
+       if (r == &rdt_resources_all[RDT_RESOURCE_L3DATA])
+               l3_qos_cfg_update(&r->alloc_enabled);
+}
+
 /*
  * Enable or disable the MBA software controller
  * which helps user specify bandwidth in MBps.
@@ -3072,7 +3085,8 @@ static int rdtgroup_rmdir(struct kernfs_node *kn)
         * If the rdtgroup is a mon group and parent directory
         * is a valid "mon_groups" directory, remove the mon group.
         */
-       if (rdtgrp->type == RDTCTRL_GROUP && parent_kn == rdtgroup_default.kn) {
+       if (rdtgrp->type == RDTCTRL_GROUP && parent_kn == rdtgroup_default.kn &&
+           rdtgrp != &rdtgroup_default) {
                if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP ||
                    rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) {
                        ret = rdtgroup_ctrl_remove(kn, rdtgrp);
index 87b97897a881035966bbef4693df91e8d46b547e..460ae7f66818c7505c5c3aaf3f1be37284e2cd6c 100644 (file)
@@ -183,7 +183,8 @@ recursion_check:
         */
        if (visit_mask) {
                if (*visit_mask & (1UL << info->type)) {
-                       printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
+                       if (task == current)
+                               printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
                        goto unknown;
                }
                *visit_mask |= 1UL << info->type;
index fe3ab9632f3bc3d23df2261098bda1b1fdb780c0..8c89e4d9ad28da008a4bb5c5d8abb95993edd4b2 100644 (file)
@@ -147,7 +147,7 @@ static inline void smpboot_restore_warm_reset_vector(void)
        *((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0;
 }
 
-static void init_freq_invariance(void);
+static void init_freq_invariance(bool secondary);
 
 /*
  * Report back to the Boot Processor during boot time or to the caller processor
@@ -185,7 +185,7 @@ static void smp_callin(void)
         */
        set_cpu_sibling_map(raw_smp_processor_id());
 
-       init_freq_invariance();
+       init_freq_invariance(true);
 
        /*
         * Get our bogomips.
@@ -1341,7 +1341,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
        set_sched_topology(x86_topology);
 
        set_cpu_sibling_map(0);
-       init_freq_invariance();
+       init_freq_invariance(false);
        smp_sanity_check();
 
        switch (apic_intr_mode) {
@@ -1877,9 +1877,6 @@ static bool knl_set_max_freq_ratio(u64 *base_freq, u64 *turbo_freq,
        int err, i;
        u64 msr;
 
-       if (!x86_match_cpu(has_knl_turbo_ratio_limits))
-               return false;
-
        err = rdmsrl_safe(MSR_PLATFORM_INFO, base_freq);
        if (err)
                return false;
@@ -1945,18 +1942,23 @@ static bool skx_set_max_freq_ratio(u64 *base_freq, u64 *turbo_freq, int size)
 
 static bool core_set_max_freq_ratio(u64 *base_freq, u64 *turbo_freq)
 {
+       u64 msr;
        int err;
 
        err = rdmsrl_safe(MSR_PLATFORM_INFO, base_freq);
        if (err)
                return false;
 
-       err = rdmsrl_safe(MSR_TURBO_RATIO_LIMIT, turbo_freq);
+       err = rdmsrl_safe(MSR_TURBO_RATIO_LIMIT, &msr);
        if (err)
                return false;
 
-       *base_freq = (*base_freq >> 8) & 0xFF;      /* max P state */
-       *turbo_freq = (*turbo_freq >> 24) & 0xFF;   /* 4C turbo    */
+       *base_freq = (*base_freq >> 8) & 0xFF;    /* max P state */
+       *turbo_freq = (msr >> 24) & 0xFF;         /* 4C turbo    */
+
+       /* The CPU may have less than 4 cores */
+       if (!*turbo_freq)
+               *turbo_freq = msr & 0xFF;         /* 1C turbo    */
 
        return true;
 }
@@ -1972,7 +1974,8 @@ static bool intel_set_max_freq_ratio(void)
            skx_set_max_freq_ratio(&base_freq, &turbo_freq, 1))
                goto out;
 
-       if (knl_set_max_freq_ratio(&base_freq, &turbo_freq, 1))
+       if (x86_match_cpu(has_knl_turbo_ratio_limits) &&
+           knl_set_max_freq_ratio(&base_freq, &turbo_freq, 1))
                goto out;
 
        if (x86_match_cpu(has_skx_turbo_ratio_limits) &&
@@ -1985,13 +1988,22 @@ static bool intel_set_max_freq_ratio(void)
        return false;
 
 out:
+       /*
+        * Some hypervisors advertise X86_FEATURE_APERFMPERF
+        * but then fill all MSR's with zeroes.
+        */
+       if (!base_freq) {
+               pr_debug("Couldn't determine cpu base frequency, necessary for scale-invariant accounting.\n");
+               return false;
+       }
+
        arch_turbo_freq_ratio = div_u64(turbo_freq * SCHED_CAPACITY_SCALE,
                                        base_freq);
        arch_set_max_freq_ratio(turbo_disabled());
        return true;
 }
 
-static void init_counter_refs(void *arg)
+static void init_counter_refs(void)
 {
        u64 aperf, mperf;
 
@@ -2002,18 +2014,25 @@ static void init_counter_refs(void *arg)
        this_cpu_write(arch_prev_mperf, mperf);
 }
 
-static void init_freq_invariance(void)
+static void init_freq_invariance(bool secondary)
 {
        bool ret = false;
 
-       if (smp_processor_id() != 0 || !boot_cpu_has(X86_FEATURE_APERFMPERF))
+       if (!boot_cpu_has(X86_FEATURE_APERFMPERF))
                return;
 
+       if (secondary) {
+               if (static_branch_likely(&arch_scale_freq_key)) {
+                       init_counter_refs();
+               }
+               return;
+       }
+
        if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
                ret = intel_set_max_freq_ratio();
 
        if (ret) {
-               on_each_cpu(init_counter_refs, NULL, 1);
+               init_counter_refs();
                static_branch_enable(&arch_scale_freq_key);
        } else {
                pr_debug("Couldn't determine max cpu frequency, necessary for scale-invariant accounting.\n");
index 4d732a444711fe3ab3abcc6ed01f926918b5a6ff..8d5cbe1bbb3bc0dc674ad868dea0623fe5ae55a8 100644 (file)
@@ -81,7 +81,7 @@
 #define        UMIP_INST_SLDT  3       /* 0F 00 /0 */
 #define        UMIP_INST_STR   4       /* 0F 00 /1 */
 
-const char * const umip_insns[5] = {
+static const char * const umip_insns[5] = {
        [UMIP_INST_SGDT] = "SGDT",
        [UMIP_INST_SIDT] = "SIDT",
        [UMIP_INST_SMSW] = "SMSW",
index a224b5ab103fa60ddd64e0a9a459c53fdb521d77..54226110bc7fd707c56c8d5715b3e776a8586c21 100644 (file)
@@ -344,6 +344,9 @@ bad_address:
        if (IS_ENABLED(CONFIG_X86_32))
                goto the_end;
 
+       if (state->task != current)
+               goto the_end;
+
        if (state->regs) {
                printk_deferred_once(KERN_WARNING
                        "WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n",
index e9cc182aa97eed1d6d23858f5a89b2f663b1c6e9..5b0bd8581fe66709f85c083ed244717625ea47a2 100644 (file)
@@ -8,19 +8,21 @@
 #include <asm/orc_lookup.h>
 
 #define orc_warn(fmt, ...) \
-       printk_deferred_once(KERN_WARNING pr_fmt("WARNING: " fmt), ##__VA_ARGS__)
+       printk_deferred_once(KERN_WARNING "WARNING: " fmt, ##__VA_ARGS__)
+
+#define orc_warn_current(args...)                                      \
+({                                                                     \
+       if (state->task == current)                                     \
+               orc_warn(args);                                         \
+})
 
 extern int __start_orc_unwind_ip[];
 extern int __stop_orc_unwind_ip[];
 extern struct orc_entry __start_orc_unwind[];
 extern struct orc_entry __stop_orc_unwind[];
 
-static DEFINE_MUTEX(sort_mutex);
-int *cur_orc_ip_table = __start_orc_unwind_ip;
-struct orc_entry *cur_orc_table = __start_orc_unwind;
-
-unsigned int lookup_num_blocks;
-bool orc_init;
+static bool orc_init __ro_after_init;
+static unsigned int lookup_num_blocks __ro_after_init;
 
 static inline unsigned long orc_ip(const int *ip)
 {
@@ -142,9 +144,6 @@ static struct orc_entry *orc_find(unsigned long ip)
 {
        static struct orc_entry *orc;
 
-       if (!orc_init)
-               return NULL;
-
        if (ip == 0)
                return &null_orc_entry;
 
@@ -189,6 +188,10 @@ static struct orc_entry *orc_find(unsigned long ip)
 
 #ifdef CONFIG_MODULES
 
+static DEFINE_MUTEX(sort_mutex);
+static int *cur_orc_ip_table = __start_orc_unwind_ip;
+static struct orc_entry *cur_orc_table = __start_orc_unwind;
+
 static void orc_sort_swap(void *_a, void *_b, int size)
 {
        struct orc_entry *orc_a, *orc_b;
@@ -381,9 +384,38 @@ static bool deref_stack_iret_regs(struct unwind_state *state, unsigned long addr
        return true;
 }
 
+/*
+ * If state->regs is non-NULL, and points to a full pt_regs, just get the reg
+ * value from state->regs.
+ *
+ * Otherwise, if state->regs just points to IRET regs, and the previous frame
+ * had full regs, it's safe to get the value from the previous regs.  This can
+ * happen when early/late IRQ entry code gets interrupted by an NMI.
+ */
+static bool get_reg(struct unwind_state *state, unsigned int reg_off,
+                   unsigned long *val)
+{
+       unsigned int reg = reg_off/8;
+
+       if (!state->regs)
+               return false;
+
+       if (state->full_regs) {
+               *val = ((unsigned long *)state->regs)[reg];
+               return true;
+       }
+
+       if (state->prev_regs) {
+               *val = ((unsigned long *)state->prev_regs)[reg];
+               return true;
+       }
+
+       return false;
+}
+
 bool unwind_next_frame(struct unwind_state *state)
 {
-       unsigned long ip_p, sp, orig_ip = state->ip, prev_sp = state->sp;
+       unsigned long ip_p, sp, tmp, orig_ip = state->ip, prev_sp = state->sp;
        enum stack_type prev_type = state->stack_info.type;
        struct orc_entry *orc;
        bool indirect = false;
@@ -445,43 +477,39 @@ bool unwind_next_frame(struct unwind_state *state)
                break;
 
        case ORC_REG_R10:
-               if (!state->regs || !state->full_regs) {
-                       orc_warn("missing regs for base reg R10 at ip %pB\n",
-                                (void *)state->ip);
+               if (!get_reg(state, offsetof(struct pt_regs, r10), &sp)) {
+                       orc_warn_current("missing R10 value at %pB\n",
+                                        (void *)state->ip);
                        goto err;
                }
-               sp = state->regs->r10;
                break;
 
        case ORC_REG_R13:
-               if (!state->regs || !state->full_regs) {
-                       orc_warn("missing regs for base reg R13 at ip %pB\n",
-                                (void *)state->ip);
+               if (!get_reg(state, offsetof(struct pt_regs, r13), &sp)) {
+                       orc_warn_current("missing R13 value at %pB\n",
+                                        (void *)state->ip);
                        goto err;
                }
-               sp = state->regs->r13;
                break;
 
        case ORC_REG_DI:
-               if (!state->regs || !state->full_regs) {
-                       orc_warn("missing regs for base reg DI at ip %pB\n",
-                                (void *)state->ip);
+               if (!get_reg(state, offsetof(struct pt_regs, di), &sp)) {
+                       orc_warn_current("missing RDI value at %pB\n",
+                                        (void *)state->ip);
                        goto err;
                }
-               sp = state->regs->di;
                break;
 
        case ORC_REG_DX:
-               if (!state->regs || !state->full_regs) {
-                       orc_warn("missing regs for base reg DX at ip %pB\n",
-                                (void *)state->ip);
+               if (!get_reg(state, offsetof(struct pt_regs, dx), &sp)) {
+                       orc_warn_current("missing DX value at %pB\n",
+                                        (void *)state->ip);
                        goto err;
                }
-               sp = state->regs->dx;
                break;
 
        default:
-               orc_warn("unknown SP base reg %d for ip %pB\n",
+               orc_warn("unknown SP base reg %d at %pB\n",
                         orc->sp_reg, (void *)state->ip);
                goto err;
        }
@@ -504,44 +532,48 @@ bool unwind_next_frame(struct unwind_state *state)
 
                state->sp = sp;
                state->regs = NULL;
+               state->prev_regs = NULL;
                state->signal = false;
                break;
 
        case ORC_TYPE_REGS:
                if (!deref_stack_regs(state, sp, &state->ip, &state->sp)) {
-                       orc_warn("can't dereference registers at %p for ip %pB\n",
-                                (void *)sp, (void *)orig_ip);
+                       orc_warn_current("can't access registers at %pB\n",
+                                        (void *)orig_ip);
                        goto err;
                }
 
                state->regs = (struct pt_regs *)sp;
+               state->prev_regs = NULL;
                state->full_regs = true;
                state->signal = true;
                break;
 
        case ORC_TYPE_REGS_IRET:
                if (!deref_stack_iret_regs(state, sp, &state->ip, &state->sp)) {
-                       orc_warn("can't dereference iret registers at %p for ip %pB\n",
-                                (void *)sp, (void *)orig_ip);
+                       orc_warn_current("can't access iret registers at %pB\n",
+                                        (void *)orig_ip);
                        goto err;
                }
 
+               if (state->full_regs)
+                       state->prev_regs = state->regs;
                state->regs = (void *)sp - IRET_FRAME_OFFSET;
                state->full_regs = false;
                state->signal = true;
                break;
 
        default:
-               orc_warn("unknown .orc_unwind entry type %d for ip %pB\n",
+               orc_warn("unknown .orc_unwind entry type %d at %pB\n",
                         orc->type, (void *)orig_ip);
-               break;
+               goto err;
        }
 
        /* Find BP: */
        switch (orc->bp_reg) {
        case ORC_REG_UNDEFINED:
-               if (state->regs && state->full_regs)
-                       state->bp = state->regs->bp;
+               if (get_reg(state, offsetof(struct pt_regs, bp), &tmp))
+                       state->bp = tmp;
                break;
 
        case ORC_REG_PREV_SP:
@@ -564,8 +596,8 @@ bool unwind_next_frame(struct unwind_state *state)
        if (state->stack_info.type == prev_type &&
            on_stack(&state->stack_info, (void *)state->sp, sizeof(long)) &&
            state->sp <= prev_sp) {
-               orc_warn("stack going in the wrong direction? ip=%pB\n",
-                        (void *)orig_ip);
+               orc_warn_current("stack going in the wrong direction? at %pB\n",
+                                (void *)orig_ip);
                goto err;
        }
 
@@ -585,6 +617,9 @@ EXPORT_SYMBOL_GPL(unwind_next_frame);
 void __unwind_start(struct unwind_state *state, struct task_struct *task,
                    struct pt_regs *regs, unsigned long *first_frame)
 {
+       if (!orc_init)
+               goto done;
+
        memset(state, 0, sizeof(*state));
        state->task = task;
 
@@ -651,7 +686,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
        /* Otherwise, skip ahead to the user-specified starting frame: */
        while (!unwind_done(state) &&
               (!on_stack(&state->stack_info, first_frame, sizeof(long)) ||
-                       state->sp <= (unsigned long)first_frame))
+                       state->sp < (unsigned long)first_frame))
                unwind_next_frame(state);
 
        return;
index a789759b7261339312e9074320ff5c72dcd02820..4a3081e9f4b5de97c4b90c1858284731088778ce 100644 (file)
@@ -3,6 +3,10 @@
 ccflags-y += -Iarch/x86/kvm
 ccflags-$(CONFIG_KVM_WERROR) += -Werror
 
+ifeq ($(CONFIG_FRAME_POINTER),y)
+OBJECT_FILES_NON_STANDARD_vmenter.o := y
+endif
+
 KVM := ../../../virt/kvm
 
 kvm-y                  += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \
index 750ff0b294047cf83b2c28f72cfbd057375fc7b1..d057376bd3d33ceb24155d6b2d19a7e5fa18a71a 100644 (file)
@@ -225,12 +225,12 @@ static int ioapic_set_irq(struct kvm_ioapic *ioapic, unsigned int irq,
        }
 
        /*
-        * AMD SVM AVIC accelerate EOI write and do not trap,
-        * in-kernel IOAPIC will not be able to receive the EOI.
-        * In this case, we do lazy update of the pending EOI when
-        * trying to set IOAPIC irq.
+        * AMD SVM AVIC accelerate EOI write iff the interrupt is edge
+        * triggered, in which case the in-kernel IOAPIC will not be able
+        * to receive the EOI.  In this case, we do a lazy update of the
+        * pending EOI when trying to set IOAPIC irq.
         */
-       if (kvm_apicv_activated(ioapic->kvm))
+       if (edge && kvm_apicv_activated(ioapic->kvm))
                ioapic_lazy_update_eoi(ioapic, irq);
 
        /*
index 0e3fc311d7da69aac911762d3fd6c93ffc790444..89f7f3aebd31b102eee3e20443455e850fcddef2 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/highmem.h>
 #include <linux/psp-sev.h>
+#include <linux/pagemap.h>
 #include <linux/swap.h>
 
 #include "x86.h"
@@ -344,7 +345,7 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr,
                return NULL;
 
        /* Pin the user virtual address. */
-       npinned = get_user_pages_fast(uaddr, npages, FOLL_WRITE, pages);
+       npinned = get_user_pages_fast(uaddr, npages, write ? FOLL_WRITE : 0, pages);
        if (npinned != npages) {
                pr_err("SEV: Failure locking %lu pages.\n", npages);
                goto err;
@@ -1117,7 +1118,7 @@ int __init sev_hardware_setup(void)
        /* Maximum number of encrypted guests supported simultaneously */
        max_sev_asid = cpuid_ecx(0x8000001F);
 
-       if (!max_sev_asid)
+       if (!svm_sev_enabled())
                return 1;
 
        /* Minimum ASID value that should be used for SEV guest */
@@ -1156,6 +1157,9 @@ err:
 
 void sev_hardware_teardown(void)
 {
+       if (!svm_sev_enabled())
+               return;
+
        bitmap_free(sev_asid_bitmap);
        bitmap_free(sev_reclaim_asid_bitmap);
 
index 2be5bbae3a40f2b0abb809c3be5284327e48a036..38f6aeefeb5537f78af2bcdf22e82dca51271543 100644 (file)
@@ -1752,6 +1752,8 @@ static int db_interception(struct vcpu_svm *svm)
        if (svm->vcpu.guest_debug &
            (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) {
                kvm_run->exit_reason = KVM_EXIT_DEBUG;
+               kvm_run->debug.arch.dr6 = svm->vmcb->save.dr6;
+               kvm_run->debug.arch.dr7 = svm->vmcb->save.dr7;
                kvm_run->debug.arch.pc =
                        svm->vmcb->save.cs.base + svm->vmcb->save.rip;
                kvm_run->debug.arch.exception = DB_VECTOR;
@@ -3276,7 +3278,7 @@ static void svm_cancel_injection(struct kvm_vcpu *vcpu)
        svm_complete_interrupts(svm);
 }
 
-bool __svm_vcpu_run(unsigned long vmcb_pa, unsigned long *regs);
+void __svm_vcpu_run(unsigned long vmcb_pa, unsigned long *regs);
 
 static void svm_vcpu_run(struct kvm_vcpu *vcpu)
 {
@@ -3330,13 +3332,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
         */
        x86_spec_ctrl_set_guest(svm->spec_ctrl, svm->virt_spec_ctrl);
 
-       local_irq_enable();
-
        __svm_vcpu_run(svm->vmcb_pa, (unsigned long *)&svm->vcpu.arch.regs);
 
-       /* Eliminate branch target predictions from guest mode */
-       vmexit_fill_RSB();
-
 #ifdef CONFIG_X86_64
        wrmsrl(MSR_GS_BASE, svm->host.gs_base);
 #else
@@ -3366,8 +3363,6 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
 
        reload_tss(vcpu);
 
-       local_irq_disable();
-
        x86_spec_ctrl_restore_host(svm->spec_ctrl, svm->virt_spec_ctrl);
 
        vcpu->arch.cr2 = svm->vmcb->save.cr2;
@@ -3411,7 +3406,6 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
 
        mark_all_clean(svm->vmcb);
 }
-STACK_FRAME_NON_STANDARD(svm_vcpu_run);
 
 static void svm_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long root)
 {
index fa1af90067e97534227196bc70f7e5dc0e358bda..bf944334003aefa2cc5f1ffe3de34e61a1e6ceb3 100644 (file)
@@ -3,6 +3,7 @@
 #include <asm/asm.h>
 #include <asm/bitsperlong.h>
 #include <asm/kvm_vcpu_regs.h>
+#include <asm/nospec-branch.h>
 
 #define WORD_SIZE (BITS_PER_LONG / 8)
 
@@ -35,7 +36,6 @@
  */
 SYM_FUNC_START(__svm_vcpu_run)
        push %_ASM_BP
-       mov  %_ASM_SP, %_ASM_BP
 #ifdef CONFIG_X86_64
        push %r15
        push %r14
@@ -78,6 +78,7 @@ SYM_FUNC_START(__svm_vcpu_run)
        pop %_ASM_AX
 
        /* Enter guest mode */
+       sti
 1:     vmload %_ASM_AX
        jmp 3f
 2:     cmpb $0, kvm_rebooting
@@ -99,6 +100,13 @@ SYM_FUNC_START(__svm_vcpu_run)
        ud2
        _ASM_EXTABLE(5b, 6b)
 7:
+       cli
+
+#ifdef CONFIG_RETPOLINE
+       /* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
+       FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
+#endif
+
        /* "POP" @regs to RAX. */
        pop %_ASM_AX
 
index cbc9ea2de28f967dbdc77f33fd83d70464568d23..e44f33c82332505b057ae016cf0d5a5c0cba23d0 100644 (file)
@@ -5165,7 +5165,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)
         */
                break;
        default:
-               BUG_ON(1);
+               BUG();
                break;
        }
 
@@ -5533,8 +5533,25 @@ static bool nested_vmx_exit_handled_vmcs_access(struct kvm_vcpu *vcpu,
        return 1 & (b >> (field & 7));
 }
 
+static bool nested_vmx_exit_handled_mtf(struct vmcs12 *vmcs12)
+{
+       u32 entry_intr_info = vmcs12->vm_entry_intr_info_field;
+
+       if (nested_cpu_has_mtf(vmcs12))
+               return true;
+
+       /*
+        * An MTF VM-exit may be injected into the guest by setting the
+        * interruption-type to 7 (other event) and the vector field to 0. Such
+        * is the case regardless of the 'monitor trap flag' VM-execution
+        * control.
+        */
+       return entry_intr_info == (INTR_INFO_VALID_MASK
+                                  | INTR_TYPE_OTHER_EVENT);
+}
+
 /*
- * Return 1 if we should exit from L2 to L1 to handle an exit, or 0 if we
+ * Return true if we should exit from L2 to L1 to handle an exit, or false if we
  * should handle it ourselves in L0 (and then continue L2). Only call this
  * when in is_guest_mode (L2).
  */
@@ -5633,7 +5650,7 @@ bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason)
        case EXIT_REASON_MWAIT_INSTRUCTION:
                return nested_cpu_has(vmcs12, CPU_BASED_MWAIT_EXITING);
        case EXIT_REASON_MONITOR_TRAP_FLAG:
-               return nested_cpu_has_mtf(vmcs12);
+               return nested_vmx_exit_handled_mtf(vmcs12);
        case EXIT_REASON_MONITOR_INSTRUCTION:
                return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_EXITING);
        case EXIT_REASON_PAUSE_INSTRUCTION:
index 87f3f24fef37b45980fae9bfbdb19e9485c87a61..51d1a82742fd5ba11b0b18f545b37edf5d3e6767 100644 (file)
@@ -82,6 +82,9 @@ SYM_FUNC_START(vmx_vmexit)
        /* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
        FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
 
+       /* Clear RFLAGS.CF and RFLAGS.ZF to preserve VM-Exit, i.e. !VM-Fail. */
+       or $1, %_ASM_AX
+
        pop %_ASM_AX
 .Lvmexit_skip_rsb:
 #endif
index 83050977490c6bfc86a299e5456ff025831a085b..c2c6335a998c2f09f7f608b38e52403765c65e22 100644 (file)
@@ -4572,7 +4572,7 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu,
  */
 static void kvm_machine_check(void)
 {
-#if defined(CONFIG_X86_MCE) && defined(CONFIG_X86_64)
+#if defined(CONFIG_X86_MCE)
        struct pt_regs regs = {
                .cs = 3, /* Fake ring 3 no matter what the guest ran on */
                .flags = X86_EFLAGS_IF,
index 3bf2ecafd0270f9ab484ecb2b503d5afea2fd616..d786c7d27ce5cd8402d900fe6bf35968c1d9d513 100644 (file)
@@ -926,19 +926,6 @@ EXPORT_SYMBOL_GPL(kvm_set_xcr);
        __reserved_bits;                                \
 })
 
-static u64 kvm_host_cr4_reserved_bits(struct cpuinfo_x86 *c)
-{
-       u64 reserved_bits = __cr4_reserved_bits(cpu_has, c);
-
-       if (kvm_cpu_cap_has(X86_FEATURE_LA57))
-               reserved_bits &= ~X86_CR4_LA57;
-
-       if (kvm_cpu_cap_has(X86_FEATURE_UMIP))
-               reserved_bits &= ~X86_CR4_UMIP;
-
-       return reserved_bits;
-}
-
 static int kvm_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
        if (cr4 & cr4_reserved_bits)
@@ -3060,6 +3047,17 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        case MSR_IA32_PERF_CTL:
        case MSR_AMD64_DC_CFG:
        case MSR_F15H_EX_CFG:
+       /*
+        * Intel Sandy Bridge CPUs must support the RAPL (running average power
+        * limit) MSRs. Just return 0, as we do not want to expose the host
+        * data here. Do not conditionalize this on CPUID, as KVM does not do
+        * so for existing CPU-specific MSRs.
+        */
+       case MSR_RAPL_POWER_UNIT:
+       case MSR_PP0_ENERGY_STATUS:     /* Power plane 0 (core) */
+       case MSR_PP1_ENERGY_STATUS:     /* Power plane 1 (graphics uncore) */
+       case MSR_PKG_ENERGY_STATUS:     /* Total package */
+       case MSR_DRAM_ENERGY_STATUS:    /* DRAM controller */
                msr_info->data = 0;
                break;
        case MSR_F15H_PERF_CTL0 ... MSR_F15H_PERF_CTR5:
@@ -3374,6 +3372,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_GET_MSR_FEATURES:
        case KVM_CAP_MSR_PLATFORM_INFO:
        case KVM_CAP_EXCEPTION_PAYLOAD:
+       case KVM_CAP_SET_GUEST_DEBUG:
                r = 1;
                break;
        case KVM_CAP_SYNC_REGS:
@@ -5049,10 +5048,13 @@ set_identity_unlock:
                r = -EFAULT;
                if (copy_from_user(&u.ps, argp, sizeof(u.ps)))
                        goto out;
+               mutex_lock(&kvm->lock);
                r = -ENXIO;
                if (!kvm->arch.vpit)
-                       goto out;
+                       goto set_pit_out;
                r = kvm_vm_ioctl_set_pit(kvm, &u.ps);
+set_pit_out:
+               mutex_unlock(&kvm->lock);
                break;
        }
        case KVM_GET_PIT2: {
@@ -5072,10 +5074,13 @@ set_identity_unlock:
                r = -EFAULT;
                if (copy_from_user(&u.ps2, argp, sizeof(u.ps2)))
                        goto out;
+               mutex_lock(&kvm->lock);
                r = -ENXIO;
                if (!kvm->arch.vpit)
-                       goto out;
+                       goto set_pit2_out;
                r = kvm_vm_ioctl_set_pit2(kvm, &u.ps2);
+set_pit2_out:
+               mutex_unlock(&kvm->lock);
                break;
        }
        case KVM_REINJECT_CONTROL: {
@@ -9658,7 +9663,9 @@ int kvm_arch_hardware_setup(void *opaque)
        if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
                supported_xss = 0;
 
-       cr4_reserved_bits = kvm_host_cr4_reserved_bits(&boot_cpu_data);
+#define __kvm_cpu_cap_has(UNUSED_, f) kvm_cpu_cap_has(f)
+       cr4_reserved_bits = __cr4_reserved_bits(__kvm_cpu_cap_has, UNUSED_);
+#undef __kvm_cpu_cap_has
 
        if (kvm_has_tsc_control) {
                /*
@@ -9690,7 +9697,8 @@ int kvm_arch_check_processor_compat(void *opaque)
 
        WARN_ON(!irqs_disabled());
 
-       if (kvm_host_cr4_reserved_bits(c) != cr4_reserved_bits)
+       if (__cr4_reserved_bits(cpu_has, c) !=
+           __cr4_reserved_bits(cpu_has, &boot_cpu_data))
                return -EIO;
 
        return ops->check_processor_compatibility();
index 59eca6a94ce7961ace4cd6588a4f7cc5df48294b..b8c55a2e402d3d5a6e53da82cec81a78f68fc675 100644 (file)
@@ -43,7 +43,8 @@ struct cpa_data {
        unsigned long   pfn;
        unsigned int    flags;
        unsigned int    force_split             : 1,
-                       force_static_prot       : 1;
+                       force_static_prot       : 1,
+                       force_flush_all         : 1;
        struct page     **pages;
 };
 
@@ -355,10 +356,10 @@ static void cpa_flush(struct cpa_data *data, int cache)
                return;
        }
 
-       if (cpa->numpages <= tlb_single_page_flush_ceiling)
-               on_each_cpu(__cpa_flush_tlb, cpa, 1);
-       else
+       if (cpa->force_flush_all || cpa->numpages > tlb_single_page_flush_ceiling)
                flush_tlb_all();
+       else
+               on_each_cpu(__cpa_flush_tlb, cpa, 1);
 
        if (!cache)
                return;
@@ -1598,6 +1599,8 @@ static int cpa_process_alias(struct cpa_data *cpa)
                alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
                alias_cpa.curpage = 0;
 
+               cpa->force_flush_all = 1;
+
                ret = __change_page_attr_set_clr(&alias_cpa, 0);
                if (ret)
                        return ret;
@@ -1618,6 +1621,7 @@ static int cpa_process_alias(struct cpa_data *cpa)
                alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
                alias_cpa.curpage = 0;
 
+               cpa->force_flush_all = 1;
                /*
                 * The high mapping range is imprecise, so ignore the
                 * return value.
index 5ea7c2cf7ab4eea153625e38dc4820fcf69a1030..42b6709e6dc7ca002cc8653446bdba62ff83f182 100644 (file)
@@ -158,6 +158,19 @@ static bool is_ereg(u32 reg)
                             BIT(BPF_REG_AX));
 }
 
+/*
+ * is_ereg_8l() == true if BPF register 'reg' is mapped to access x86-64
+ * lower 8-bit registers dil,sil,bpl,spl,r8b..r15b, which need extra byte
+ * of encoding. al,cl,dl,bl have simpler encoding.
+ */
+static bool is_ereg_8l(u32 reg)
+{
+       return is_ereg(reg) ||
+           (1 << reg) & (BIT(BPF_REG_1) |
+                         BIT(BPF_REG_2) |
+                         BIT(BPF_REG_FP));
+}
+
 static bool is_axreg(u32 reg)
 {
        return reg == BPF_REG_0;
@@ -598,9 +611,8 @@ static void emit_stx(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, int off)
        switch (size) {
        case BPF_B:
                /* Emit 'mov byte ptr [rax + off], al' */
-               if (is_ereg(dst_reg) || is_ereg(src_reg) ||
-                   /* We have to add extra byte for x86 SIL, DIL regs */
-                   src_reg == BPF_REG_1 || src_reg == BPF_REG_2)
+               if (is_ereg(dst_reg) || is_ereg_8l(src_reg))
+                       /* Add extra byte for eregs or SIL,DIL,BPL in src_reg */
                        EMIT2(add_2mod(0x40, dst_reg, src_reg), 0x88);
                else
                        EMIT1(0x88);
index 4d2a7a76460262a537bc242c4f3468ea1d0ee15b..66cd150b7e541d77302819298284ec3b81c54b12 100644 (file)
@@ -1847,14 +1847,16 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
                        case BPF_B:
                        case BPF_H:
                        case BPF_W:
-                               if (!bpf_prog->aux->verifier_zext)
+                               if (bpf_prog->aux->verifier_zext)
                                        break;
                                if (dstk) {
                                        EMIT3(0xC7, add_1reg(0x40, IA32_EBP),
                                              STACK_VAR(dst_hi));
                                        EMIT(0x0, 4);
                                } else {
-                                       EMIT3(0xC7, add_1reg(0xC0, dst_hi), 0);
+                                       /* xor dst_hi,dst_hi */
+                                       EMIT2(0x33,
+                                             add_2reg(0xC0, dst_hi, dst_hi));
                                }
                                break;
                        case BPF_DW:
@@ -2013,8 +2015,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
                case BPF_JMP | BPF_JSET | BPF_X:
                case BPF_JMP32 | BPF_JSET | BPF_X: {
                        bool is_jmp64 = BPF_CLASS(insn->code) == BPF_JMP;
-                       u8 dreg_lo = dstk ? IA32_EAX : dst_lo;
-                       u8 dreg_hi = dstk ? IA32_EDX : dst_hi;
+                       u8 dreg_lo = IA32_EAX;
+                       u8 dreg_hi = IA32_EDX;
                        u8 sreg_lo = sstk ? IA32_ECX : src_lo;
                        u8 sreg_hi = sstk ? IA32_EBX : src_hi;
 
@@ -2026,6 +2028,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
                                              add_2reg(0x40, IA32_EBP,
                                                       IA32_EDX),
                                              STACK_VAR(dst_hi));
+                       } else {
+                               /* mov dreg_lo,dst_lo */
+                               EMIT2(0x89, add_2reg(0xC0, dreg_lo, dst_lo));
+                               if (is_jmp64)
+                                       /* mov dreg_hi,dst_hi */
+                                       EMIT2(0x89,
+                                             add_2reg(0xC0, dreg_hi, dst_hi));
                        }
 
                        if (sstk) {
@@ -2050,8 +2059,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
                case BPF_JMP | BPF_JSET | BPF_K:
                case BPF_JMP32 | BPF_JSET | BPF_K: {
                        bool is_jmp64 = BPF_CLASS(insn->code) == BPF_JMP;
-                       u8 dreg_lo = dstk ? IA32_EAX : dst_lo;
-                       u8 dreg_hi = dstk ? IA32_EDX : dst_hi;
+                       u8 dreg_lo = IA32_EAX;
+                       u8 dreg_hi = IA32_EDX;
                        u8 sreg_lo = IA32_ECX;
                        u8 sreg_hi = IA32_EBX;
                        u32 hi;
@@ -2064,6 +2073,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
                                              add_2reg(0x40, IA32_EBP,
                                                       IA32_EDX),
                                              STACK_VAR(dst_hi));
+                       } else {
+                               /* mov dreg_lo,dst_lo */
+                               EMIT2(0x89, add_2reg(0xC0, dreg_lo, dst_lo));
+                               if (is_jmp64)
+                                       /* mov dreg_hi,dst_hi */
+                                       EMIT2(0x89,
+                                             add_2reg(0xC0, dreg_hi, dst_hi));
                        }
 
                        /* mov ecx,imm32 */
index 211bb9358b733e84ca9fe65b1b7be6670db892a9..c5e393f8bb3f6363f47d94f42465155a2e333179 100644 (file)
@@ -202,7 +202,7 @@ virt_to_phys_or_null_size(void *va, unsigned long size)
 
 int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 {
-       unsigned long pfn, text, pf;
+       unsigned long pfn, text, pf, rodata;
        struct page *page;
        unsigned npages;
        pgd_t *pgd = efi_mm.pgd;
@@ -256,7 +256,7 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 
        efi_scratch.phys_stack = page_to_phys(page + 1); /* stack grows down */
 
-       npages = (__end_rodata_aligned - _text) >> PAGE_SHIFT;
+       npages = (_etext - _text) >> PAGE_SHIFT;
        text = __pa(_text);
        pfn = text >> PAGE_SHIFT;
 
@@ -266,6 +266,14 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
                return 1;
        }
 
+       npages = (__end_rodata - __start_rodata) >> PAGE_SHIFT;
+       rodata = __pa(__start_rodata);
+       pfn = rodata >> PAGE_SHIFT;
+       if (kernel_map_pages_in_pgd(pgd, pfn, rodata, npages, pf)) {
+               pr_err("Failed to map kernel rodata 1:1\n");
+               return 1;
+       }
+
        return 0;
 }
 
@@ -638,7 +646,7 @@ efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor,
        phys_vendor = virt_to_phys_or_null(vnd);
        phys_data = virt_to_phys_or_null_size(data, data_size);
 
-       if (!phys_name || !phys_data)
+       if (!phys_name || (data && !phys_data))
                status = EFI_INVALID_PARAMETER;
        else
                status = efi_thunk(set_variable, phys_name, phys_vendor,
@@ -669,7 +677,7 @@ efi_thunk_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
        phys_vendor = virt_to_phys_or_null(vnd);
        phys_data = virt_to_phys_or_null_size(data, data_size);
 
-       if (!phys_name || !phys_data)
+       if (!phys_name || (data && !phys_data))
                status = EFI_INVALID_PARAMETER;
        else
                status = efi_thunk(set_variable, phys_name, phys_vendor,
similarity index 57%
rename from arch/xtensa/include/asm/module.h
rename to arch/xtensa/include/asm/vermagic.h
index 488b40c6f9b9aa89fcf0cce02d33e9bd6bfa6274..6d9c670e4ba98843029effc73e20738e344ad376 100644 (file)
@@ -1,8 +1,4 @@
 /*
- * include/asm-xtensa/module.h
- *
- * This file contains the module code specific to the Xtensa architecture.
- *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  * Copyright (C) 2001 - 2005 Tensilica Inc.
  */
 
-#ifndef _XTENSA_MODULE_H
-#define _XTENSA_MODULE_H
+#ifndef _ASM_VERMAGIC_H
+#define _ASM_VERMAGIC_H
 
-#define MODULE_ARCH_VERMAGIC "xtensa-" __stringify(XCHAL_CORE_ID) " "
+#include <linux/stringify.h>
+#include <variant/core.h>
 
-#include <asm-generic/module.h>
+#define MODULE_ARCH_VERMAGIC "xtensa-" __stringify(XCHAL_CORE_ID) " "
 
-#endif /* _XTENSA_MODULE_H */
+#endif /* _ASM_VERMAGIC_H */
index 78ba57efd16b5fe3dca4af5108c7e7cce46b2def..3d411716d7ee4d2a4c57df277adb95ce32d2ab8d 100644 (file)
 #include <linux/ioprio.h>
 #include <linux/sbitmap.h>
 #include <linux/delay.h>
+#include <linux/backing-dev.h>
 
 #include "blk.h"
 #include "blk-mq.h"
@@ -4976,8 +4977,9 @@ bfq_set_next_ioprio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic)
        ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio);
        switch (ioprio_class) {
        default:
-               dev_err(bfqq->bfqd->queue->backing_dev_info->dev,
-                       "bfq: bad prio class %d\n", ioprio_class);
+               pr_err("bdi %s: bfq: bad prio class %d\n",
+                               bdi_dev_name(bfqq->bfqd->queue->backing_dev_info),
+                               ioprio_class);
                /* fall through */
        case IOPRIO_CLASS_NONE:
                /*
index c5dc833212e1d1a58fdf55f4686c421e3e34a55d..930212c1a5129c18b0d685827a48ebeb799774fc 100644 (file)
@@ -496,7 +496,7 @@ const char *blkg_dev_name(struct blkcg_gq *blkg)
 {
        /* some drivers (floppy) instantiate a queue w/o disk registered */
        if (blkg->q->backing_dev_info->dev)
-               return dev_name(blkg->q->backing_dev_info->dev);
+               return bdi_dev_name(blkg->q->backing_dev_info);
        return NULL;
 }
 
index db35ee682294c138ec78a048a34bd80aeb860a7d..7c1fe605d0d6cb2a3de837977653c187b626c040 100644 (file)
@@ -466,7 +466,7 @@ struct ioc_gq {
         */
        atomic64_t                      vtime;
        atomic64_t                      done_vtime;
-       atomic64_t                      abs_vdebt;
+       u64                             abs_vdebt;
        u64                             last_vtime;
 
        /*
@@ -1142,7 +1142,7 @@ static void iocg_kick_waitq(struct ioc_gq *iocg, struct ioc_now *now)
        struct iocg_wake_ctx ctx = { .iocg = iocg };
        u64 margin_ns = (u64)(ioc->period_us *
                              WAITQ_TIMER_MARGIN_PCT / 100) * NSEC_PER_USEC;
-       u64 abs_vdebt, vdebt, vshortage, expires, oexpires;
+       u64 vdebt, vshortage, expires, oexpires;
        s64 vbudget;
        u32 hw_inuse;
 
@@ -1152,18 +1152,15 @@ static void iocg_kick_waitq(struct ioc_gq *iocg, struct ioc_now *now)
        vbudget = now->vnow - atomic64_read(&iocg->vtime);
 
        /* pay off debt */
-       abs_vdebt = atomic64_read(&iocg->abs_vdebt);
-       vdebt = abs_cost_to_cost(abs_vdebt, hw_inuse);
+       vdebt = abs_cost_to_cost(iocg->abs_vdebt, hw_inuse);
        if (vdebt && vbudget > 0) {
                u64 delta = min_t(u64, vbudget, vdebt);
                u64 abs_delta = min(cost_to_abs_cost(delta, hw_inuse),
-                                   abs_vdebt);
+                                   iocg->abs_vdebt);
 
                atomic64_add(delta, &iocg->vtime);
                atomic64_add(delta, &iocg->done_vtime);
-               atomic64_sub(abs_delta, &iocg->abs_vdebt);
-               if (WARN_ON_ONCE(atomic64_read(&iocg->abs_vdebt) < 0))
-                       atomic64_set(&iocg->abs_vdebt, 0);
+               iocg->abs_vdebt -= abs_delta;
        }
 
        /*
@@ -1219,12 +1216,18 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now, u64 cost)
        u64 expires, oexpires;
        u32 hw_inuse;
 
+       lockdep_assert_held(&iocg->waitq.lock);
+
        /* debt-adjust vtime */
        current_hweight(iocg, NULL, &hw_inuse);
-       vtime += abs_cost_to_cost(atomic64_read(&iocg->abs_vdebt), hw_inuse);
+       vtime += abs_cost_to_cost(iocg->abs_vdebt, hw_inuse);
 
-       /* clear or maintain depending on the overage */
-       if (time_before_eq64(vtime, now->vnow)) {
+       /*
+        * Clear or maintain depending on the overage. Non-zero vdebt is what
+        * guarantees that @iocg is online and future iocg_kick_delay() will
+        * clear use_delay. Don't leave it on when there's no vdebt.
+        */
+       if (!iocg->abs_vdebt || time_before_eq64(vtime, now->vnow)) {
                blkcg_clear_delay(blkg);
                return false;
        }
@@ -1258,9 +1261,12 @@ static enum hrtimer_restart iocg_delay_timer_fn(struct hrtimer *timer)
 {
        struct ioc_gq *iocg = container_of(timer, struct ioc_gq, delay_timer);
        struct ioc_now now;
+       unsigned long flags;
 
+       spin_lock_irqsave(&iocg->waitq.lock, flags);
        ioc_now(iocg->ioc, &now);
        iocg_kick_delay(iocg, &now, 0);
+       spin_unlock_irqrestore(&iocg->waitq.lock, flags);
 
        return HRTIMER_NORESTART;
 }
@@ -1368,14 +1374,13 @@ static void ioc_timer_fn(struct timer_list *timer)
         * should have woken up in the last period and expire idle iocgs.
         */
        list_for_each_entry_safe(iocg, tiocg, &ioc->active_iocgs, active_list) {
-               if (!waitqueue_active(&iocg->waitq) &&
-                   !atomic64_read(&iocg->abs_vdebt) && !iocg_is_idle(iocg))
+               if (!waitqueue_active(&iocg->waitq) && iocg->abs_vdebt &&
+                   !iocg_is_idle(iocg))
                        continue;
 
                spin_lock(&iocg->waitq.lock);
 
-               if (waitqueue_active(&iocg->waitq) ||
-                   atomic64_read(&iocg->abs_vdebt)) {
+               if (waitqueue_active(&iocg->waitq) || iocg->abs_vdebt) {
                        /* might be oversleeping vtime / hweight changes, kick */
                        iocg_kick_waitq(iocg, &now);
                        iocg_kick_delay(iocg, &now, 0);
@@ -1591,7 +1596,7 @@ skip_surplus_transfers:
                                      vrate_min, vrate_max);
                }
 
-               trace_iocost_ioc_vrate_adj(ioc, vrate, &missed_ppm, rq_wait_pct,
+               trace_iocost_ioc_vrate_adj(ioc, vrate, missed_ppm, rq_wait_pct,
                                           nr_lagging, nr_shortages,
                                           nr_surpluses);
 
@@ -1600,7 +1605,7 @@ skip_surplus_transfers:
                        ioc->period_us * vrate * INUSE_MARGIN_PCT, 100);
        } else if (ioc->busy_level != prev_busy_level || nr_lagging) {
                trace_iocost_ioc_vrate_adj(ioc, atomic64_read(&ioc->vtime_rate),
-                                          &missed_ppm, rq_wait_pct, nr_lagging,
+                                          missed_ppm, rq_wait_pct, nr_lagging,
                                           nr_shortages, nr_surpluses);
        }
 
@@ -1718,28 +1723,49 @@ static void ioc_rqos_throttle(struct rq_qos *rqos, struct bio *bio)
         * tests are racy but the races aren't systemic - we only miss once
         * in a while which is fine.
         */
-       if (!waitqueue_active(&iocg->waitq) &&
-           !atomic64_read(&iocg->abs_vdebt) &&
+       if (!waitqueue_active(&iocg->waitq) && !iocg->abs_vdebt &&
            time_before_eq64(vtime + cost, now.vnow)) {
                iocg_commit_bio(iocg, bio, cost);
                return;
        }
 
        /*
-        * We're over budget.  If @bio has to be issued regardless,
-        * remember the abs_cost instead of advancing vtime.
-        * iocg_kick_waitq() will pay off the debt before waking more IOs.
+        * We activated above but w/o any synchronization. Deactivation is
+        * synchronized with waitq.lock and we won't get deactivated as long
+        * as we're waiting or has debt, so we're good if we're activated
+        * here. In the unlikely case that we aren't, just issue the IO.
+        */
+       spin_lock_irq(&iocg->waitq.lock);
+
+       if (unlikely(list_empty(&iocg->active_list))) {
+               spin_unlock_irq(&iocg->waitq.lock);
+               iocg_commit_bio(iocg, bio, cost);
+               return;
+       }
+
+       /*
+        * We're over budget. If @bio has to be issued regardless, remember
+        * the abs_cost instead of advancing vtime. iocg_kick_waitq() will pay
+        * off the debt before waking more IOs.
+        *
         * This way, the debt is continuously paid off each period with the
-        * actual budget available to the cgroup.  If we just wound vtime,
-        * we would incorrectly use the current hw_inuse for the entire
-        * amount which, for example, can lead to the cgroup staying
-        * blocked for a long time even with substantially raised hw_inuse.
+        * actual budget available to the cgroup. If we just wound vtime, we
+        * would incorrectly use the current hw_inuse for the entire amount
+        * which, for example, can lead to the cgroup staying blocked for a
+        * long time even with substantially raised hw_inuse.
+        *
+        * An iocg with vdebt should stay online so that the timer can keep
+        * deducting its vdebt and [de]activate use_delay mechanism
+        * accordingly. We don't want to race against the timer trying to
+        * clear them and leave @iocg inactive w/ dangling use_delay heavily
+        * penalizing the cgroup and its descendants.
         */
        if (bio_issue_as_root_blkg(bio) || fatal_signal_pending(current)) {
-               atomic64_add(abs_cost, &iocg->abs_vdebt);
+               iocg->abs_vdebt += abs_cost;
                if (iocg_kick_delay(iocg, &now, cost))
                        blkcg_schedule_throttle(rqos->q,
                                        (bio->bi_opf & REQ_SWAP) == REQ_SWAP);
+               spin_unlock_irq(&iocg->waitq.lock);
                return;
        }
 
@@ -1756,20 +1782,6 @@ static void ioc_rqos_throttle(struct rq_qos *rqos, struct bio *bio)
         * All waiters are on iocg->waitq and the wait states are
         * synchronized using waitq.lock.
         */
-       spin_lock_irq(&iocg->waitq.lock);
-
-       /*
-        * We activated above but w/o any synchronization.  Deactivation is
-        * synchronized with waitq.lock and we won't get deactivated as
-        * long as we're waiting, so we're good if we're activated here.
-        * In the unlikely case that we are deactivated, just issue the IO.
-        */
-       if (unlikely(list_empty(&iocg->active_list))) {
-               spin_unlock_irq(&iocg->waitq.lock);
-               iocg_commit_bio(iocg, bio, cost);
-               return;
-       }
-
        init_waitqueue_func_entry(&wait.wait, iocg_wake_fn);
        wait.wait.private = current;
        wait.bio = bio;
@@ -1801,6 +1813,7 @@ static void ioc_rqos_merge(struct rq_qos *rqos, struct request *rq,
        struct ioc_now now;
        u32 hw_inuse;
        u64 abs_cost, cost;
+       unsigned long flags;
 
        /* bypass if disabled or for root cgroup */
        if (!ioc->enabled || !iocg->level)
@@ -1820,15 +1833,28 @@ static void ioc_rqos_merge(struct rq_qos *rqos, struct request *rq,
                iocg->cursor = bio_end;
 
        /*
-        * Charge if there's enough vtime budget and the existing request
-        * has cost assigned.  Otherwise, account it as debt.  See debt
-        * handling in ioc_rqos_throttle() for details.
+        * Charge if there's enough vtime budget and the existing request has
+        * cost assigned.
         */
        if (rq->bio && rq->bio->bi_iocost_cost &&
-           time_before_eq64(atomic64_read(&iocg->vtime) + cost, now.vnow))
+           time_before_eq64(atomic64_read(&iocg->vtime) + cost, now.vnow)) {
                iocg_commit_bio(iocg, bio, cost);
-       else
-               atomic64_add(abs_cost, &iocg->abs_vdebt);
+               return;
+       }
+
+       /*
+        * Otherwise, account it as debt if @iocg is online, which it should
+        * be for the vast majority of cases. See debt handling in
+        * ioc_rqos_throttle() for details.
+        */
+       spin_lock_irqsave(&iocg->waitq.lock, flags);
+       if (likely(!list_empty(&iocg->active_list))) {
+               iocg->abs_vdebt += abs_cost;
+               iocg_kick_delay(iocg, &now, cost);
+       } else {
+               iocg_commit_bio(iocg, bio, cost);
+       }
+       spin_unlock_irqrestore(&iocg->waitq.lock, flags);
 }
 
 static void ioc_rqos_done_bio(struct rq_qos *rqos, struct bio *bio)
@@ -1998,7 +2024,6 @@ static void ioc_pd_init(struct blkg_policy_data *pd)
        iocg->ioc = ioc;
        atomic64_set(&iocg->vtime, now.vnow);
        atomic64_set(&iocg->done_vtime, now.vnow);
-       atomic64_set(&iocg->abs_vdebt, 0);
        atomic64_set(&iocg->active_period, atomic64_read(&ioc->cur_period));
        INIT_LIST_HEAD(&iocg->active_list);
        iocg->hweight_active = HWEIGHT_WHOLE;
index 8e56884fd2e92643f1f7ecc32380ea245740c610..a7785df2c94462b9fb9d18faa2fcecb8c4fd8dfd 100644 (file)
@@ -1222,8 +1222,10 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list,
                rq = list_first_entry(list, struct request, queuelist);
 
                hctx = rq->mq_hctx;
-               if (!got_budget && !blk_mq_get_dispatch_budget(hctx))
+               if (!got_budget && !blk_mq_get_dispatch_budget(hctx)) {
+                       blk_mq_put_driver_tag(rq);
                        break;
+               }
 
                if (!blk_mq_get_driver_tag(rq)) {
                        /*
index 8641ba9793c5fb0831eebb5743935771b38da5ac..9cb082f38b936e8909735558e0a8512ba331b684 100644 (file)
@@ -313,7 +313,7 @@ static void scale_up(struct rq_wb *rwb)
        calc_wb_limits(rwb);
        rwb->unknown_cnt = 0;
        rwb_wake_all(rwb);
-       rwb_trace_step(rwb, "scale up");
+       rwb_trace_step(rwb, tracepoint_string("scale up"));
 }
 
 static void scale_down(struct rq_wb *rwb, bool hard_throttle)
@@ -322,7 +322,7 @@ static void scale_down(struct rq_wb *rwb, bool hard_throttle)
                return;
        calc_wb_limits(rwb);
        rwb->unknown_cnt = 0;
-       rwb_trace_step(rwb, "scale down");
+       rwb_trace_step(rwb, tracepoint_string("scale down"));
 }
 
 static void rwb_arm_timer(struct rq_wb *rwb)
index bc1ded1331b148b5317a662f6f3a97a86ec3f4d1..9ef48a8cff867268830e0b06ac2c8d91f8a521fc 100644 (file)
@@ -496,7 +496,7 @@ int blk_drop_partitions(struct gendisk *disk, struct block_device *bdev)
 
        if (!disk_part_scan_enabled(disk))
                return 0;
-       if (bdev->bd_part_count || bdev->bd_openers > 1)
+       if (bdev->bd_part_count)
                return -EBUSY;
        res = invalidate_partition(disk, 0);
        if (res)
index 376d7ed3f1f8715d0da884425fabcf41b74149a9..3c734b81b3a20108a4b7292bf17d2e6c179fcfb1 100644 (file)
@@ -287,7 +287,7 @@ static void exit_tfm(struct crypto_skcipher *tfm)
        crypto_free_skcipher(ctx->child);
 }
 
-static void free(struct skcipher_instance *inst)
+static void free_inst(struct skcipher_instance *inst)
 {
        crypto_drop_skcipher(skcipher_instance_ctx(inst));
        kfree(inst);
@@ -400,12 +400,12 @@ static int create(struct crypto_template *tmpl, struct rtattr **tb)
        inst->alg.encrypt = encrypt;
        inst->alg.decrypt = decrypt;
 
-       inst->free = free;
+       inst->free = free_inst;
 
        err = skcipher_register_instance(tmpl, inst);
        if (err) {
 err_free_inst:
-               free(inst);
+               free_inst(inst);
        }
        return err;
 }
index dbdd8af629e6963fd4b8de6d9b15d26fa5232ee9..6d8cea94b3cfbbc276014c3b831c640a99e0fd6f 100644 (file)
@@ -322,7 +322,7 @@ static void exit_tfm(struct crypto_skcipher *tfm)
        crypto_free_cipher(ctx->tweak);
 }
 
-static void free(struct skcipher_instance *inst)
+static void free_inst(struct skcipher_instance *inst)
 {
        crypto_drop_skcipher(skcipher_instance_ctx(inst));
        kfree(inst);
@@ -434,12 +434,12 @@ static int create(struct crypto_template *tmpl, struct rtattr **tb)
        inst->alg.encrypt = encrypt;
        inst->alg.decrypt = decrypt;
 
-       inst->free = free;
+       inst->free = free_inst;
 
        err = skcipher_register_instance(tmpl, inst);
        if (err) {
 err_free_inst:
-               free(inst);
+               free_inst(inst);
        }
        return err;
 }
index 00112cf1532203da1b04144975b4069779b128e0..78cfc70cb3209c8997d297cf9274815163bbd477 100644 (file)
@@ -87,18 +87,6 @@ static const struct dmi_system_id dmi_lid_quirks[] = {
                },
                .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_DISABLED,
        },
-       {
-               /*
-                * Asus T200TA, _LID keeps reporting closed after every second
-                * openening of the lid. Causing immediate re-suspend after
-                * opening every other open. Using LID_INIT_OPEN fixes this.
-                */
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "T200TA"),
-               },
-               .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
-       },
        {
                /* GP-electronic T701, _LID method points to a floating GPIO */
                .matches = {
index b2263ec67b432e14cca0df18434fed68cab0373e..5832bc10aca8d5ff93354df2bcf59d00fd67640d 100644 (file)
@@ -273,13 +273,13 @@ int acpi_device_set_power(struct acpi_device *device, int state)
  end:
        if (result) {
                dev_warn(&device->dev, "Failed to change power state to %s\n",
-                        acpi_power_state_string(state));
+                        acpi_power_state_string(target_state));
        } else {
                device->power.state = target_state;
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Device [%s] transitioned to %s\n",
                                  device->pnp.bus_id,
-                                 acpi_power_state_string(state)));
+                                 acpi_power_state_string(target_state)));
        }
 
        return result;
index 00a6da2121be30bd08de4bcbe2f9a6e9a12c4488..ed3d2182cf2c0a0eb80624876ce66ef6cba02566 100644 (file)
@@ -322,10 +322,10 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
                resource->res.data.extended_irq.polarity =
                    link->irq.polarity;
                if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
-                       resource->res.data.irq.shareable =
+                       resource->res.data.extended_irq.shareable =
                            ACPI_EXCLUSIVE;
                else
-                       resource->res.data.irq.shareable = ACPI_SHARED;
+                       resource->res.data.extended_irq.shareable = ACPI_SHARED;
                resource->res.data.extended_irq.interrupt_count = 1;
                resource->res.data.extended_irq.interrupts[0] = irq;
                /* ignore resource_source, it's optional */
index fe1523664816a49712c88b4afcdc9ee65011b955..8558b629880b17ae4906f6ee22dfa3a10e6d2e29 100644 (file)
@@ -645,6 +645,7 @@ static void amba_device_initialize(struct amba_device *dev, const char *name)
        dev->dev.release = amba_device_release;
        dev->dev.bus = &amba_bustype;
        dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
+       dev->dev.dma_parms = &dev->dma_parms;
        dev->res.name = dev_name(&dev->dev);
 }
 
index 0101b65250cb2d86e021b36eaf75c861f4de8a29..0c0a736eb8613d16e9ef597c7ce179d2595bd169 100644 (file)
@@ -410,6 +410,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x22a3), board_ahci_mobile }, /* Cherry Tr. AHCI */
        { PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_mobile }, /* ApolloLake AHCI */
        { PCI_VDEVICE(INTEL, 0x34d3), board_ahci_mobile }, /* Ice Lake LP AHCI */
+       { PCI_VDEVICE(INTEL, 0x02d3), board_ahci_mobile }, /* Comet Lake PCH-U AHCI */
        { PCI_VDEVICE(INTEL, 0x02d7), board_ahci_mobile }, /* Comet Lake PCH RAID */
 
        /* JMicron 360/1/3/5/6, match class to avoid IDE function */
index a6b76cc12a66192aa21ad20aae68e2e8175944a9..e517bd8822a5faaeef2039a356518ed5a4e970da 100644 (file)
@@ -145,7 +145,7 @@ enum {
 
        /* PORT_IDMA_CTL bits */
        IDMA_CTL_RST_ATA        = (1 << 2),  /* hardreset ATA bus */
-       IDMA_CTL_RST_IDMA       = (1 << 5),  /* reset IDMA machinary */
+       IDMA_CTL_RST_IDMA       = (1 << 5),  /* reset IDMA machinery */
        IDMA_CTL_GO             = (1 << 7),  /* IDMA mode go */
        IDMA_CTL_ATA_NIEN       = (1 << 8),  /* ATA IRQ disable */
 
index e977041047845ddc05a1edcdd754a2247cc84d09..dcfbe7251dc43b86edd347c371c306d70d32e39d 100644 (file)
@@ -256,7 +256,8 @@ static int try_to_bring_up_master(struct master *master,
        ret = master->ops->bind(master->dev);
        if (ret < 0) {
                devres_release_group(master->dev, NULL);
-               dev_info(master->dev, "master bind failed: %d\n", ret);
+               if (ret != -EPROBE_DEFER)
+                       dev_info(master->dev, "master bind failed: %d\n", ret);
                return ret;
        }
 
@@ -611,8 +612,9 @@ static int component_bind(struct component *component, struct master *master,
                devres_release_group(component->dev, NULL);
                devres_release_group(master->dev, NULL);
 
-               dev_err(master->dev, "failed to bind %s (ops %ps): %d\n",
-                       dev_name(component->dev), component->ops, ret);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(master->dev, "failed to bind %s (ops %ps): %d\n",
+                               dev_name(component->dev), component->ops, ret);
        }
 
        return ret;
index 139cdf7e73271a02182cf4f7cdba707ded7cce55..073045cb214e8fdf82b7702e2a6297e720389a6f 100644 (file)
@@ -2370,6 +2370,11 @@ u32 fw_devlink_get_flags(void)
        return fw_devlink_flags;
 }
 
+static bool fw_devlink_is_permissive(void)
+{
+       return fw_devlink_flags == DL_FLAG_SYNC_STATE_ONLY;
+}
+
 /**
  * device_add - add device to device hierarchy.
  * @dev: device.
@@ -2524,7 +2529,7 @@ int device_add(struct device *dev)
        if (fw_devlink_flags && is_fwnode_dev &&
            fwnode_has_op(dev->fwnode, add_links)) {
                fw_ret = fwnode_call_int_op(dev->fwnode, add_links, dev);
-               if (fw_ret == -ENODEV)
+               if (fw_ret == -ENODEV && !fw_devlink_is_permissive())
                        device_link_wait_for_mandatory_supplier(dev);
                else if (fw_ret)
                        device_link_wait_for_optional_supplier(dev);
index 06ec0e851fa168f734641514475659e07d7d9e3c..94037be7f5d75cc88cd2f1321a8ee66c8f37b210 100644 (file)
@@ -224,17 +224,9 @@ static int deferred_devs_show(struct seq_file *s, void *data)
 }
 DEFINE_SHOW_ATTRIBUTE(deferred_devs);
 
-#ifdef CONFIG_MODULES
-/*
- * In the case of modules, set the default probe timeout to
- * 30 seconds to give userland some time to load needed modules
- */
-int driver_deferred_probe_timeout = 30;
-#else
-/* In the case of !modules, no probe timeout needed */
-int driver_deferred_probe_timeout = -1;
-#endif
+int driver_deferred_probe_timeout;
 EXPORT_SYMBOL_GPL(driver_deferred_probe_timeout);
+static DECLARE_WAIT_QUEUE_HEAD(probe_timeout_waitqueue);
 
 static int __init deferred_probe_timeout_setup(char *str)
 {
@@ -266,8 +258,8 @@ int driver_deferred_probe_check_state(struct device *dev)
                return -ENODEV;
        }
 
-       if (!driver_deferred_probe_timeout) {
-               dev_WARN(dev, "deferred probe timeout, ignoring dependency");
+       if (!driver_deferred_probe_timeout && initcalls_done) {
+               dev_warn(dev, "deferred probe timeout, ignoring dependency");
                return -ETIMEDOUT;
        }
 
@@ -284,6 +276,7 @@ static void deferred_probe_timeout_work_func(struct work_struct *work)
 
        list_for_each_entry_safe(private, p, &deferred_probe_pending_list, deferred_probe)
                dev_info(private->device, "deferred probe pending");
+       wake_up(&probe_timeout_waitqueue);
 }
 static DECLARE_DELAYED_WORK(deferred_probe_timeout_work, deferred_probe_timeout_work_func);
 
@@ -658,6 +651,9 @@ int driver_probe_done(void)
  */
 void wait_for_device_probe(void)
 {
+       /* wait for probe timeout */
+       wait_event(probe_timeout_waitqueue, !driver_deferred_probe_timeout);
+
        /* wait for the deferred probe workqueue to finish */
        flush_work(&deferred_probe_work);
 
index ba9d30b28edc5a9d8a439f0a6a07610a5590cbb4..a182e318bd0969d9391d99f7c84ca97af59ef568 100644 (file)
@@ -45,5 +45,4 @@ struct ctl_table firmware_config_table[] = {
        },
        { }
 };
-EXPORT_SYMBOL_GPL(firmware_config_table);
 #endif
index 5255550b7c34f1aca050d76785c09713049b2e1c..b27d0f6c18c9c0eeec0c46ade6db1c338ec0b1a4 100644 (file)
@@ -380,6 +380,8 @@ struct platform_object {
  */
 static void setup_pdev_dma_masks(struct platform_device *pdev)
 {
+       pdev->dev.dma_parms = &pdev->dma_parms;
+
        if (!pdev->dev.coherent_dma_mask)
                pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
        if (!pdev->dev.dma_mask) {
index fdd508a78ffd66044a4ffd89f5e44fd16f74e05f..0e07e17c2def339448a2a6ae41d496f703b81472 100644 (file)
@@ -730,7 +730,7 @@ static bool dpm_async_fn(struct device *dev, async_func_t func)
 
        if (is_async(dev)) {
                get_device(dev);
-               async_schedule(func, dev);
+               async_schedule_dev(func, dev);
                return true;
        }
 
index 62b660821dbcc19b390712b4088fc7141a4b27c2..81b311c9d781ef5d61108093db0d8a79518e4245 100644 (file)
@@ -85,26 +85,35 @@ struct nullb {
        char disk_name[DISK_NAME_LEN];
 };
 
+blk_status_t null_process_cmd(struct nullb_cmd *cmd,
+                             enum req_opf op, sector_t sector,
+                             unsigned int nr_sectors);
+
 #ifdef CONFIG_BLK_DEV_ZONED
-int null_zone_init(struct nullb_device *dev);
-void null_zone_exit(struct nullb_device *dev);
+int null_init_zoned_dev(struct nullb_device *dev, struct request_queue *q);
+int null_register_zoned_dev(struct nullb *nullb);
+void null_free_zoned_dev(struct nullb_device *dev);
 int null_report_zones(struct gendisk *disk, sector_t sector,
                      unsigned int nr_zones, report_zones_cb cb, void *data);
-blk_status_t null_handle_zoned(struct nullb_cmd *cmd,
-                               enum req_opf op, sector_t sector,
-                               sector_t nr_sectors);
+blk_status_t null_process_zoned_cmd(struct nullb_cmd *cmd,
+                                   enum req_opf op, sector_t sector,
+                                   sector_t nr_sectors);
 size_t null_zone_valid_read_len(struct nullb *nullb,
                                sector_t sector, unsigned int len);
 #else
-static inline int null_zone_init(struct nullb_device *dev)
+static inline int null_init_zoned_dev(struct nullb_device *dev,
+                                     struct request_queue *q)
 {
        pr_err("CONFIG_BLK_DEV_ZONED not enabled\n");
        return -EINVAL;
 }
-static inline void null_zone_exit(struct nullb_device *dev) {}
-static inline blk_status_t null_handle_zoned(struct nullb_cmd *cmd,
-                                            enum req_opf op, sector_t sector,
-                                            sector_t nr_sectors)
+static inline int null_register_zoned_dev(struct nullb *nullb)
+{
+       return -ENODEV;
+}
+static inline void null_free_zoned_dev(struct nullb_device *dev) {}
+static inline blk_status_t null_process_zoned_cmd(struct nullb_cmd *cmd,
+                       enum req_opf op, sector_t sector, sector_t nr_sectors)
 {
        return BLK_STS_NOTSUPP;
 }
index 4e1c0712278eaf89e1cedb897db54f73fe13ae94..8efd8778e2095e4a4ce6606f36effb5882339cd4 100644 (file)
@@ -580,7 +580,7 @@ static void null_free_dev(struct nullb_device *dev)
        if (!dev)
                return;
 
-       null_zone_exit(dev);
+       null_free_zoned_dev(dev);
        badblocks_exit(&dev->badblocks);
        kfree(dev);
 }
@@ -1276,6 +1276,25 @@ static inline void nullb_complete_cmd(struct nullb_cmd *cmd)
        }
 }
 
+blk_status_t null_process_cmd(struct nullb_cmd *cmd,
+                             enum req_opf op, sector_t sector,
+                             unsigned int nr_sectors)
+{
+       struct nullb_device *dev = cmd->nq->dev;
+       blk_status_t ret;
+
+       if (dev->badblocks.shift != -1) {
+               ret = null_handle_badblocks(cmd, sector, nr_sectors);
+               if (ret != BLK_STS_OK)
+                       return ret;
+       }
+
+       if (dev->memory_backed)
+               return null_handle_memory_backed(cmd, op);
+
+       return BLK_STS_OK;
+}
+
 static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
                                    sector_t nr_sectors, enum req_opf op)
 {
@@ -1294,17 +1313,11 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
                goto out;
        }
 
-       if (nullb->dev->badblocks.shift != -1) {
-               cmd->error = null_handle_badblocks(cmd, sector, nr_sectors);
-               if (cmd->error != BLK_STS_OK)
-                       goto out;
-       }
-
-       if (dev->memory_backed)
-               cmd->error = null_handle_memory_backed(cmd, op);
-
-       if (!cmd->error && dev->zoned)
-               cmd->error = null_handle_zoned(cmd, op, sector, nr_sectors);
+       if (dev->zoned)
+               cmd->error = null_process_zoned_cmd(cmd, op,
+                                                   sector, nr_sectors);
+       else
+               cmd->error = null_process_cmd(cmd, op, sector, nr_sectors);
 
 out:
        nullb_complete_cmd(cmd);
@@ -1605,19 +1618,12 @@ static int null_gendisk_register(struct nullb *nullb)
        disk->queue             = nullb->q;
        strncpy(disk->disk_name, nullb->disk_name, DISK_NAME_LEN);
 
-#ifdef CONFIG_BLK_DEV_ZONED
        if (nullb->dev->zoned) {
-               if (queue_is_mq(nullb->q)) {
-                       int ret = blk_revalidate_disk_zones(disk);
-                       if (ret)
-                               return ret;
-               } else {
-                       blk_queue_chunk_sectors(nullb->q,
-                                       nullb->dev->zone_size_sects);
-                       nullb->q->nr_zones = blkdev_nr_zones(disk);
-               }
+               int ret = null_register_zoned_dev(nullb);
+
+               if (ret)
+                       return ret;
        }
-#endif
 
        add_disk(disk);
        return 0;
@@ -1773,14 +1779,9 @@ static int null_add_dev(struct nullb_device *dev)
        }
 
        if (dev->zoned) {
-               rv = null_zone_init(dev);
+               rv = null_init_zoned_dev(dev, nullb->q);
                if (rv)
                        goto out_cleanup_blk_queue;
-
-               nullb->q->limits.zoned = BLK_ZONED_HM;
-               blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, nullb->q);
-               blk_queue_required_elevator_features(nullb->q,
-                                               ELEVATOR_F_ZBD_SEQ_WRITE);
        }
 
        nullb->q->queuedata = nullb;
@@ -1809,8 +1810,7 @@ static int null_add_dev(struct nullb_device *dev)
 
        return 0;
 out_cleanup_zone:
-       if (dev->zoned)
-               null_zone_exit(dev);
+       null_free_zoned_dev(dev);
 out_cleanup_blk_queue:
        blk_cleanup_queue(nullb->q);
 out_cleanup_tags:
index 673618d8222a6e6acc48ddb95fb56a85d73506bd..9e4bcdad1a80f700562a447cca6c533b828369d0 100644 (file)
@@ -13,7 +13,7 @@ static inline unsigned int null_zone_no(struct nullb_device *dev, sector_t sect)
        return sect >> ilog2(dev->zone_size_sects);
 }
 
-int null_zone_init(struct nullb_device *dev)
+int null_init_zoned_dev(struct nullb_device *dev, struct request_queue *q)
 {
        sector_t dev_size = (sector_t)dev->size * 1024 * 1024;
        sector_t sector = 0;
@@ -61,10 +61,27 @@ int null_zone_init(struct nullb_device *dev)
                sector += dev->zone_size_sects;
        }
 
+       q->limits.zoned = BLK_ZONED_HM;
+       blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, q);
+       blk_queue_required_elevator_features(q, ELEVATOR_F_ZBD_SEQ_WRITE);
+
+       return 0;
+}
+
+int null_register_zoned_dev(struct nullb *nullb)
+{
+       struct request_queue *q = nullb->q;
+
+       if (queue_is_mq(q))
+               return blk_revalidate_disk_zones(nullb->disk);
+
+       blk_queue_chunk_sectors(q, nullb->dev->zone_size_sects);
+       q->nr_zones = blkdev_nr_zones(nullb->disk);
+
        return 0;
 }
 
-void null_zone_exit(struct nullb_device *dev)
+void null_free_zoned_dev(struct nullb_device *dev)
 {
        kvfree(dev->zones);
 }
@@ -126,11 +143,16 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
        struct nullb_device *dev = cmd->nq->dev;
        unsigned int zno = null_zone_no(dev, sector);
        struct blk_zone *zone = &dev->zones[zno];
+       blk_status_t ret;
+
+       trace_nullb_zone_op(cmd, zno, zone->cond);
+
+       if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
+               return null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
 
        switch (zone->cond) {
        case BLK_ZONE_COND_FULL:
                /* Cannot write to a full zone */
-               cmd->error = BLK_STS_IOERR;
                return BLK_STS_IOERR;
        case BLK_ZONE_COND_EMPTY:
        case BLK_ZONE_COND_IMP_OPEN:
@@ -143,19 +165,18 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
                if (zone->cond != BLK_ZONE_COND_EXP_OPEN)
                        zone->cond = BLK_ZONE_COND_IMP_OPEN;
 
+               ret = null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
+               if (ret != BLK_STS_OK)
+                       return ret;
+
                zone->wp += nr_sectors;
                if (zone->wp == zone->start + zone->len)
                        zone->cond = BLK_ZONE_COND_FULL;
-               break;
-       case BLK_ZONE_COND_NOT_WP:
-               break;
+               return BLK_STS_OK;
        default:
                /* Invalid zone condition */
                return BLK_STS_IOERR;
        }
-
-       trace_nullb_zone_op(cmd, zno, zone->cond);
-       return BLK_STS_OK;
 }
 
 static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
@@ -216,8 +237,8 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
        return BLK_STS_OK;
 }
 
-blk_status_t null_handle_zoned(struct nullb_cmd *cmd, enum req_opf op,
-                              sector_t sector, sector_t nr_sectors)
+blk_status_t null_process_zoned_cmd(struct nullb_cmd *cmd, enum req_opf op,
+                                   sector_t sector, sector_t nr_sectors)
 {
        switch (op) {
        case REQ_OP_WRITE:
@@ -229,6 +250,6 @@ blk_status_t null_handle_zoned(struct nullb_cmd *cmd, enum req_opf op,
        case REQ_OP_ZONE_FINISH:
                return null_zone_mgmt(cmd, op, sector);
        default:
-               return BLK_STS_OK;
+               return null_process_cmd(cmd, op, sector, nr_sectors);
        }
 }
index 1e0a6b19ae0dde59e29328b63f331bd0d3c507f3..67d65ac785e9dcc585dd769503b13dceaaf116a9 100644 (file)
@@ -3754,11 +3754,7 @@ static int __rbd_notify_op_lock(struct rbd_device *rbd_dev,
 static void rbd_notify_op_lock(struct rbd_device *rbd_dev,
                               enum rbd_notify_op notify_op)
 {
-       struct page **reply_pages;
-       size_t reply_len;
-
-       __rbd_notify_op_lock(rbd_dev, notify_op, &reply_pages, &reply_len);
-       ceph_release_page_vector(reply_pages, calc_pages_for(0, reply_len));
+       __rbd_notify_op_lock(rbd_dev, notify_op, NULL, NULL);
 }
 
 static void rbd_notify_acquired_lock(struct work_struct *work)
@@ -4527,6 +4523,10 @@ static void cancel_tasks_sync(struct rbd_device *rbd_dev)
        cancel_work_sync(&rbd_dev->unlock_work);
 }
 
+/*
+ * header_rwsem must not be held to avoid a deadlock with
+ * rbd_dev_refresh() when flushing notifies.
+ */
 static void rbd_unregister_watch(struct rbd_device *rbd_dev)
 {
        cancel_tasks_sync(rbd_dev);
@@ -6894,9 +6894,10 @@ static void rbd_print_dne(struct rbd_device *rbd_dev, bool is_snap)
 
 static void rbd_dev_image_release(struct rbd_device *rbd_dev)
 {
-       rbd_dev_unprobe(rbd_dev);
-       if (rbd_dev->opts)
+       if (!rbd_is_ro(rbd_dev))
                rbd_unregister_watch(rbd_dev);
+
+       rbd_dev_unprobe(rbd_dev);
        rbd_dev->image_format = 0;
        kfree(rbd_dev->spec->image_id);
        rbd_dev->spec->image_id = NULL;
@@ -6907,6 +6908,9 @@ static void rbd_dev_image_release(struct rbd_device *rbd_dev)
  * device.  If this image is the one being mapped (i.e., not a
  * parent), initiate a watch on its header object before using that
  * object to get detailed information about the rbd image.
+ *
+ * On success, returns with header_rwsem held for write if called
+ * with @depth == 0.
  */
 static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
 {
@@ -6936,11 +6940,14 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
                }
        }
 
+       if (!depth)
+               down_write(&rbd_dev->header_rwsem);
+
        ret = rbd_dev_header_info(rbd_dev);
        if (ret) {
                if (ret == -ENOENT && !need_watch)
                        rbd_print_dne(rbd_dev, false);
-               goto err_out_watch;
+               goto err_out_probe;
        }
 
        /*
@@ -6985,10 +6992,11 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
        return 0;
 
 err_out_probe:
-       rbd_dev_unprobe(rbd_dev);
-err_out_watch:
+       if (!depth)
+               up_write(&rbd_dev->header_rwsem);
        if (need_watch)
                rbd_unregister_watch(rbd_dev);
+       rbd_dev_unprobe(rbd_dev);
 err_out_format:
        rbd_dev->image_format = 0;
        kfree(rbd_dev->spec->image_id);
@@ -7050,12 +7058,9 @@ static ssize_t do_rbd_add(struct bus_type *bus,
                goto err_out_rbd_dev;
        }
 
-       down_write(&rbd_dev->header_rwsem);
        rc = rbd_dev_image_probe(rbd_dev, 0);
-       if (rc < 0) {
-               up_write(&rbd_dev->header_rwsem);
+       if (rc < 0)
                goto err_out_rbd_dev;
-       }
 
        if (rbd_dev->opts->alloc_size > rbd_dev->layout.object_size) {
                rbd_warn(rbd_dev, "alloc_size adjusted to %u",
index f9b1e70f1b3149b4da7a4c1b9f324821b1d0b7ab..9d21bf0f155eed65fa150d71e6b92104fd701960 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/blk-mq.h>
 #include <linux/blk-mq-virtio.h>
 #include <linux/numa.h>
+#include <uapi/linux/virtio_ring.h>
 
 #define PART_BITS 4
 #define VQ_NAME_LEN 16
@@ -32,6 +33,15 @@ struct virtio_blk_vq {
 } ____cacheline_aligned_in_smp;
 
 struct virtio_blk {
+       /*
+        * This mutex must be held by anything that may run after
+        * virtblk_remove() sets vblk->vdev to NULL.
+        *
+        * blk-mq, virtqueue processing, and sysfs attribute code paths are
+        * shut down before vblk->vdev is set to NULL and therefore do not need
+        * to hold this mutex.
+        */
+       struct mutex vdev_mutex;
        struct virtio_device *vdev;
 
        /* The disk structure for the kernel. */
@@ -43,6 +53,13 @@ struct virtio_blk {
        /* Process context for config space updates */
        struct work_struct config_work;
 
+       /*
+        * Tracks references from block_device_operations open/release and
+        * virtio_driver probe/remove so this object can be freed once no
+        * longer in use.
+        */
+       refcount_t refs;
+
        /* What host tells us, plus 2 for header & tailer. */
        unsigned int sg_elems;
 
@@ -294,10 +311,55 @@ out:
        return err;
 }
 
+static void virtblk_get(struct virtio_blk *vblk)
+{
+       refcount_inc(&vblk->refs);
+}
+
+static void virtblk_put(struct virtio_blk *vblk)
+{
+       if (refcount_dec_and_test(&vblk->refs)) {
+               ida_simple_remove(&vd_index_ida, vblk->index);
+               mutex_destroy(&vblk->vdev_mutex);
+               kfree(vblk);
+       }
+}
+
+static int virtblk_open(struct block_device *bd, fmode_t mode)
+{
+       struct virtio_blk *vblk = bd->bd_disk->private_data;
+       int ret = 0;
+
+       mutex_lock(&vblk->vdev_mutex);
+
+       if (vblk->vdev)
+               virtblk_get(vblk);
+       else
+               ret = -ENXIO;
+
+       mutex_unlock(&vblk->vdev_mutex);
+       return ret;
+}
+
+static void virtblk_release(struct gendisk *disk, fmode_t mode)
+{
+       struct virtio_blk *vblk = disk->private_data;
+
+       virtblk_put(vblk);
+}
+
 /* We provide getgeo only to please some old bootloader/partitioning tools */
 static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
 {
        struct virtio_blk *vblk = bd->bd_disk->private_data;
+       int ret = 0;
+
+       mutex_lock(&vblk->vdev_mutex);
+
+       if (!vblk->vdev) {
+               ret = -ENXIO;
+               goto out;
+       }
 
        /* see if the host passed in geometry config */
        if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_GEOMETRY)) {
@@ -313,11 +375,15 @@ static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
                geo->sectors = 1 << 5;
                geo->cylinders = get_capacity(bd->bd_disk) >> 11;
        }
-       return 0;
+out:
+       mutex_unlock(&vblk->vdev_mutex);
+       return ret;
 }
 
 static const struct block_device_operations virtblk_fops = {
        .owner  = THIS_MODULE,
+       .open = virtblk_open,
+       .release = virtblk_release,
        .getgeo = virtblk_getgeo,
 };
 
@@ -654,6 +720,10 @@ static int virtblk_probe(struct virtio_device *vdev)
                goto out_free_index;
        }
 
+       /* This reference is dropped in virtblk_remove(). */
+       refcount_set(&vblk->refs, 1);
+       mutex_init(&vblk->vdev_mutex);
+
        vblk->vdev = vdev;
        vblk->sg_elems = sg_elems;
 
@@ -819,8 +889,6 @@ out:
 static void virtblk_remove(struct virtio_device *vdev)
 {
        struct virtio_blk *vblk = vdev->priv;
-       int index = vblk->index;
-       int refc;
 
        /* Make sure no work handler is accessing the device. */
        flush_work(&vblk->config_work);
@@ -830,18 +898,21 @@ static void virtblk_remove(struct virtio_device *vdev)
 
        blk_mq_free_tag_set(&vblk->tag_set);
 
+       mutex_lock(&vblk->vdev_mutex);
+
        /* Stop all the virtqueues. */
        vdev->config->reset(vdev);
 
-       refc = kref_read(&disk_to_dev(vblk->disk)->kobj.kref);
+       /* Virtqueues are stopped, nothing can use vblk->vdev anymore. */
+       vblk->vdev = NULL;
+
        put_disk(vblk->disk);
        vdev->config->del_vqs(vdev);
        kfree(vblk->vqs);
-       kfree(vblk);
 
-       /* Only free device id if we don't have any users */
-       if (refc == 1)
-               ida_simple_remove(&vd_index_ida, index);
+       mutex_unlock(&vblk->vdev_mutex);
+
+       virtblk_put(vblk);
 }
 
 #ifdef CONFIG_PM_SLEEP
index b38359c480eacecdb8c324cc98ea260ad59e6cef..eb2ab058a01d2ebdcd6485baa03af5096c7676a6 100644 (file)
@@ -812,10 +812,9 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
        if (!mhi_cntrl)
                return -EINVAL;
 
-       if (!mhi_cntrl->runtime_get || !mhi_cntrl->runtime_put)
-               return -EINVAL;
-
-       if (!mhi_cntrl->status_cb || !mhi_cntrl->link_status)
+       if (!mhi_cntrl->runtime_get || !mhi_cntrl->runtime_put ||
+           !mhi_cntrl->status_cb || !mhi_cntrl->read_reg ||
+           !mhi_cntrl->write_reg)
                return -EINVAL;
 
        ret = parse_config(mhi_cntrl, config);
index 5deadfaa053a811212e7d15256159dda3b39d0f5..095d95bc0e3741c77970124ac898e734aedcb64e 100644 (file)
@@ -11,9 +11,6 @@
 
 extern struct bus_type mhi_bus_type;
 
-/* MHI MMIO register mapping */
-#define PCI_INVALID_READ(val) (val == U32_MAX)
-
 #define MHIREGLEN (0x0)
 #define MHIREGLEN_MHIREGLEN_MASK (0xFFFFFFFF)
 #define MHIREGLEN_MHIREGLEN_SHIFT (0)
index eb4256b81406a2e9144926effb5eabcb3f9e6ee9..97e06cc586e4f7cda57d3e22be9f585269d09d17 100644 (file)
 int __must_check mhi_read_reg(struct mhi_controller *mhi_cntrl,
                              void __iomem *base, u32 offset, u32 *out)
 {
-       u32 tmp = readl(base + offset);
-
-       /* If there is any unexpected value, query the link status */
-       if (PCI_INVALID_READ(tmp) &&
-           mhi_cntrl->link_status(mhi_cntrl))
-               return -EIO;
-
-       *out = tmp;
-
-       return 0;
+       return mhi_cntrl->read_reg(mhi_cntrl, base + offset, out);
 }
 
 int __must_check mhi_read_reg_field(struct mhi_controller *mhi_cntrl,
@@ -49,7 +40,7 @@ int __must_check mhi_read_reg_field(struct mhi_controller *mhi_cntrl,
 void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *base,
                   u32 offset, u32 val)
 {
-       writel(val, base + offset);
+       mhi_cntrl->write_reg(mhi_cntrl, base + offset, val);
 }
 
 void mhi_write_reg_field(struct mhi_controller *mhi_cntrl, void __iomem *base,
@@ -294,7 +285,7 @@ void mhi_create_devices(struct mhi_controller *mhi_cntrl)
                    !(mhi_chan->ee_mask & BIT(mhi_cntrl->ee)))
                        continue;
                mhi_dev = mhi_alloc_device(mhi_cntrl);
-               if (!mhi_dev)
+               if (IS_ERR(mhi_dev))
                        return;
 
                mhi_dev->dev_type = MHI_DEVICE_XFER;
@@ -336,7 +327,8 @@ void mhi_create_devices(struct mhi_controller *mhi_cntrl)
 
                /* Channel name is same for both UL and DL */
                mhi_dev->chan_name = mhi_chan->name;
-               dev_set_name(&mhi_dev->dev, "%04x_%s", mhi_chan->chan,
+               dev_set_name(&mhi_dev->dev, "%s_%s",
+                            dev_name(mhi_cntrl->cntrl_dev),
                             mhi_dev->chan_name);
 
                /* Init wakeup source if available */
index 52690cb5c89cb5a4602494d04aed8513e4dfb1d4..dc83d65f7784e26657deda2f83ae7a355918f44c 100644 (file)
@@ -902,7 +902,11 @@ int mhi_sync_power_up(struct mhi_controller *mhi_cntrl)
                           MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
                           msecs_to_jiffies(mhi_cntrl->timeout_ms));
 
-       return (MHI_IN_MISSION_MODE(mhi_cntrl->ee)) ? 0 : -EIO;
+       ret = (MHI_IN_MISSION_MODE(mhi_cntrl->ee)) ? 0 : -ETIMEDOUT;
+       if (ret)
+               mhi_power_down(mhi_cntrl, false);
+
+       return ret;
 }
 EXPORT_SYMBOL(mhi_sync_power_up);
 
index 718d8c0876506c59e4d05b7ccc5ef950e431ed19..79a6e47b5fbc9f20a5529620eee384b42842283a 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/virtio.h>
 #include <linux/virtio_rng.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 
 static DEFINE_IDA(rng_index_ida);
 
index a438b1206fcbe7c4355e9a04281bfbb55f83dc2c..1621ce8187052cf332cab95d0dffed87ec2f074e 100644 (file)
@@ -323,7 +323,7 @@ int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
 
        for (i = 0; i < chip->nr_allocated_banks; i++) {
                if (digests[i].alg_id != chip->allocated_banks[i].alg_id) {
-                       rc = EINVAL;
+                       rc = -EINVAL;
                        goto out;
                }
        }
index 76f67b155bd5420981e7baea3f530745748cbed2..eff1f12d981ab275e07387864a876e1cfc35e2d9 100644 (file)
@@ -681,6 +681,7 @@ out:
                rc = -ENODEV;
        return rc;
 }
+EXPORT_SYMBOL_GPL(tpm2_get_cc_attrs_tbl);
 
 /**
  * tpm2_startup - turn on the TPM
index 1a49db9e108e5d3e09ad678d66f10a3908d14ba0..09fe45246b8cc0d65760eecff54af9bdbd2997ef 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (C) 2012 IBM Corporation
+ * Copyright (C) 2012-2020 IBM Corporation
  *
  * Author: Ashley Lai <ashleydlai@gmail.com>
  *
@@ -134,6 +134,64 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
        return len;
 }
 
+/**
+ * ibmvtpm_crq_send_init - Send a CRQ initialize message
+ * @ibmvtpm:   vtpm device struct
+ *
+ * Return:
+ *     0 on success.
+ *     Non-zero on failure.
+ */
+static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
+{
+       int rc;
+
+       rc = ibmvtpm_send_crq_word(ibmvtpm->vdev, INIT_CRQ_CMD);
+       if (rc != H_SUCCESS)
+               dev_err(ibmvtpm->dev,
+                       "%s failed rc=%d\n", __func__, rc);
+
+       return rc;
+}
+
+/**
+ * tpm_ibmvtpm_resume - Resume from suspend
+ *
+ * @dev:       device struct
+ *
+ * Return: Always 0.
+ */
+static int tpm_ibmvtpm_resume(struct device *dev)
+{
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+       struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
+       int rc = 0;
+
+       do {
+               if (rc)
+                       msleep(100);
+               rc = plpar_hcall_norets(H_ENABLE_CRQ,
+                                       ibmvtpm->vdev->unit_address);
+       } while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc));
+
+       if (rc) {
+               dev_err(dev, "Error enabling ibmvtpm rc=%d\n", rc);
+               return rc;
+       }
+
+       rc = vio_enable_interrupts(ibmvtpm->vdev);
+       if (rc) {
+               dev_err(dev, "Error vio_enable_interrupts rc=%d\n", rc);
+               return rc;
+       }
+
+       rc = ibmvtpm_crq_send_init(ibmvtpm);
+       if (rc)
+               dev_err(dev, "Error send_init rc=%d\n", rc);
+
+       return rc;
+}
+
 /**
  * tpm_ibmvtpm_send() - Send a TPM command
  * @chip:      tpm chip struct
@@ -147,6 +205,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
 {
        struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
+       bool retry = true;
        int rc, sig;
 
        if (!ibmvtpm->rtce_buf) {
@@ -180,18 +239,27 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
         */
        ibmvtpm->tpm_processing_cmd = true;
 
+again:
        rc = ibmvtpm_send_crq(ibmvtpm->vdev,
                        IBMVTPM_VALID_CMD, VTPM_TPM_COMMAND,
                        count, ibmvtpm->rtce_dma_handle);
        if (rc != H_SUCCESS) {
+               /*
+                * H_CLOSED can be returned after LPM resume.  Call
+                * tpm_ibmvtpm_resume() to re-enable the CRQ then retry
+                * ibmvtpm_send_crq() once before failing.
+                */
+               if (rc == H_CLOSED && retry) {
+                       tpm_ibmvtpm_resume(ibmvtpm->dev);
+                       retry = false;
+                       goto again;
+               }
                dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
-               rc = 0;
                ibmvtpm->tpm_processing_cmd = false;
-       } else
-               rc = 0;
+       }
 
        spin_unlock(&ibmvtpm->rtce_lock);
-       return rc;
+       return 0;
 }
 
 static void tpm_ibmvtpm_cancel(struct tpm_chip *chip)
@@ -269,26 +337,6 @@ static int ibmvtpm_crq_send_init_complete(struct ibmvtpm_dev *ibmvtpm)
        return rc;
 }
 
-/**
- * ibmvtpm_crq_send_init - Send a CRQ initialize message
- * @ibmvtpm:   vtpm device struct
- *
- * Return:
- *     0 on success.
- *     Non-zero on failure.
- */
-static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
-{
-       int rc;
-
-       rc = ibmvtpm_send_crq_word(ibmvtpm->vdev, INIT_CRQ_CMD);
-       if (rc != H_SUCCESS)
-               dev_err(ibmvtpm->dev,
-                       "ibmvtpm_crq_send_init failed rc=%d\n", rc);
-
-       return rc;
-}
-
 /**
  * tpm_ibmvtpm_remove - ibm vtpm remove entry point
  * @vdev:      vio device struct
@@ -401,44 +449,6 @@ static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm)
                                  ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE);
 }
 
-/**
- * tpm_ibmvtpm_resume - Resume from suspend
- *
- * @dev:       device struct
- *
- * Return: Always 0.
- */
-static int tpm_ibmvtpm_resume(struct device *dev)
-{
-       struct tpm_chip *chip = dev_get_drvdata(dev);
-       struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
-       int rc = 0;
-
-       do {
-               if (rc)
-                       msleep(100);
-               rc = plpar_hcall_norets(H_ENABLE_CRQ,
-                                       ibmvtpm->vdev->unit_address);
-       } while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc));
-
-       if (rc) {
-               dev_err(dev, "Error enabling ibmvtpm rc=%d\n", rc);
-               return rc;
-       }
-
-       rc = vio_enable_interrupts(ibmvtpm->vdev);
-       if (rc) {
-               dev_err(dev, "Error vio_enable_interrupts rc=%d\n", rc);
-               return rc;
-       }
-
-       rc = ibmvtpm_crq_send_init(ibmvtpm);
-       if (rc)
-               dev_err(dev, "Error send_init rc=%d\n", rc);
-
-       return rc;
-}
-
 static bool tpm_ibmvtpm_req_canceled(struct tpm_chip *chip, u8 status)
 {
        return (status == 0);
index 27c6ca031e23ec8a26401dc281271404e8e3a008..2435216bd10aaac1856f48a30c507a532bf19deb 100644 (file)
@@ -433,6 +433,9 @@ static void disable_interrupts(struct tpm_chip *chip)
        u32 intmask;
        int rc;
 
+       if (priv->irq == 0)
+               return;
+
        rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
        if (rc < 0)
                intmask = 0;
@@ -1062,9 +1065,12 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
                if (irq) {
                        tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
                                                 irq);
-                       if (!(chip->flags & TPM_CHIP_FLAG_IRQ))
+                       if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
                                dev_err(&chip->dev, FW_BUG
                                        "TPM interrupt not working, polling instead\n");
+
+                               disable_interrupts(chip);
+                       }
                } else {
                        tpm_tis_probe_irq(chip, intmask);
                }
index 536b59aabd2cba18dab1656e66590628b08b1f6e..bacebd457e6f34697e546b7b7ea12a1cc8960427 100644 (file)
@@ -276,7 +276,7 @@ static void __init asm9260_acc_init(struct device_node *np)
 
        /* TODO: Convert to DT parent scheme */
        ref_clk = of_clk_get_parent_name(np, 0);
-       hw = __clk_hw_register_fixed_rate_with_accuracy(NULL, NULL, pll_clk,
+       hw = __clk_hw_register_fixed_rate(NULL, NULL, pll_clk,
                        ref_clk, NULL, NULL, 0, rate, 0,
                        CLK_FIXED_RATE_PARENT_ACCURACY);
 
index 7077be293871193c94b780f73949f065d0002754..962014cfdc44e02e5314faa27896e81b9229593e 100644 (file)
@@ -97,7 +97,7 @@ static const struct clk_ops mmp_clk_pll_ops = {
        .recalc_rate = mmp_clk_pll_recalc_rate,
 };
 
-struct clk *mmp_clk_register_pll(char *name,
+static struct clk *mmp_clk_register_pll(char *name,
                        unsigned long default_rate,
                        void __iomem *enable_reg, u32 enable,
                        void __iomem *reg, u8 shift,
@@ -137,3 +137,34 @@ struct clk *mmp_clk_register_pll(char *name,
 
        return clk;
 }
+
+void mmp_register_pll_clks(struct mmp_clk_unit *unit,
+                       struct mmp_param_pll_clk *clks,
+                       void __iomem *base, int size)
+{
+       struct clk *clk;
+       int i;
+
+       for (i = 0; i < size; i++) {
+               void __iomem *reg = NULL;
+
+               if (clks[i].offset)
+                       reg = base + clks[i].offset;
+
+               clk = mmp_clk_register_pll(clks[i].name,
+                                       clks[i].default_rate,
+                                       base + clks[i].enable_offset,
+                                       clks[i].enable,
+                                       reg, clks[i].shift,
+                                       clks[i].input_rate,
+                                       base + clks[i].postdiv_offset,
+                                       clks[i].postdiv_shift);
+               if (IS_ERR(clk)) {
+                       pr_err("%s: failed to register clock %s\n",
+                              __func__, clks[i].name);
+                       continue;
+               }
+               if (clks[i].id)
+                       unit->clk_table[clks[i].id] = clk;
+       }
+}
index 317123641d1ed0be3ac73b41c9880d418c5119f5..ca7d37e2c7be6bb6aba2a7d4e1459d8c4369fcca 100644 (file)
@@ -176,37 +176,6 @@ void mmp_register_div_clks(struct mmp_clk_unit *unit,
        }
 }
 
-void mmp_register_pll_clks(struct mmp_clk_unit *unit,
-                       struct mmp_param_pll_clk *clks,
-                       void __iomem *base, int size)
-{
-       struct clk *clk;
-       int i;
-
-       for (i = 0; i < size; i++) {
-               void __iomem *reg = NULL;
-
-               if (clks[i].offset)
-                       reg = base + clks[i].offset;
-
-               clk = mmp_clk_register_pll(clks[i].name,
-                                       clks[i].default_rate,
-                                       base + clks[i].enable_offset,
-                                       clks[i].enable,
-                                       reg, clks[i].shift,
-                                       clks[i].input_rate,
-                                       base + clks[i].postdiv_offset,
-                                       clks[i].postdiv_shift);
-               if (IS_ERR(clk)) {
-                       pr_err("%s: failed to register clock %s\n",
-                              __func__, clks[i].name);
-                       continue;
-               }
-               if (clks[i].id)
-                       unit->clk_table[clks[i].id] = clk;
-       }
-}
-
 void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id,
                        struct clk *clk)
 {
index 971b4d6d992fb774e4730e343aca7d34739c997a..20dc1e5dd7564367b8f0601feb30a98914984720 100644 (file)
@@ -238,13 +238,6 @@ void mmp_register_pll_clks(struct mmp_clk_unit *unit,
                        struct mmp_param_pll_clk *clks,
                        void __iomem *base, int size);
 
-extern struct clk *mmp_clk_register_pll(char *name,
-                       unsigned long default_rate,
-                       void __iomem *enable_reg, u32 enable,
-                       void __iomem *reg, u8 shift,
-                       unsigned long input_rate,
-                       void __iomem *postdiv_reg, u8 postdiv_shift);
-
 #define DEFINE_MIX_REG_INFO(w_d, s_d, w_m, s_m, fc)    \
 {                                                      \
        .width_div = (w_d),                             \
index a0631f7756cfc6c79aaee2462458d6c82b9cf98f..2e2dfb2d48fff271662129eef32853c1ac6833c8 100644 (file)
@@ -1641,8 +1641,9 @@ static SPRD_SC_GATE_CLK_FW_NAME(i2c4_eb,  "i2c4-eb",      "ext-26m", 0x0,
                                0x1000, BIT(12), 0, 0);
 static SPRD_SC_GATE_CLK_FW_NAME(uart0_eb,      "uart0-eb",     "ext-26m", 0x0,
                                0x1000, BIT(13), 0, 0);
+/* uart1_eb is for console, don't gate even if unused */
 static SPRD_SC_GATE_CLK_FW_NAME(uart1_eb,      "uart1-eb",     "ext-26m", 0x0,
-                               0x1000, BIT(14), 0, 0);
+                               0x1000, BIT(14), CLK_IGNORE_UNUSED, 0);
 static SPRD_SC_GATE_CLK_FW_NAME(uart2_eb,      "uart2-eb",     "ext-26m", 0x0,
                                0x1000, BIT(15), 0, 0);
 static SPRD_SC_GATE_CLK_FW_NAME(uart3_eb,      "uart3-eb",     "ext-26m", 0x0,
index 9dab190c49b062821442ef7852e026fe7ad48d04..aa13708c2bc30653ba8426b99f2b4ddc82cf0c5e 100644 (file)
@@ -44,6 +44,7 @@ MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
  * @base:              base port address of the IIO device
  */
 struct quad8_iio {
+       struct mutex lock;
        struct counter_device counter;
        unsigned int fck_prescaler[QUAD8_NUM_COUNTERS];
        unsigned int preset[QUAD8_NUM_COUNTERS];
@@ -123,6 +124,8 @@ static int quad8_read_raw(struct iio_dev *indio_dev,
                /* Borrow XOR Carry effectively doubles count range */
                *val = (borrow ^ carry) << 24;
 
+               mutex_lock(&priv->lock);
+
                /* Reset Byte Pointer; transfer Counter to Output Latch */
                outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
                     base_offset + 1);
@@ -130,6 +133,8 @@ static int quad8_read_raw(struct iio_dev *indio_dev,
                for (i = 0; i < 3; i++)
                        *val |= (unsigned int)inb(base_offset) << (8 * i);
 
+               mutex_unlock(&priv->lock);
+
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_ENABLE:
                *val = priv->ab_enable[chan->channel];
@@ -160,6 +165,8 @@ static int quad8_write_raw(struct iio_dev *indio_dev,
                if ((unsigned int)val > 0xFFFFFF)
                        return -EINVAL;
 
+               mutex_lock(&priv->lock);
+
                /* Reset Byte Pointer */
                outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
 
@@ -183,12 +190,16 @@ static int quad8_write_raw(struct iio_dev *indio_dev,
                /* Reset Error flag */
                outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
 
+               mutex_unlock(&priv->lock);
+
                return 0;
        case IIO_CHAN_INFO_ENABLE:
                /* only boolean values accepted */
                if (val < 0 || val > 1)
                        return -EINVAL;
 
+               mutex_lock(&priv->lock);
+
                priv->ab_enable[chan->channel] = val;
 
                ior_cfg = val | priv->preset_enable[chan->channel] << 1;
@@ -196,11 +207,18 @@ static int quad8_write_raw(struct iio_dev *indio_dev,
                /* Load I/O control configuration */
                outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1);
 
+               mutex_unlock(&priv->lock);
+
                return 0;
        case IIO_CHAN_INFO_SCALE:
+               mutex_lock(&priv->lock);
+
                /* Quadrature scaling only available in quadrature mode */
-               if (!priv->quadrature_mode[chan->channel] && (val2 || val != 1))
+               if (!priv->quadrature_mode[chan->channel] &&
+                               (val2 || val != 1)) {
+                       mutex_unlock(&priv->lock);
                        return -EINVAL;
+               }
 
                /* Only three gain states (1, 0.5, 0.25) */
                if (val == 1 && !val2)
@@ -214,11 +232,15 @@ static int quad8_write_raw(struct iio_dev *indio_dev,
                                priv->quadrature_scale[chan->channel] = 2;
                                break;
                        default:
+                               mutex_unlock(&priv->lock);
                                return -EINVAL;
                        }
-               else
+               else {
+                       mutex_unlock(&priv->lock);
                        return -EINVAL;
+               }
 
+               mutex_unlock(&priv->lock);
                return 0;
        }
 
@@ -255,6 +277,8 @@ static ssize_t quad8_write_preset(struct iio_dev *indio_dev, uintptr_t private,
        if (preset > 0xFFFFFF)
                return -EINVAL;
 
+       mutex_lock(&priv->lock);
+
        priv->preset[chan->channel] = preset;
 
        /* Reset Byte Pointer */
@@ -264,6 +288,8 @@ static ssize_t quad8_write_preset(struct iio_dev *indio_dev, uintptr_t private,
        for (i = 0; i < 3; i++)
                outb(preset >> (8 * i), base_offset);
 
+       mutex_unlock(&priv->lock);
+
        return len;
 }
 
@@ -293,6 +319,8 @@ static ssize_t quad8_write_set_to_preset_on_index(struct iio_dev *indio_dev,
        /* Preset enable is active low in Input/Output Control register */
        preset_enable = !preset_enable;
 
+       mutex_lock(&priv->lock);
+
        priv->preset_enable[chan->channel] = preset_enable;
 
        ior_cfg = priv->ab_enable[chan->channel] |
@@ -301,6 +329,8 @@ static ssize_t quad8_write_set_to_preset_on_index(struct iio_dev *indio_dev,
        /* Load I/O control configuration to Input / Output Control Register */
        outb(QUAD8_CTR_IOR | ior_cfg, base_offset);
 
+       mutex_unlock(&priv->lock);
+
        return len;
 }
 
@@ -358,6 +388,8 @@ static int quad8_set_count_mode(struct iio_dev *indio_dev,
        unsigned int mode_cfg = cnt_mode << 1;
        const int base_offset = priv->base + 2 * chan->channel + 1;
 
+       mutex_lock(&priv->lock);
+
        priv->count_mode[chan->channel] = cnt_mode;
 
        /* Add quadrature mode configuration */
@@ -367,6 +399,8 @@ static int quad8_set_count_mode(struct iio_dev *indio_dev,
        /* Load mode configuration to Counter Mode Register */
        outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
 
+       mutex_unlock(&priv->lock);
+
        return 0;
 }
 
@@ -394,19 +428,26 @@ static int quad8_set_synchronous_mode(struct iio_dev *indio_dev,
        const struct iio_chan_spec *chan, unsigned int synchronous_mode)
 {
        struct quad8_iio *const priv = iio_priv(indio_dev);
-       const unsigned int idr_cfg = synchronous_mode |
-               priv->index_polarity[chan->channel] << 1;
        const int base_offset = priv->base + 2 * chan->channel + 1;
+       unsigned int idr_cfg = synchronous_mode;
+
+       mutex_lock(&priv->lock);
+
+       idr_cfg |= priv->index_polarity[chan->channel] << 1;
 
        /* Index function must be non-synchronous in non-quadrature mode */
-       if (synchronous_mode && !priv->quadrature_mode[chan->channel])
+       if (synchronous_mode && !priv->quadrature_mode[chan->channel]) {
+               mutex_unlock(&priv->lock);
                return -EINVAL;
+       }
 
        priv->synchronous_mode[chan->channel] = synchronous_mode;
 
        /* Load Index Control configuration to Index Control Register */
        outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
 
+       mutex_unlock(&priv->lock);
+
        return 0;
 }
 
@@ -434,8 +475,12 @@ static int quad8_set_quadrature_mode(struct iio_dev *indio_dev,
        const struct iio_chan_spec *chan, unsigned int quadrature_mode)
 {
        struct quad8_iio *const priv = iio_priv(indio_dev);
-       unsigned int mode_cfg = priv->count_mode[chan->channel] << 1;
        const int base_offset = priv->base + 2 * chan->channel + 1;
+       unsigned int mode_cfg;
+
+       mutex_lock(&priv->lock);
+
+       mode_cfg = priv->count_mode[chan->channel] << 1;
 
        if (quadrature_mode)
                mode_cfg |= (priv->quadrature_scale[chan->channel] + 1) << 3;
@@ -453,6 +498,8 @@ static int quad8_set_quadrature_mode(struct iio_dev *indio_dev,
        /* Load mode configuration to Counter Mode Register */
        outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
 
+       mutex_unlock(&priv->lock);
+
        return 0;
 }
 
@@ -480,15 +527,20 @@ static int quad8_set_index_polarity(struct iio_dev *indio_dev,
        const struct iio_chan_spec *chan, unsigned int index_polarity)
 {
        struct quad8_iio *const priv = iio_priv(indio_dev);
-       const unsigned int idr_cfg = priv->synchronous_mode[chan->channel] |
-               index_polarity << 1;
        const int base_offset = priv->base + 2 * chan->channel + 1;
+       unsigned int idr_cfg = index_polarity << 1;
+
+       mutex_lock(&priv->lock);
+
+       idr_cfg |= priv->synchronous_mode[chan->channel];
 
        priv->index_polarity[chan->channel] = index_polarity;
 
        /* Load Index Control configuration to Index Control Register */
        outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
 
+       mutex_unlock(&priv->lock);
+
        return 0;
 }
 
@@ -589,7 +641,7 @@ static int quad8_signal_read(struct counter_device *counter,
 static int quad8_count_read(struct counter_device *counter,
        struct counter_count *count, unsigned long *val)
 {
-       const struct quad8_iio *const priv = counter->priv;
+       struct quad8_iio *const priv = counter->priv;
        const int base_offset = priv->base + 2 * count->id;
        unsigned int flags;
        unsigned int borrow;
@@ -603,6 +655,8 @@ static int quad8_count_read(struct counter_device *counter,
        /* Borrow XOR Carry effectively doubles count range */
        *val = (unsigned long)(borrow ^ carry) << 24;
 
+       mutex_lock(&priv->lock);
+
        /* Reset Byte Pointer; transfer Counter to Output Latch */
        outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
             base_offset + 1);
@@ -610,13 +664,15 @@ static int quad8_count_read(struct counter_device *counter,
        for (i = 0; i < 3; i++)
                *val |= (unsigned long)inb(base_offset) << (8 * i);
 
+       mutex_unlock(&priv->lock);
+
        return 0;
 }
 
 static int quad8_count_write(struct counter_device *counter,
        struct counter_count *count, unsigned long val)
 {
-       const struct quad8_iio *const priv = counter->priv;
+       struct quad8_iio *const priv = counter->priv;
        const int base_offset = priv->base + 2 * count->id;
        int i;
 
@@ -624,6 +680,8 @@ static int quad8_count_write(struct counter_device *counter,
        if (val > 0xFFFFFF)
                return -EINVAL;
 
+       mutex_lock(&priv->lock);
+
        /* Reset Byte Pointer */
        outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
 
@@ -647,6 +705,8 @@ static int quad8_count_write(struct counter_device *counter,
        /* Reset Error flag */
        outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
 
+       mutex_unlock(&priv->lock);
+
        return 0;
 }
 
@@ -667,13 +727,13 @@ static enum counter_count_function quad8_count_functions_list[] = {
 static int quad8_function_get(struct counter_device *counter,
        struct counter_count *count, size_t *function)
 {
-       const struct quad8_iio *const priv = counter->priv;
+       struct quad8_iio *const priv = counter->priv;
        const int id = count->id;
-       const unsigned int quadrature_mode = priv->quadrature_mode[id];
-       const unsigned int scale = priv->quadrature_scale[id];
 
-       if (quadrature_mode)
-               switch (scale) {
+       mutex_lock(&priv->lock);
+
+       if (priv->quadrature_mode[id])
+               switch (priv->quadrature_scale[id]) {
                case 0:
                        *function = QUAD8_COUNT_FUNCTION_QUADRATURE_X1;
                        break;
@@ -687,6 +747,8 @@ static int quad8_function_get(struct counter_device *counter,
        else
                *function = QUAD8_COUNT_FUNCTION_PULSE_DIRECTION;
 
+       mutex_unlock(&priv->lock);
+
        return 0;
 }
 
@@ -697,10 +759,15 @@ static int quad8_function_set(struct counter_device *counter,
        const int id = count->id;
        unsigned int *const quadrature_mode = priv->quadrature_mode + id;
        unsigned int *const scale = priv->quadrature_scale + id;
-       unsigned int mode_cfg = priv->count_mode[id] << 1;
        unsigned int *const synchronous_mode = priv->synchronous_mode + id;
-       const unsigned int idr_cfg = priv->index_polarity[id] << 1;
        const int base_offset = priv->base + 2 * id + 1;
+       unsigned int mode_cfg;
+       unsigned int idr_cfg;
+
+       mutex_lock(&priv->lock);
+
+       mode_cfg = priv->count_mode[id] << 1;
+       idr_cfg = priv->index_polarity[id] << 1;
 
        if (function == QUAD8_COUNT_FUNCTION_PULSE_DIRECTION) {
                *quadrature_mode = 0;
@@ -736,6 +803,8 @@ static int quad8_function_set(struct counter_device *counter,
        /* Load mode configuration to Counter Mode Register */
        outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
 
+       mutex_unlock(&priv->lock);
+
        return 0;
 }
 
@@ -852,15 +921,20 @@ static int quad8_index_polarity_set(struct counter_device *counter,
 {
        struct quad8_iio *const priv = counter->priv;
        const size_t channel_id = signal->id - 16;
-       const unsigned int idr_cfg = priv->synchronous_mode[channel_id] |
-               index_polarity << 1;
        const int base_offset = priv->base + 2 * channel_id + 1;
+       unsigned int idr_cfg = index_polarity << 1;
+
+       mutex_lock(&priv->lock);
+
+       idr_cfg |= priv->synchronous_mode[channel_id];
 
        priv->index_polarity[channel_id] = index_polarity;
 
        /* Load Index Control configuration to Index Control Register */
        outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
 
+       mutex_unlock(&priv->lock);
+
        return 0;
 }
 
@@ -887,19 +961,26 @@ static int quad8_synchronous_mode_set(struct counter_device *counter,
 {
        struct quad8_iio *const priv = counter->priv;
        const size_t channel_id = signal->id - 16;
-       const unsigned int idr_cfg = synchronous_mode |
-               priv->index_polarity[channel_id] << 1;
        const int base_offset = priv->base + 2 * channel_id + 1;
+       unsigned int idr_cfg = synchronous_mode;
+
+       mutex_lock(&priv->lock);
+
+       idr_cfg |= priv->index_polarity[channel_id] << 1;
 
        /* Index function must be non-synchronous in non-quadrature mode */
-       if (synchronous_mode && !priv->quadrature_mode[channel_id])
+       if (synchronous_mode && !priv->quadrature_mode[channel_id]) {
+               mutex_unlock(&priv->lock);
                return -EINVAL;
+       }
 
        priv->synchronous_mode[channel_id] = synchronous_mode;
 
        /* Load Index Control configuration to Index Control Register */
        outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
 
+       mutex_unlock(&priv->lock);
+
        return 0;
 }
 
@@ -964,6 +1045,8 @@ static int quad8_count_mode_set(struct counter_device *counter,
                break;
        }
 
+       mutex_lock(&priv->lock);
+
        priv->count_mode[count->id] = cnt_mode;
 
        /* Set count mode configuration value */
@@ -976,6 +1059,8 @@ static int quad8_count_mode_set(struct counter_device *counter,
        /* Load mode configuration to Counter Mode Register */
        outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
 
+       mutex_unlock(&priv->lock);
+
        return 0;
 }
 
@@ -1017,6 +1102,8 @@ static ssize_t quad8_count_enable_write(struct counter_device *counter,
        if (err)
                return err;
 
+       mutex_lock(&priv->lock);
+
        priv->ab_enable[count->id] = ab_enable;
 
        ior_cfg = ab_enable | priv->preset_enable[count->id] << 1;
@@ -1024,6 +1111,8 @@ static ssize_t quad8_count_enable_write(struct counter_device *counter,
        /* Load I/O control configuration */
        outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1);
 
+       mutex_unlock(&priv->lock);
+
        return len;
 }
 
@@ -1052,14 +1141,28 @@ static ssize_t quad8_count_preset_read(struct counter_device *counter,
        return sprintf(buf, "%u\n", priv->preset[count->id]);
 }
 
+static void quad8_preset_register_set(struct quad8_iio *quad8iio, int id,
+               unsigned int preset)
+{
+       const unsigned int base_offset = quad8iio->base + 2 * id;
+       int i;
+
+       quad8iio->preset[id] = preset;
+
+       /* Reset Byte Pointer */
+       outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
+
+       /* Set Preset Register */
+       for (i = 0; i < 3; i++)
+               outb(preset >> (8 * i), base_offset);
+}
+
 static ssize_t quad8_count_preset_write(struct counter_device *counter,
        struct counter_count *count, void *private, const char *buf, size_t len)
 {
        struct quad8_iio *const priv = counter->priv;
-       const int base_offset = priv->base + 2 * count->id;
        unsigned int preset;
        int ret;
-       int i;
 
        ret = kstrtouint(buf, 0, &preset);
        if (ret)
@@ -1069,14 +1172,11 @@ static ssize_t quad8_count_preset_write(struct counter_device *counter,
        if (preset > 0xFFFFFF)
                return -EINVAL;
 
-       priv->preset[count->id] = preset;
+       mutex_lock(&priv->lock);
 
-       /* Reset Byte Pointer */
-       outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
+       quad8_preset_register_set(priv, count->id, preset);
 
-       /* Set Preset Register */
-       for (i = 0; i < 3; i++)
-               outb(preset >> (8 * i), base_offset);
+       mutex_unlock(&priv->lock);
 
        return len;
 }
@@ -1084,15 +1184,20 @@ static ssize_t quad8_count_preset_write(struct counter_device *counter,
 static ssize_t quad8_count_ceiling_read(struct counter_device *counter,
        struct counter_count *count, void *private, char *buf)
 {
-       const struct quad8_iio *const priv = counter->priv;
+       struct quad8_iio *const priv = counter->priv;
+
+       mutex_lock(&priv->lock);
 
        /* Range Limit and Modulo-N count modes use preset value as ceiling */
        switch (priv->count_mode[count->id]) {
        case 1:
        case 3:
-               return quad8_count_preset_read(counter, count, private, buf);
+               mutex_unlock(&priv->lock);
+               return sprintf(buf, "%u\n", priv->preset[count->id]);
        }
 
+       mutex_unlock(&priv->lock);
+
        /* By default 0x1FFFFFF (25 bits unsigned) is maximum count */
        return sprintf(buf, "33554431\n");
 }
@@ -1101,15 +1206,29 @@ static ssize_t quad8_count_ceiling_write(struct counter_device *counter,
        struct counter_count *count, void *private, const char *buf, size_t len)
 {
        struct quad8_iio *const priv = counter->priv;
+       unsigned int ceiling;
+       int ret;
+
+       ret = kstrtouint(buf, 0, &ceiling);
+       if (ret)
+               return ret;
+
+       /* Only 24-bit values are supported */
+       if (ceiling > 0xFFFFFF)
+               return -EINVAL;
+
+       mutex_lock(&priv->lock);
 
        /* Range Limit and Modulo-N count modes use preset value as ceiling */
        switch (priv->count_mode[count->id]) {
        case 1:
        case 3:
-               return quad8_count_preset_write(counter, count, private, buf,
-                                               len);
+               quad8_preset_register_set(priv, count->id, ceiling);
+               break;
        }
 
+       mutex_unlock(&priv->lock);
+
        return len;
 }
 
@@ -1137,6 +1256,8 @@ static ssize_t quad8_count_preset_enable_write(struct counter_device *counter,
        /* Preset enable is active low in Input/Output Control register */
        preset_enable = !preset_enable;
 
+       mutex_lock(&priv->lock);
+
        priv->preset_enable[count->id] = preset_enable;
 
        ior_cfg = priv->ab_enable[count->id] | (unsigned int)preset_enable << 1;
@@ -1144,6 +1265,8 @@ static ssize_t quad8_count_preset_enable_write(struct counter_device *counter,
        /* Load I/O control configuration to Input / Output Control Register */
        outb(QUAD8_CTR_IOR | ior_cfg, base_offset);
 
+       mutex_unlock(&priv->lock);
+
        return len;
 }
 
@@ -1429,6 +1552,9 @@ static int quad8_probe(struct device *dev, unsigned int id)
        quad8iio->counter.priv = quad8iio;
        quad8iio->base = base[id];
 
+       /* Initialize mutex */
+       mutex_init(&quad8iio->lock);
+
        /* Reset all counters and disable interrupt function */
        outb(QUAD8_CHAN_OP_RESET_COUNTERS, base[id] + QUAD8_REG_CHAN_OP);
        /* Set initial configuration for all counters */
index 4d1e25d1ced18e878859346b35dc81d2e864f95f..4d3429b2058fcc5f16582b53c516922c263d56ae 100644 (file)
@@ -1059,7 +1059,7 @@ static ssize_t store_no_turbo(struct kobject *a, struct kobj_attribute *b,
 
        update_turbo_state();
        if (global.turbo_disabled) {
-               pr_warn("Turbo disabled by BIOS or unavailable on processor\n");
+               pr_notice_once("Turbo disabled by BIOS or unavailable on processor\n");
                mutex_unlock(&intel_pstate_limits_lock);
                mutex_unlock(&intel_pstate_driver_lock);
                return -EPERM;
index b7bb7c30adeb823d92fd5f233d40e0ba644f0afa..b2f9882bc010f1619b0e17eb2204caaecf41895c 100644 (file)
@@ -963,10 +963,12 @@ static void aead_crypt_done(struct device *jrdev, u32 *desc, u32 err,
        struct caam_drv_private_jr *jrp = dev_get_drvdata(jrdev);
        struct aead_edesc *edesc;
        int ecode = 0;
+       bool has_bklog;
 
        dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 
        edesc = rctx->edesc;
+       has_bklog = edesc->bklog;
 
        if (err)
                ecode = caam_jr_strstatus(jrdev, err);
@@ -979,7 +981,7 @@ static void aead_crypt_done(struct device *jrdev, u32 *desc, u32 err,
         * If no backlog flag, the completion of the request is done
         * by CAAM, not crypto engine.
         */
-       if (!edesc->bklog)
+       if (!has_bklog)
                aead_request_complete(req, ecode);
        else
                crypto_finalize_aead_request(jrp->engine, req, ecode);
@@ -995,10 +997,12 @@ static void skcipher_crypt_done(struct device *jrdev, u32 *desc, u32 err,
        struct caam_drv_private_jr *jrp = dev_get_drvdata(jrdev);
        int ivsize = crypto_skcipher_ivsize(skcipher);
        int ecode = 0;
+       bool has_bklog;
 
        dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 
        edesc = rctx->edesc;
+       has_bklog = edesc->bklog;
        if (err)
                ecode = caam_jr_strstatus(jrdev, err);
 
@@ -1028,7 +1032,7 @@ static void skcipher_crypt_done(struct device *jrdev, u32 *desc, u32 err,
         * If no backlog flag, the completion of the request is done
         * by CAAM, not crypto engine.
         */
-       if (!edesc->bklog)
+       if (!has_bklog)
                skcipher_request_complete(req, ecode);
        else
                crypto_finalize_skcipher_request(jrp->engine, req, ecode);
@@ -1711,7 +1715,7 @@ static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req,
 
        if (ivsize || mapped_dst_nents > 1)
                sg_to_sec4_set_last(edesc->sec4_sg + dst_sg_idx +
-                                   mapped_dst_nents);
+                                   mapped_dst_nents - 1 + !!ivsize);
 
        if (sec4_sg_bytes) {
                edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
index 943bc0296267d3a751c5493358a2a291ff3b5af2..27ff4a3d037ee6927f5a44c1072bdb7f266c933b 100644 (file)
@@ -583,10 +583,12 @@ static inline void ahash_done_cpy(struct device *jrdev, u32 *desc, u32 err,
        struct caam_hash_state *state = ahash_request_ctx(req);
        struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
        int ecode = 0;
+       bool has_bklog;
 
        dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 
        edesc = state->edesc;
+       has_bklog = edesc->bklog;
 
        if (err)
                ecode = caam_jr_strstatus(jrdev, err);
@@ -603,7 +605,7 @@ static inline void ahash_done_cpy(struct device *jrdev, u32 *desc, u32 err,
         * If no backlog flag, the completion of the request is done
         * by CAAM, not crypto engine.
         */
-       if (!edesc->bklog)
+       if (!has_bklog)
                req->base.complete(&req->base, ecode);
        else
                crypto_finalize_hash_request(jrp->engine, req, ecode);
@@ -632,10 +634,12 @@ static inline void ahash_done_switch(struct device *jrdev, u32 *desc, u32 err,
        struct caam_hash_state *state = ahash_request_ctx(req);
        int digestsize = crypto_ahash_digestsize(ahash);
        int ecode = 0;
+       bool has_bklog;
 
        dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 
        edesc = state->edesc;
+       has_bklog = edesc->bklog;
        if (err)
                ecode = caam_jr_strstatus(jrdev, err);
 
@@ -663,7 +667,7 @@ static inline void ahash_done_switch(struct device *jrdev, u32 *desc, u32 err,
         * If no backlog flag, the completion of the request is done
         * by CAAM, not crypto engine.
         */
-       if (!edesc->bklog)
+       if (!has_bklog)
                req->base.complete(&req->base, ecode);
        else
                crypto_finalize_hash_request(jrp->engine, req, ecode);
index 4fcae37a2e33c1943c99b2945ea7703233d155c2..2e44d685618fded647b016c6a4e250ae40971032 100644 (file)
@@ -121,11 +121,13 @@ static void rsa_pub_done(struct device *dev, u32 *desc, u32 err, void *context)
        struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
        struct rsa_edesc *edesc;
        int ecode = 0;
+       bool has_bklog;
 
        if (err)
                ecode = caam_jr_strstatus(dev, err);
 
        edesc = req_ctx->edesc;
+       has_bklog = edesc->bklog;
 
        rsa_pub_unmap(dev, edesc, req);
        rsa_io_unmap(dev, edesc, req);
@@ -135,7 +137,7 @@ static void rsa_pub_done(struct device *dev, u32 *desc, u32 err, void *context)
         * If no backlog flag, the completion of the request is done
         * by CAAM, not crypto engine.
         */
-       if (!edesc->bklog)
+       if (!has_bklog)
                akcipher_request_complete(req, ecode);
        else
                crypto_finalize_akcipher_request(jrp->engine, req, ecode);
@@ -152,11 +154,13 @@ static void rsa_priv_f_done(struct device *dev, u32 *desc, u32 err,
        struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
        struct rsa_edesc *edesc;
        int ecode = 0;
+       bool has_bklog;
 
        if (err)
                ecode = caam_jr_strstatus(dev, err);
 
        edesc = req_ctx->edesc;
+       has_bklog = edesc->bklog;
 
        switch (key->priv_form) {
        case FORM1:
@@ -176,7 +180,7 @@ static void rsa_priv_f_done(struct device *dev, u32 *desc, u32 err,
         * If no backlog flag, the completion of the request is done
         * by CAAM, not crypto engine.
         */
-       if (!edesc->bklog)
+       if (!has_bklog)
                akcipher_request_complete(req, ecode);
        else
                crypto_finalize_akcipher_request(jrp->engine, req, ecode);
index cd1769ecdc1cc99b68fa9b50bd329621d6be320e..43d9e24201104b9c33d402ee60b42d573c62cc58 100644 (file)
@@ -120,12 +120,10 @@ out:
 static int chcr_ktls_update_connection_state(struct chcr_ktls_info *tx_info,
                                             int new_state)
 {
-       unsigned long flags;
-
        /* This function can be called from both rx (interrupt context) and tx
         * queue contexts.
         */
-       spin_lock_irqsave(&tx_info->lock, flags);
+       spin_lock_bh(&tx_info->lock);
        switch (tx_info->connection_state) {
        case KTLS_CONN_CLOSED:
                tx_info->connection_state = new_state;
@@ -169,7 +167,7 @@ static int chcr_ktls_update_connection_state(struct chcr_ktls_info *tx_info,
                pr_err("unknown KTLS connection state\n");
                break;
        }
-       spin_unlock_irqrestore(&tx_info->lock, flags);
+       spin_unlock_bh(&tx_info->lock);
 
        return tx_info->connection_state;
 }
@@ -675,41 +673,14 @@ int chcr_ktls_cpl_set_tcb_rpl(struct adapter *adap, unsigned char *input)
        return 0;
 }
 
-/*
- * chcr_write_cpl_set_tcb_ulp: update tcb values.
- * TCB is responsible to create tcp headers, so all the related values
- * should be correctly updated.
- * @tx_info - driver specific tls info.
- * @q - tx queue on which packet is going out.
- * @tid - TCB identifier.
- * @pos - current index where should we start writing.
- * @word - TCB word.
- * @mask - TCB word related mask.
- * @val - TCB word related value.
- * @reply - set 1 if looking for TP response.
- * return - next position to write.
- */
-static void *chcr_write_cpl_set_tcb_ulp(struct chcr_ktls_info *tx_info,
-                                       struct sge_eth_txq *q, u32 tid,
-                                       void *pos, u16 word, u64 mask,
+static void *__chcr_write_cpl_set_tcb_ulp(struct chcr_ktls_info *tx_info,
+                                       u32 tid, void *pos, u16 word, u64 mask,
                                        u64 val, u32 reply)
 {
        struct cpl_set_tcb_field_core *cpl;
        struct ulptx_idata *idata;
        struct ulp_txpkt *txpkt;
-       void *save_pos = NULL;
-       u8 buf[48] = {0};
-       int left;
 
-       left = (void *)q->q.stat - pos;
-       if (unlikely(left < CHCR_SET_TCB_FIELD_LEN)) {
-               if (!left) {
-                       pos = q->q.desc;
-               } else {
-                       save_pos = pos;
-                       pos = buf;
-               }
-       }
        /* ULP_TXPKT */
        txpkt = pos;
        txpkt->cmd_dest = htonl(ULPTX_CMD_V(ULP_TX_PKT) | ULP_TXPKT_DEST_V(0));
@@ -734,18 +705,54 @@ static void *chcr_write_cpl_set_tcb_ulp(struct chcr_ktls_info *tx_info,
        idata = (struct ulptx_idata *)(cpl + 1);
        idata->cmd_more = htonl(ULPTX_CMD_V(ULP_TX_SC_NOOP));
        idata->len = htonl(0);
+       pos = idata + 1;
 
-       if (save_pos) {
-               pos = chcr_copy_to_txd(buf, &q->q, save_pos,
-                                      CHCR_SET_TCB_FIELD_LEN);
-       } else {
-               /* check again if we are at the end of the queue */
-               if (left == CHCR_SET_TCB_FIELD_LEN)
+       return pos;
+}
+
+
+/*
+ * chcr_write_cpl_set_tcb_ulp: update tcb values.
+ * TCB is responsible to create tcp headers, so all the related values
+ * should be correctly updated.
+ * @tx_info - driver specific tls info.
+ * @q - tx queue on which packet is going out.
+ * @tid - TCB identifier.
+ * @pos - current index where should we start writing.
+ * @word - TCB word.
+ * @mask - TCB word related mask.
+ * @val - TCB word related value.
+ * @reply - set 1 if looking for TP response.
+ * return - next position to write.
+ */
+static void *chcr_write_cpl_set_tcb_ulp(struct chcr_ktls_info *tx_info,
+                                       struct sge_eth_txq *q, u32 tid,
+                                       void *pos, u16 word, u64 mask,
+                                       u64 val, u32 reply)
+{
+       int left = (void *)q->q.stat - pos;
+
+       if (unlikely(left < CHCR_SET_TCB_FIELD_LEN)) {
+               if (!left) {
                        pos = q->q.desc;
-               else
-                       pos = idata + 1;
+               } else {
+                       u8 buf[48] = {0};
+
+                       __chcr_write_cpl_set_tcb_ulp(tx_info, tid, buf, word,
+                                                    mask, val, reply);
+
+                       return chcr_copy_to_txd(buf, &q->q, pos,
+                                               CHCR_SET_TCB_FIELD_LEN);
+               }
        }
 
+       pos = __chcr_write_cpl_set_tcb_ulp(tx_info, tid, pos, word,
+                                          mask, val, reply);
+
+       /* check again if we are at the end of the queue */
+       if (left == CHCR_SET_TCB_FIELD_LEN)
+               pos = q->q.desc;
+
        return pos;
 }
 
index ccc9eda1bc282851a6b4d2777297de271b03b029..07df88f2e3057e0c9def11f24b3d430823d30350 100644 (file)
@@ -388,7 +388,8 @@ static long dma_buf_ioctl(struct file *file,
 
                return ret;
 
-       case DMA_BUF_SET_NAME:
+       case DMA_BUF_SET_NAME_A:
+       case DMA_BUF_SET_NAME_B:
                return dma_buf_set_name(dmabuf, (const char __user *)arg);
 
        default:
@@ -655,8 +656,8 @@ EXPORT_SYMBOL_GPL(dma_buf_put);
  * calls attach() of dma_buf_ops to allow device-specific attach functionality
  * @dmabuf:            [in]    buffer to attach device to.
  * @dev:               [in]    device to be attached.
- * @importer_ops       [in]    importer operations for the attachment
- * @importer_priv      [in]    importer private pointer for the attachment
+ * @importer_ops:      [in]    importer operations for the attachment
+ * @importer_priv:     [in]    importer private pointer for the attachment
  *
  * Returns struct dma_buf_attachment pointer for this attachment. Attachments
  * must be cleaned up by calling dma_buf_detach().
index 0924836443152fb52d7923f85cc87ca3655cb562..023db6883d0518521b8e416a01cc4f9de22d3e83 100644 (file)
@@ -241,7 +241,8 @@ config FSL_RAID
 
 config HISI_DMA
        tristate "HiSilicon DMA Engine support"
-       depends on ARM64 || (COMPILE_TEST && PCI_MSI)
+       depends on ARM64 || COMPILE_TEST
+       depends on PCI_MSI
        select DMA_ENGINE
        select DMA_VIRTUAL_CHANNELS
        help
index 4830ba658ce18c387f6e6f138519f73014c90872..d31076d9ef258899ef9db3bf633ec828f5d616fa 100644 (file)
@@ -232,10 +232,6 @@ static void chan_dev_release(struct device *dev)
        struct dma_chan_dev *chan_dev;
 
        chan_dev = container_of(dev, typeof(*chan_dev), device);
-       if (atomic_dec_and_test(chan_dev->idr_ref)) {
-               ida_free(&dma_ida, chan_dev->dev_id);
-               kfree(chan_dev->idr_ref);
-       }
        kfree(chan_dev);
 }
 
@@ -1043,27 +1039,9 @@ static int get_dma_id(struct dma_device *device)
 }
 
 static int __dma_async_device_channel_register(struct dma_device *device,
-                                              struct dma_chan *chan,
-                                              int chan_id)
+                                              struct dma_chan *chan)
 {
        int rc = 0;
-       int chancnt = device->chancnt;
-       atomic_t *idr_ref;
-       struct dma_chan *tchan;
-
-       tchan = list_first_entry_or_null(&device->channels,
-                                        struct dma_chan, device_node);
-       if (!tchan)
-               return -ENODEV;
-
-       if (tchan->dev) {
-               idr_ref = tchan->dev->idr_ref;
-       } else {
-               idr_ref = kmalloc(sizeof(*idr_ref), GFP_KERNEL);
-               if (!idr_ref)
-                       return -ENOMEM;
-               atomic_set(idr_ref, 0);
-       }
 
        chan->local = alloc_percpu(typeof(*chan->local));
        if (!chan->local)
@@ -1079,29 +1057,36 @@ static int __dma_async_device_channel_register(struct dma_device *device,
         * When the chan_id is a negative value, we are dynamically adding
         * the channel. Otherwise we are static enumerating.
         */
-       chan->chan_id = chan_id < 0 ? chancnt : chan_id;
+       mutex_lock(&device->chan_mutex);
+       chan->chan_id = ida_alloc(&device->chan_ida, GFP_KERNEL);
+       mutex_unlock(&device->chan_mutex);
+       if (chan->chan_id < 0) {
+               pr_err("%s: unable to alloc ida for chan: %d\n",
+                      __func__, chan->chan_id);
+               goto err_out;
+       }
+
        chan->dev->device.class = &dma_devclass;
        chan->dev->device.parent = device->dev;
        chan->dev->chan = chan;
-       chan->dev->idr_ref = idr_ref;
        chan->dev->dev_id = device->dev_id;
-       atomic_inc(idr_ref);
        dev_set_name(&chan->dev->device, "dma%dchan%d",
                     device->dev_id, chan->chan_id);
-
        rc = device_register(&chan->dev->device);
        if (rc)
-               goto err_out;
+               goto err_out_ida;
        chan->client_count = 0;
-       device->chancnt = chan->chan_id + 1;
+       device->chancnt++;
 
        return 0;
 
+ err_out_ida:
+       mutex_lock(&device->chan_mutex);
+       ida_free(&device->chan_ida, chan->chan_id);
+       mutex_unlock(&device->chan_mutex);
  err_out:
        free_percpu(chan->local);
        kfree(chan->dev);
-       if (atomic_dec_return(idr_ref) == 0)
-               kfree(idr_ref);
        return rc;
 }
 
@@ -1110,7 +1095,7 @@ int dma_async_device_channel_register(struct dma_device *device,
 {
        int rc;
 
-       rc = __dma_async_device_channel_register(device, chan, -1);
+       rc = __dma_async_device_channel_register(device, chan);
        if (rc < 0)
                return rc;
 
@@ -1130,6 +1115,9 @@ static void __dma_async_device_channel_unregister(struct dma_device *device,
        device->chancnt--;
        chan->dev->chan = NULL;
        mutex_unlock(&dma_list_mutex);
+       mutex_lock(&device->chan_mutex);
+       ida_free(&device->chan_ida, chan->chan_id);
+       mutex_unlock(&device->chan_mutex);
        device_unregister(&chan->dev->device);
        free_percpu(chan->local);
 }
@@ -1152,7 +1140,7 @@ EXPORT_SYMBOL_GPL(dma_async_device_channel_unregister);
  */
 int dma_async_device_register(struct dma_device *device)
 {
-       int rc, i = 0;
+       int rc;
        struct dma_chan* chan;
 
        if (!device)
@@ -1257,9 +1245,12 @@ int dma_async_device_register(struct dma_device *device)
        if (rc != 0)
                return rc;
 
+       mutex_init(&device->chan_mutex);
+       ida_init(&device->chan_ida);
+
        /* represent channels in sysfs. Probably want devs too */
        list_for_each_entry(chan, &device->channels, device_node) {
-               rc = __dma_async_device_channel_register(device, chan, i++);
+               rc = __dma_async_device_channel_register(device, chan);
                if (rc < 0)
                        goto err_out;
        }
@@ -1334,6 +1325,7 @@ void dma_async_device_unregister(struct dma_device *device)
         */
        dma_cap_set(DMA_PRIVATE, device->cap_mask);
        dma_channel_rebalance();
+       ida_free(&dma_ida, device->dev_id);
        dma_device_put(device);
        mutex_unlock(&dma_list_mutex);
 }
index a2cadfa2e6d7848e8d4a163a0a6e5f387b26622c..364dd34799d45cf490e19f7062eae2139f504d4c 100644 (file)
@@ -240,7 +240,7 @@ static bool is_threaded_test_run(struct dmatest_info *info)
                struct dmatest_thread *thread;
 
                list_for_each_entry(thread, &dtc->threads, node) {
-                       if (!thread->done)
+                       if (!thread->done && !thread->pending)
                                return true;
                }
        }
@@ -662,8 +662,8 @@ static int dmatest_func(void *data)
                flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
 
        ktime = ktime_get();
-       while (!kthread_should_stop()
-              && !(params->iterations && total_tests >= params->iterations)) {
+       while (!(kthread_should_stop() ||
+              (params->iterations && total_tests >= params->iterations))) {
                struct dma_async_tx_descriptor *tx = NULL;
                struct dmaengine_unmap_data *um;
                dma_addr_t *dsts;
index 10117f271b12b2cfb540438b4cd979e92da3d265..d683232d7fea072f80d31a92ae553afe2c6ab236 100644 (file)
@@ -363,6 +363,8 @@ static void mmp_tdma_free_descriptor(struct mmp_tdma_chan *tdmac)
                gen_pool_free(gpool, (unsigned long)tdmac->desc_arr,
                                size);
        tdmac->desc_arr = NULL;
+       if (tdmac->status == DMA_ERROR)
+               tdmac->status = DMA_COMPLETE;
 
        return;
 }
@@ -443,7 +445,8 @@ static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic(
        if (!desc)
                goto err_out;
 
-       mmp_tdma_config_write(chan, direction, &tdmac->slave_config);
+       if (mmp_tdma_config_write(chan, direction, &tdmac->slave_config))
+               goto err_out;
 
        while (buf < buf_len) {
                desc = &tdmac->desc_arr[i];
index 581e7a290d98e1856cb1d0428c53b4aaee6ce518..a3b0b4c56a190b55ec242762d3766dfae506dbb9 100644 (file)
@@ -865,6 +865,7 @@ static int pch_dma_probe(struct pci_dev *pdev,
        }
 
        pci_set_master(pdev);
+       pd->dma.dev = &pdev->dev;
 
        err = request_irq(pdev->irq, pd_irq, IRQF_SHARED, DRV_NAME, pd);
        if (err) {
@@ -880,7 +881,6 @@ static int pch_dma_probe(struct pci_dev *pdev,
                goto err_free_irq;
        }
 
-       pd->dma.dev = &pdev->dev;
 
        INIT_LIST_HEAD(&pd->dma.channels);
 
index f6a2f42ffc514414965f40dae2be5143c37c87cc..b9f0d9636620d22ae8ef89413f929e99dfbfee22 100644 (file)
@@ -816,6 +816,13 @@ static bool tegra_dma_eoc_interrupt_deasserted(struct tegra_dma_channel *tdc)
 static void tegra_dma_synchronize(struct dma_chan *dc)
 {
        struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc);
+       int err;
+
+       err = pm_runtime_get_sync(tdc->tdma->dev);
+       if (err < 0) {
+               dev_err(tdc2dev(tdc), "Failed to synchronize DMA: %d\n", err);
+               return;
+       }
 
        /*
         * CPU, which handles interrupt, could be busy in
@@ -825,6 +832,8 @@ static void tegra_dma_synchronize(struct dma_chan *dc)
        wait_event(tdc->wq, tegra_dma_eoc_interrupt_deasserted(tdc));
 
        tasklet_kill(&tdc->tasklet);
+
+       pm_runtime_put(tdc->tdma->dev);
 }
 
 static unsigned int tegra_dma_sg_bytes_xferred(struct tegra_dma_channel *tdc,
index d7b965049ccb1e63149bf8d636e95952bc5c9f52..fb7c8150b0d1d971ded5f66091c039864ee23215 100644 (file)
@@ -27,6 +27,7 @@ struct psil_endpoint_config *psil_get_ep_config(u32 thread_id)
                        soc_ep_map = &j721e_ep_map;
                } else {
                        pr_err("PSIL: No compatible machine found for map\n");
+                       mutex_unlock(&ep_map_mutex);
                        return ERR_PTR(-ENOTSUPP);
                }
                pr_debug("%s: Using map for %s\n", __func__, soc_ep_map->name);
index aecd5a35a29651dd68a5c7d9c680b97351b4a652..5429497d3560be6a54ace01afaf51ac3ad8a1427 100644 (file)
@@ -1230,16 +1230,16 @@ static enum dma_status xilinx_dma_tx_status(struct dma_chan *dchan,
                return ret;
 
        spin_lock_irqsave(&chan->lock, flags);
-
-       desc = list_last_entry(&chan->active_list,
-                              struct xilinx_dma_tx_descriptor, node);
-       /*
-        * VDMA and simple mode do not support residue reporting, so the
-        * residue field will always be 0.
-        */
-       if (chan->has_sg && chan->xdev->dma_config->dmatype != XDMA_TYPE_VDMA)
-               residue = xilinx_dma_get_residue(chan, desc);
-
+       if (!list_empty(&chan->active_list)) {
+               desc = list_last_entry(&chan->active_list,
+                                      struct xilinx_dma_tx_descriptor, node);
+               /*
+                * VDMA and simple mode do not support residue reporting, so the
+                * residue field will always be 0.
+                */
+               if (chan->has_sg && chan->xdev->dma_config->dmatype != XDMA_TYPE_VDMA)
+                       residue = xilinx_dma_get_residue(chan, desc);
+       }
        spin_unlock_irqrestore(&chan->lock, flags);
 
        dma_set_residue(txstate, residue);
index b1af0de2e10080ef8080183d0797436217520b28..9d2512913d2587361b576893897969d73e24d029 100644 (file)
@@ -101,7 +101,7 @@ void cper_print_bits(const char *pfx, unsigned int bits,
                if (!len)
                        len = snprintf(buf, sizeof(buf), "%s%s", pfx, str);
                else
-                       len += snprintf(buf+len, sizeof(buf)-len, ", %s", str);
+                       len += scnprintf(buf+len, sizeof(buf)-len, ", %s", str);
        }
        if (len)
                printk("%s\n", buf);
index cc90a748bcf0208a6a7c6cfc5b7815f2487dfe7f..67d26949fd26df4a90ed2a6793d55940b46cef6c 100644 (file)
@@ -25,7 +25,7 @@
 #define EFI_ALLOC_ALIGN                EFI_PAGE_SIZE
 #endif
 
-#ifdef CONFIG_ARM
+#if defined(CONFIG_ARM) || defined(CONFIG_X86)
 #define __efistub_global       __section(.data)
 #else
 #define __efistub_global
index d4c7e5f59d2c8eaa63d34967b0c28c799aa39449..ea66b1f16a79d17b4b5bf1cce7a92042a296af69 100644 (file)
  */
 #define EFI_READ_CHUNK_SIZE    SZ_1M
 
+struct finfo {
+       efi_file_info_t info;
+       efi_char16_t    filename[MAX_FILENAME_SIZE];
+};
+
 static efi_status_t efi_open_file(efi_file_protocol_t *volume,
-                                 efi_char16_t *filename_16,
+                                 struct finfo *fi,
                                  efi_file_protocol_t **handle,
                                  unsigned long *file_size)
 {
-       struct {
-               efi_file_info_t info;
-               efi_char16_t    filename[MAX_FILENAME_SIZE];
-       } finfo;
        efi_guid_t info_guid = EFI_FILE_INFO_ID;
        efi_file_protocol_t *fh;
        unsigned long info_sz;
        efi_status_t status;
 
-       status = volume->open(volume, &fh, filename_16, EFI_FILE_MODE_READ, 0);
+       status = volume->open(volume, &fh, fi->filename, EFI_FILE_MODE_READ, 0);
        if (status != EFI_SUCCESS) {
                pr_efi_err("Failed to open file: ");
-               efi_char16_printk(filename_16);
+               efi_char16_printk(fi->filename);
                efi_printk("\n");
                return status;
        }
 
-       info_sz = sizeof(finfo);
-       status = fh->get_info(fh, &info_guid, &info_sz, &finfo);
+       info_sz = sizeof(struct finfo);
+       status = fh->get_info(fh, &info_guid, &info_sz, fi);
        if (status != EFI_SUCCESS) {
                pr_efi_err("Failed to get file info\n");
                fh->close(fh);
@@ -60,7 +61,7 @@ static efi_status_t efi_open_file(efi_file_protocol_t *volume,
        }
 
        *handle = fh;
-       *file_size = finfo.info.file_size;
+       *file_size = fi->info.file_size;
        return EFI_SUCCESS;
 }
 
@@ -146,13 +147,13 @@ static efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
 
        alloc_addr = alloc_size = 0;
        do {
-               efi_char16_t filename[MAX_FILENAME_SIZE];
+               struct finfo fi;
                unsigned long size;
                void *addr;
 
                offset = find_file_option(cmdline, cmdline_len,
                                          optstr, optstr_size,
-                                         filename, ARRAY_SIZE(filename));
+                                         fi.filename, ARRAY_SIZE(fi.filename));
 
                if (!offset)
                        break;
@@ -166,7 +167,7 @@ static efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
                                return status;
                }
 
-               status = efi_open_file(volume, filename, &file, &size);
+               status = efi_open_file(volume, &fi, &file, &size);
                if (status != EFI_SUCCESS)
                        goto err_close_volume;
 
index 8d3a707789de83fd3c713a081505dbd8a2b33346..05ccb229fb45ffbb24df88bbb1f90ffb5ec73f77 100644 (file)
@@ -20,7 +20,7 @@
 /* Maximum physical address for 64-bit kernel with 4-level paging */
 #define MAXMEM_X86_64_4LEVEL (1ull << 46)
 
-static efi_system_table_t *sys_table;
+static efi_system_table_t *sys_table __efistub_global;
 extern const bool efi_is64;
 extern u32 image_offset;
 
@@ -392,8 +392,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
        image_base = efi_table_attr(image, image_base);
        image_offset = (void *)startup_32 - image_base;
 
-       hdr = &((struct boot_params *)image_base)->hdr;
-
        status = efi_allocate_pages(0x4000, (unsigned long *)&boot_params, ULONG_MAX);
        if (status != EFI_SUCCESS) {
                efi_printk("Failed to allocate lowmem for boot params\n");
@@ -742,8 +740,15 @@ unsigned long efi_main(efi_handle_t handle,
         * now use KERNEL_IMAGE_SIZE, which will be 512MiB, the same as what
         * KASLR uses.
         *
-        * Also relocate it if image_offset is zero, i.e. we weren't loaded by
-        * LoadImage, but we are not aligned correctly.
+        * Also relocate it if image_offset is zero, i.e. the kernel wasn't
+        * loaded by LoadImage, but rather by a bootloader that called the
+        * handover entry. The reason we must always relocate in this case is
+        * to handle the case of systemd-boot booting a unified kernel image,
+        * which is a PE executable that contains the bzImage and an initrd as
+        * COFF sections. The initrd section is placed after the bzImage
+        * without ensuring that there are at least init_size bytes available
+        * for the bzImage, and thus the compressed kernel's startup code may
+        * overwrite the initrd unless it is moved out of the way.
         */
 
        buffer_start = ALIGN(bzimage_addr - image_offset,
@@ -753,8 +758,7 @@ unsigned long efi_main(efi_handle_t handle,
        if ((buffer_start < LOAD_PHYSICAL_ADDR)                              ||
            (IS_ENABLED(CONFIG_X86_32) && buffer_end > KERNEL_IMAGE_SIZE)    ||
            (IS_ENABLED(CONFIG_X86_64) && buffer_end > MAXMEM_X86_64_4LEVEL) ||
-           (image_offset == 0 && !IS_ALIGNED(bzimage_addr,
-                                             hdr->kernel_alignment))) {
+           (image_offset == 0)) {
                status = efi_relocate_kernel(&bzimage_addr,
                                             hdr->init_size, hdr->init_size,
                                             hdr->pref_address,
index 31f9f0e369b977345dee40523d2f615aec402e84..55b031d2c989074ec9f3b53f9662865d2e448122 100644 (file)
@@ -16,7 +16,7 @@
 int efi_tpm_final_log_size;
 EXPORT_SYMBOL(efi_tpm_final_log_size);
 
-static int tpm2_calc_event_log_size(void *data, int count, void *size_info)
+static int __init tpm2_calc_event_log_size(void *data, int count, void *size_info)
 {
        struct tcg_pcr_event2_head *header;
        int event_size, size = 0;
index 116707a075f35b234076f5f7798a6b281f27e4ae..1d2e5b85d7ca8458f3d67bac38b964f4f9100ef6 100644 (file)
@@ -12,7 +12,7 @@ config IMX_DSP
 
 config IMX_SCU
        bool "IMX SCU Protocol driver"
-       depends on IMX_MBOX || COMPILE_TEST
+       depends on IMX_MBOX
        help
          The System Controller Firmware (SCFW) is a low-level system function
          which runs on a dedicated Cortex-M core to provide power, clock, and
@@ -24,6 +24,6 @@ config IMX_SCU
 
 config IMX_SCU_PD
        bool "IMX SCU Power Domain driver"
-       depends on IMX_SCU || COMPILE_TEST
+       depends on IMX_SCU
        help
          The System Controller Firmware (SCFW) based power domain driver.
index c6d0724da4dbca771174984efa414170fdd426c3..43bc6cfdab45ea3a8803870c183c5e8264652a0c 100644 (file)
@@ -35,7 +35,7 @@ static struct pm_api_info pm_api_list[] = {
        PM_API(PM_QUERY_DATA),
 };
 
-struct dentry *firmware_debugfs_root;
+static struct dentry *firmware_debugfs_root;
 
 /**
  * zynqmp_pm_argument_value() - Extract argument value from a PM-API request
index 89ca292236ad8655ea582b72d264e4bf1bde8aa5..538755062ab7ca7d8fee6911ca2af02a8afc7a37 100644 (file)
@@ -248,11 +248,13 @@ static int cci_pci_sriov_configure(struct pci_dev *pcidev, int num_vfs)
                        return ret;
 
                ret = pci_enable_sriov(pcidev, num_vfs);
-               if (ret)
+               if (ret) {
                        dfl_fpga_cdev_config_ports_pf(cdev);
+                       return ret;
+               }
        }
 
-       return ret;
+       return num_vfs;
 }
 
 static void cci_pci_remove(struct pci_dev *pcidev)
index ee7765049607453933c5e4541ba3751a3bc02b03..07fa8d9ec67500586878267c2cd7ee541ceeeefd 100644 (file)
@@ -583,7 +583,8 @@ static int zynq_fpga_probe(struct platform_device *pdev)
 
        priv->clk = devm_clk_get(dev, "ref_clk");
        if (IS_ERR(priv->clk)) {
-               dev_err(dev, "input clock not found\n");
+               if (PTR_ERR(priv->clk) != -EPROBE_DEFER)
+                       dev_err(dev, "input clock not found\n");
                return PTR_ERR(priv->clk);
        }
 
index 559dc24ef436719f1b25992070b360d2e911fc16..affde2de2a0dbd3f68f934c693ff7a906f9223a7 100644 (file)
@@ -2008,8 +2008,24 @@ static void amdgpu_device_fill_reset_magic(struct amdgpu_device *adev)
  */
 static bool amdgpu_device_check_vram_lost(struct amdgpu_device *adev)
 {
-       return !!memcmp(adev->gart.ptr, adev->reset_magic,
-                       AMDGPU_RESET_MAGIC_NUM);
+       if (memcmp(adev->gart.ptr, adev->reset_magic,
+                       AMDGPU_RESET_MAGIC_NUM))
+               return true;
+
+       if (!adev->in_gpu_reset)
+               return false;
+
+       /*
+        * For all ASICs with baco/mode1 reset, the VRAM is
+        * always assumed to be lost.
+        */
+       switch (amdgpu_asic_reset_method(adev)) {
+       case AMD_RESET_METHOD_BACO:
+       case AMD_RESET_METHOD_MODE1:
+               return true;
+       default:
+               return false;
+       }
 }
 
 /**
@@ -2340,6 +2356,8 @@ static int amdgpu_device_ip_suspend_phase1(struct amdgpu_device *adev)
 {
        int i, r;
 
+       amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
+       amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
 
        for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
                if (!adev->ip_blocks[i].status.valid)
@@ -3354,15 +3372,12 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
                }
        }
 
-       amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
-       amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
-
-       amdgpu_amdkfd_suspend(adev, !fbcon);
-
        amdgpu_ras_suspend(adev);
 
        r = amdgpu_device_ip_suspend_phase1(adev);
 
+       amdgpu_amdkfd_suspend(adev, !fbcon);
+
        /* evict vram memory */
        amdgpu_bo_evict_vram(adev);
 
index 8ea86ffdea0d8dfbcf860c67bc1cfc08d26885a8..466bfe541e455599377f6d8dcdf0948749348a8e 100644 (file)
  * - 3.34.0 - Non-DC can flip correctly between buffers with different pitches
  * - 3.35.0 - Add drm_amdgpu_info_device::tcc_disabled_mask
  * - 3.36.0 - Allow reading more status registers on si/cik
+ * - 3.37.0 - L2 is invalidated before SDMA IBs, needed for correctness
  */
 #define KMS_DRIVER_MAJOR       3
-#define KMS_DRIVER_MINOR       36
+#define KMS_DRIVER_MINOR       37
 #define KMS_DRIVER_PATCHLEVEL  0
 
 int amdgpu_vram_limit = 0;
index 006f21ef7ddf09a375ead24f7b31af1fa41fd207..62635e58e45eede7c7a48e1b0c35372f8607c896 100644 (file)
@@ -1358,8 +1358,6 @@ static int cik_asic_reset(struct amdgpu_device *adev)
        int r;
 
        if (cik_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) {
-               if (!adev->in_suspend)
-                       amdgpu_inc_vram_lost(adev);
                r = amdgpu_dpm_baco_reset(adev);
        } else {
                r = cik_asic_pci_config_reset(adev);
index d78059fd2c72560d14392949e4fbc434cb82787b..f92c158d89a12ba4906014fcc6868969858c4abf 100644 (file)
@@ -279,7 +279,7 @@ static const struct soc15_reg_golden golden_settings_gc_10_1_2_nv12[] =
 
 #define DEFAULT_SH_MEM_CONFIG \
        ((SH_MEM_ADDRESS_MODE_64 << SH_MEM_CONFIG__ADDRESS_MODE__SHIFT) | \
-        (SH_MEM_ALIGNMENT_MODE_DWORD << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | \
+        (SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | \
         (SH_MEM_RETRY_MODE_ALL << SH_MEM_CONFIG__RETRY_MODE__SHIFT) | \
         (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT))
 
index e6b113ed2f409f718dd3d3ac22fb2172be290564..0c390485bc106455960cfe2120d2dec47d4b7bfd 100644 (file)
@@ -1234,6 +1234,8 @@ struct amdgpu_gfxoff_quirk {
 static const struct amdgpu_gfxoff_quirk amdgpu_gfxoff_quirk_list[] = {
        /* https://bugzilla.kernel.org/show_bug.cgi?id=204689 */
        { 0x1002, 0x15dd, 0x1002, 0x15dd, 0xc8 },
+       /* https://bugzilla.kernel.org/show_bug.cgi?id=207171 */
+       { 0x1002, 0x15dd, 0x103c, 0x83e7, 0xd3 },
        { 0, 0, 0, 0, 0 },
 };
 
index 074a9a09c0a79e80b29296e22843ff962ae04d33..a5b60c9a24189d314f00b7ee1c09d8896ae6f2aa 100644 (file)
 #define SDMA_OP_AQL_COPY  0
 #define SDMA_OP_AQL_BARRIER_OR  0
 
+#define SDMA_GCR_RANGE_IS_PA           (1 << 18)
+#define SDMA_GCR_SEQ(x)                        (((x) & 0x3) << 16)
+#define SDMA_GCR_GL2_WB                        (1 << 15)
+#define SDMA_GCR_GL2_INV               (1 << 14)
+#define SDMA_GCR_GL2_DISCARD           (1 << 13)
+#define SDMA_GCR_GL2_RANGE(x)          (((x) & 0x3) << 11)
+#define SDMA_GCR_GL2_US                        (1 << 10)
+#define SDMA_GCR_GL1_INV               (1 << 9)
+#define SDMA_GCR_GLV_INV               (1 << 8)
+#define SDMA_GCR_GLK_INV               (1 << 7)
+#define SDMA_GCR_GLK_WB                        (1 << 6)
+#define SDMA_GCR_GLM_INV               (1 << 5)
+#define SDMA_GCR_GLM_WB                        (1 << 4)
+#define SDMA_GCR_GL1_RANGE(x)          (((x) & 0x3) << 2)
+#define SDMA_GCR_GLI_INV(x)            (((x) & 0x3) << 0)
+
 /*define for op field*/
 #define SDMA_PKT_HEADER_op_offset 0
 #define SDMA_PKT_HEADER_op_mask   0x000000FF
index 033cbbca2072d0eb430738dccbafddb5c718d119..52318b03c424ff570d22cca4b33fd10d0c971b08 100644 (file)
@@ -351,8 +351,6 @@ static int nv_asic_reset(struct amdgpu_device *adev)
        struct smu_context *smu = &adev->smu;
 
        if (nv_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) {
-               if (!adev->in_suspend)
-                       amdgpu_inc_vram_lost(adev);
                ret = smu_baco_enter(smu);
                if (ret)
                        return ret;
@@ -360,8 +358,6 @@ static int nv_asic_reset(struct amdgpu_device *adev)
                if (ret)
                        return ret;
        } else {
-               if (!adev->in_suspend)
-                       amdgpu_inc_vram_lost(adev);
                ret = nv_asic_mode1_reset(adev);
        }
 
index ebfd2cdf4e651215bc5ee0bf6d54be8ec9f46762..d2840c2f62865c23229d599fecfa530be2be7ce7 100644 (file)
@@ -382,6 +382,18 @@ static void sdma_v5_0_ring_emit_ib(struct amdgpu_ring *ring,
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
        uint64_t csa_mc_addr = amdgpu_sdma_get_csa_mc_addr(ring, vmid);
 
+       /* Invalidate L2, because if we don't do it, we might get stale cache
+        * lines from previous IBs.
+        */
+       amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_GCR_REQ));
+       amdgpu_ring_write(ring, 0);
+       amdgpu_ring_write(ring, (SDMA_GCR_GL2_INV |
+                                SDMA_GCR_GL2_WB |
+                                SDMA_GCR_GLM_INV |
+                                SDMA_GCR_GLM_WB) << 16);
+       amdgpu_ring_write(ring, 0xffffff80);
+       amdgpu_ring_write(ring, 0xffff);
+
        /* An IB packet must end on a 8 DW boundary--the next dword
         * must be on a 8-dword boundary. Our IB packet below is 6
         * dwords long, thus add x number of NOPs, such that, in
@@ -1595,7 +1607,7 @@ static const struct amdgpu_ring_funcs sdma_v5_0_ring_funcs = {
                SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 +
                SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 6 * 2 +
                10 + 10 + 10, /* sdma_v5_0_ring_emit_fence x3 for user fence, vm fence */
-       .emit_ib_size = 7 + 6, /* sdma_v5_0_ring_emit_ib */
+       .emit_ib_size = 5 + 7 + 6, /* sdma_v5_0_ring_emit_ib */
        .emit_ib = sdma_v5_0_ring_emit_ib,
        .emit_fence = sdma_v5_0_ring_emit_fence,
        .emit_pipeline_sync = sdma_v5_0_ring_emit_pipeline_sync,
index a40499d51c93cd9a1fd3f262402f92c6ae592dc4..d42a8d8a0dea9309723ab07b5afe2260614a61b3 100644 (file)
@@ -569,14 +569,10 @@ static int soc15_asic_reset(struct amdgpu_device *adev)
 
        switch (soc15_asic_reset_method(adev)) {
                case AMD_RESET_METHOD_BACO:
-                       if (!adev->in_suspend)
-                               amdgpu_inc_vram_lost(adev);
                        return soc15_asic_baco_reset(adev);
                case AMD_RESET_METHOD_MODE2:
                        return amdgpu_dpm_mode2_reset(adev);
                default:
-                       if (!adev->in_suspend)
-                               amdgpu_inc_vram_lost(adev);
                        return soc15_asic_mode1_reset(adev);
        }
 }
index 78b35901643bcf8707cdaa1a7a60e4cbfbeb5771..3ce10e05d0d6b8f4efe32eb8f255785e7cd22ccf 100644 (file)
@@ -765,8 +765,6 @@ static int vi_asic_reset(struct amdgpu_device *adev)
        int r;
 
        if (vi_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) {
-               if (!adev->in_suspend)
-                       amdgpu_inc_vram_lost(adev);
                r = amdgpu_dpm_baco_reset(adev);
        } else {
                r = vi_asic_pci_config_reset(adev);
index f7c5cdc10a705b1b78cfb074596649f55d831639..9c83c1303f080b80b5adae907a5763480dbb473e 100644 (file)
@@ -2008,17 +2008,22 @@ void amdgpu_dm_update_connector_after_detect(
                dc_sink_retain(aconnector->dc_sink);
                if (sink->dc_edid.length == 0) {
                        aconnector->edid = NULL;
-                       drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux);
+                       if (aconnector->dc_link->aux_mode) {
+                               drm_dp_cec_unset_edid(
+                                       &aconnector->dm_dp_aux.aux);
+                       }
                } else {
                        aconnector->edid =
-                               (struct edid *) sink->dc_edid.raw_edid;
-
+                               (struct edid *)sink->dc_edid.raw_edid;
 
                        drm_connector_update_edid_property(connector,
-                                       aconnector->edid);
-                       drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux,
-                                           aconnector->edid);
+                                                          aconnector->edid);
+
+                       if (aconnector->dc_link->aux_mode)
+                               drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux,
+                                                   aconnector->edid);
                }
+
                amdgpu_dm_update_freesync_caps(connector, aconnector->edid);
                update_connector_ext_caps(aconnector);
        } else {
@@ -3340,7 +3345,8 @@ fill_plane_dcc_attributes(struct amdgpu_device *adev,
                          const union dc_tiling_info *tiling_info,
                          const uint64_t info,
                          struct dc_plane_dcc_param *dcc,
-                         struct dc_plane_address *address)
+                         struct dc_plane_address *address,
+                         bool force_disable_dcc)
 {
        struct dc *dc = adev->dm.dc;
        struct dc_dcc_surface_param input;
@@ -3352,6 +3358,9 @@ fill_plane_dcc_attributes(struct amdgpu_device *adev,
        memset(&input, 0, sizeof(input));
        memset(&output, 0, sizeof(output));
 
+       if (force_disable_dcc)
+               return 0;
+
        if (!offset)
                return 0;
 
@@ -3401,7 +3410,8 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev,
                             union dc_tiling_info *tiling_info,
                             struct plane_size *plane_size,
                             struct dc_plane_dcc_param *dcc,
-                            struct dc_plane_address *address)
+                            struct dc_plane_address *address,
+                            bool force_disable_dcc)
 {
        const struct drm_framebuffer *fb = &afb->base;
        int ret;
@@ -3507,7 +3517,8 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev,
 
                ret = fill_plane_dcc_attributes(adev, afb, format, rotation,
                                                plane_size, tiling_info,
-                                               tiling_flags, dcc, address);
+                                               tiling_flags, dcc, address,
+                                               force_disable_dcc);
                if (ret)
                        return ret;
        }
@@ -3599,7 +3610,8 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
                            const struct drm_plane_state *plane_state,
                            const uint64_t tiling_flags,
                            struct dc_plane_info *plane_info,
-                           struct dc_plane_address *address)
+                           struct dc_plane_address *address,
+                           bool force_disable_dcc)
 {
        const struct drm_framebuffer *fb = plane_state->fb;
        const struct amdgpu_framebuffer *afb =
@@ -3681,7 +3693,8 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
                                           plane_info->rotation, tiling_flags,
                                           &plane_info->tiling_info,
                                           &plane_info->plane_size,
-                                          &plane_info->dcc, address);
+                                          &plane_info->dcc, address,
+                                          force_disable_dcc);
        if (ret)
                return ret;
 
@@ -3704,6 +3717,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
        struct dc_plane_info plane_info;
        uint64_t tiling_flags;
        int ret;
+       bool force_disable_dcc = false;
 
        ret = fill_dc_scaling_info(plane_state, &scaling_info);
        if (ret)
@@ -3718,9 +3732,11 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
        if (ret)
                return ret;
 
+       force_disable_dcc = adev->asic_type == CHIP_RAVEN && adev->in_suspend;
        ret = fill_dc_plane_info_and_addr(adev, plane_state, tiling_flags,
                                          &plane_info,
-                                         &dc_plane_state->address);
+                                         &dc_plane_state->address,
+                                         force_disable_dcc);
        if (ret)
                return ret;
 
@@ -4664,6 +4680,7 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
                i2c_del_adapter(&aconnector->i2c->base);
                kfree(aconnector->i2c);
        }
+       kfree(aconnector->dm_dp_aux.aux.name);
 
        kfree(connector);
 }
@@ -4723,10 +4740,19 @@ amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector)
 static int
 amdgpu_dm_connector_late_register(struct drm_connector *connector)
 {
-#if defined(CONFIG_DEBUG_FS)
        struct amdgpu_dm_connector *amdgpu_dm_connector =
                to_amdgpu_dm_connector(connector);
+       int r;
 
+       if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
+           (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
+               amdgpu_dm_connector->dm_dp_aux.aux.dev = connector->kdev;
+               r = drm_dp_aux_register(&amdgpu_dm_connector->dm_dp_aux.aux);
+               if (r)
+                       return r;
+       }
+
+#if defined(CONFIG_DEBUG_FS)
        connector_debugfs_init(amdgpu_dm_connector);
 #endif
 
@@ -5332,6 +5358,7 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
        uint64_t tiling_flags;
        uint32_t domain;
        int r;
+       bool force_disable_dcc = false;
 
        dm_plane_state_old = to_dm_plane_state(plane->state);
        dm_plane_state_new = to_dm_plane_state(new_state);
@@ -5390,11 +5417,13 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
                        dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) {
                struct dc_plane_state *plane_state = dm_plane_state_new->dc_state;
 
+               force_disable_dcc = adev->asic_type == CHIP_RAVEN && adev->in_suspend;
                fill_plane_buffer_attributes(
                        adev, afb, plane_state->format, plane_state->rotation,
                        tiling_flags, &plane_state->tiling_info,
                        &plane_state->plane_size, &plane_state->dcc,
-                       &plane_state->address);
+                       &plane_state->address,
+                       force_disable_dcc);
        }
 
        return 0;
@@ -6092,7 +6121,7 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
 
        if (connector_type == DRM_MODE_CONNECTOR_DisplayPort
                || connector_type == DRM_MODE_CONNECTOR_eDP)
-               amdgpu_dm_initialize_dp_connector(dm, aconnector);
+               amdgpu_dm_initialize_dp_connector(dm, aconnector, link->link_index);
 
 out_free:
        if (res) {
@@ -6666,7 +6695,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                fill_dc_plane_info_and_addr(
                        dm->adev, new_plane_state, tiling_flags,
                        &bundle->plane_infos[planes_count],
-                       &bundle->flip_addrs[planes_count].address);
+                       &bundle->flip_addrs[planes_count].address,
+                       false);
+
+               DRM_DEBUG_DRIVER("plane: id=%d dcc_en=%d\n",
+                                new_plane_state->plane->index,
+                                bundle->plane_infos[planes_count].dcc.enable);
 
                bundle->surface_updates[planes_count].plane_info =
                        &bundle->plane_infos[planes_count];
@@ -8086,7 +8120,8 @@ dm_determine_update_type_for_commit(struct amdgpu_display_manager *dm,
                                ret = fill_dc_plane_info_and_addr(
                                        dm->adev, new_plane_state, tiling_flags,
                                        plane_info,
-                                       &flip_addr->address);
+                                       &flip_addr->address,
+                                       false);
                                if (ret)
                                        goto cleanup;
 
index fabbe78d5aefeefc6f933aef4deadc4f486b1157..d2917759b7ab1b70abdea458e5c8d97c16e0a344 100644 (file)
@@ -156,16 +156,16 @@ amdgpu_dm_mst_connector_late_register(struct drm_connector *connector)
                to_amdgpu_dm_connector(connector);
        int r;
 
-       amdgpu_dm_connector->dm_dp_aux.aux.dev = connector->kdev;
-       r = drm_dp_aux_register(&amdgpu_dm_connector->dm_dp_aux.aux);
-       if (r)
+       r = drm_dp_mst_connector_late_register(connector,
+                                              amdgpu_dm_connector->port);
+       if (r < 0)
                return r;
 
 #if defined(CONFIG_DEBUG_FS)
        connector_debugfs_init(amdgpu_dm_connector);
 #endif
 
-       return r;
+       return 0;
 }
 
 static void
@@ -472,9 +472,12 @@ static const struct drm_dp_mst_topology_cbs dm_mst_cbs = {
 };
 
 void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
-                                      struct amdgpu_dm_connector *aconnector)
+                                      struct amdgpu_dm_connector *aconnector,
+                                      int link_index)
 {
-       aconnector->dm_dp_aux.aux.name = "dmdc";
+       aconnector->dm_dp_aux.aux.name =
+               kasprintf(GFP_KERNEL, "AMDGPU DM aux hw bus %d",
+                         link_index);
        aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer;
        aconnector->dm_dp_aux.ddc_service = aconnector->dc_link->ddc;
 
index d6813ce67bbd36844b5af0ac235b7190e8164a44..d2c56579a2cc412a3074ba0a089f29b891492c77 100644 (file)
@@ -32,7 +32,8 @@ struct amdgpu_dm_connector;
 int dm_mst_get_pbn_divider(struct dc_link *link);
 
 void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
-                                      struct amdgpu_dm_connector *aconnector);
+                                      struct amdgpu_dm_connector *aconnector,
+                                      int link_index);
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
 bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
index 8489f1e56892c9b5dce662812887f0dba40e49b8..47431ca6986db7443ec7397678621e8985bdbcbb 100644 (file)
@@ -834,11 +834,10 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
 static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context)
 {
        int i;
-       int count = 0;
-       struct pipe_ctx *pipe;
        PERF_TRACE();
        for (i = 0; i < MAX_PIPES; i++) {
-               pipe = &context->res_ctx.pipe_ctx[i];
+               int count = 0;
+               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
 
                if (!pipe->plane_state)
                        continue;
index 7cbb1efb4f68eb245c33eb7dd525256a6ea0b9ed..27a7d2a58079bad8b20d11dd95bdb7e10e606f89 100644 (file)
@@ -2908,6 +2908,12 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
                                        sizeof(hpd_irq_dpcd_data),
                                        "Status: ");
 
+               for (i = 0; i < MAX_PIPES; i++) {
+                       pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
+                       if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link)
+                               link->dc->hwss.blank_stream(pipe_ctx);
+               }
+
                for (i = 0; i < MAX_PIPES; i++) {
                        pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
                        if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link)
@@ -2927,6 +2933,12 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
                if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
                        dc_link_reallocate_mst_payload(link);
 
+               for (i = 0; i < MAX_PIPES; i++) {
+                       pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
+                       if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link)
+                               link->dc->hwss.unblank_stream(pipe_ctx, &previous_link_settings);
+               }
+
                status = false;
                if (out_link_loss)
                        *out_link_loss = true;
@@ -4227,6 +4239,21 @@ void dp_set_fec_enable(struct dc_link *link, bool enable)
 void dpcd_set_source_specific_data(struct dc_link *link)
 {
        const uint32_t post_oui_delay = 30; // 30ms
+       uint8_t dspc = 0;
+       enum dc_status ret = DC_ERROR_UNEXPECTED;
+
+       ret = core_link_read_dpcd(link, DP_DOWN_STREAM_PORT_COUNT, &dspc,
+                                 sizeof(dspc));
+
+       if (ret != DC_OK) {
+               DC_LOG_ERROR("Error in DP aux read transaction,"
+                            " not writing source specific data\n");
+               return;
+       }
+
+       /* Return if OUI unsupported */
+       if (!(dspc & DP_OUI_SUPPORT))
+               return;
 
        if (!link->dc->vendor_signature.is_valid) {
                struct dpcd_amd_signature amd_signature;
index 6ddbb00ed37a5aa5f0b53a525995bb327bc882b7..4f0e7203dba4f41fd6fa4419b11f99aefc7d97c1 100644 (file)
@@ -231,34 +231,6 @@ struct dc_stream_status *dc_stream_get_status(
        return dc_stream_get_status_from_state(dc->current_state, stream);
 }
 
-static void delay_cursor_until_vupdate(struct pipe_ctx *pipe_ctx, struct dc *dc)
-{
-#if defined(CONFIG_DRM_AMD_DC_DCN)
-       unsigned int vupdate_line;
-       unsigned int lines_to_vupdate, us_to_vupdate, vpos, nvpos;
-       struct dc_stream_state *stream = pipe_ctx->stream;
-       unsigned int us_per_line;
-
-       if (stream->ctx->asic_id.chip_family == FAMILY_RV &&
-                       ASICREV_IS_RAVEN(stream->ctx->asic_id.hw_internal_rev)) {
-
-               vupdate_line = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
-               if (!dc_stream_get_crtc_position(dc, &stream, 1, &vpos, &nvpos))
-                       return;
-
-               if (vpos >= vupdate_line)
-                       return;
-
-               us_per_line = stream->timing.h_total * 10000 / stream->timing.pix_clk_100hz;
-               lines_to_vupdate = vupdate_line - vpos;
-               us_to_vupdate = lines_to_vupdate * us_per_line;
-
-               /* 70 us is a conservative estimate of cursor update time*/
-               if (us_to_vupdate < 70)
-                       udelay(us_to_vupdate);
-       }
-#endif
-}
 
 /**
  * dc_stream_set_cursor_attributes() - Update cursor attributes and set cursor surface address
@@ -298,9 +270,7 @@ bool dc_stream_set_cursor_attributes(
 
                if (!pipe_to_program) {
                        pipe_to_program = pipe_ctx;
-
-                       delay_cursor_until_vupdate(pipe_ctx, dc);
-                       dc->hwss.pipe_control_lock(dc, pipe_to_program, true);
+                       dc->hwss.cursor_lock(dc, pipe_to_program, true);
                }
 
                dc->hwss.set_cursor_attribute(pipe_ctx);
@@ -309,7 +279,7 @@ bool dc_stream_set_cursor_attributes(
        }
 
        if (pipe_to_program)
-               dc->hwss.pipe_control_lock(dc, pipe_to_program, false);
+               dc->hwss.cursor_lock(dc, pipe_to_program, false);
 
        return true;
 }
@@ -349,16 +319,14 @@ bool dc_stream_set_cursor_position(
 
                if (!pipe_to_program) {
                        pipe_to_program = pipe_ctx;
-
-                       delay_cursor_until_vupdate(pipe_ctx, dc);
-                       dc->hwss.pipe_control_lock(dc, pipe_to_program, true);
+                       dc->hwss.cursor_lock(dc, pipe_to_program, true);
                }
 
                dc->hwss.set_cursor_position(pipe_ctx);
        }
 
        if (pipe_to_program)
-               dc->hwss.pipe_control_lock(dc, pipe_to_program, false);
+               dc->hwss.cursor_lock(dc, pipe_to_program, false);
 
        return true;
 }
index c279982947e10ae7cb020485ae850f531a81a1dd..10527593868cc91031c48031c9d5532f4f0d5dd0 100644 (file)
@@ -2757,6 +2757,7 @@ static const struct hw_sequencer_funcs dce110_funcs = {
        .disable_plane = dce110_power_down_fe,
        .pipe_control_lock = dce_pipe_control_lock,
        .interdependent_update_lock = NULL,
+       .cursor_lock = dce_pipe_control_lock,
        .prepare_bandwidth = dce110_prepare_bandwidth,
        .optimize_bandwidth = dce110_optimize_bandwidth,
        .set_drr = set_drr,
index b0357546471b22cf24d40a31480c1a8e09e7f84b..085c1a39b3130a955b4ea27ba8bd5d69bf26603d 100644 (file)
@@ -1625,6 +1625,16 @@ void dcn10_pipe_control_lock(
                hws->funcs.verify_allow_pstate_change_high(dc);
 }
 
+void dcn10_cursor_lock(struct dc *dc, struct pipe_ctx *pipe, bool lock)
+{
+       /* cursor lock is per MPCC tree, so only need to lock one pipe per stream */
+       if (!pipe || pipe->top_pipe)
+               return;
+
+       dc->res_pool->mpc->funcs->cursor_lock(dc->res_pool->mpc,
+                       pipe->stream_res.opp->inst, lock);
+}
+
 static bool wait_for_reset_trigger_to_occur(
        struct dc_context *dc_ctx,
        struct timing_generator *tg)
index 16a50e05ffbfaa13ba23121fe5da7443632241f1..af51424315d5ca9f4c38b0102c22a7a9c20e6c4e 100644 (file)
@@ -49,6 +49,7 @@ void dcn10_pipe_control_lock(
        struct dc *dc,
        struct pipe_ctx *pipe,
        bool lock);
+void dcn10_cursor_lock(struct dc *dc, struct pipe_ctx *pipe, bool lock);
 void dcn10_blank_pixel_data(
                struct dc *dc,
                struct pipe_ctx *pipe_ctx,
index dd02d3983695aba3f6b91c82637edda27a76f1e2..700509bdf5035803d26b0536d53d2545bf3e501c 100644 (file)
@@ -50,6 +50,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
        .disable_audio_stream = dce110_disable_audio_stream,
        .disable_plane = dcn10_disable_plane,
        .pipe_control_lock = dcn10_pipe_control_lock,
+       .cursor_lock = dcn10_cursor_lock,
        .interdependent_update_lock = dcn10_lock_all_pipes,
        .prepare_bandwidth = dcn10_prepare_bandwidth,
        .optimize_bandwidth = dcn10_optimize_bandwidth,
index 04f863499cfb75352ef0a2b6a69fe165f645dabd..3fcd408e9103250933044ff3721de622c7d5247c 100644 (file)
@@ -223,6 +223,9 @@ struct mpcc *mpc1_insert_plane(
        REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, dpp_id);
        REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, tree->opp_id);
 
+       /* Configure VUPDATE lock set for this MPCC to map to the OPP */
+       REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, tree->opp_id);
+
        /* update mpc tree mux setting */
        if (tree->opp_list == insert_above_mpcc) {
                /* insert the toppest mpcc */
@@ -318,6 +321,7 @@ void mpc1_remove_mpcc(
                REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
                REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
                REG_SET(MPCC_OPP_ID[mpcc_id],  0, MPCC_OPP_ID,  0xf);
+               REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf);
 
                /* mark this mpcc as not in use */
                mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id);
@@ -328,6 +332,7 @@ void mpc1_remove_mpcc(
                REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
                REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
                REG_SET(MPCC_OPP_ID[mpcc_id],  0, MPCC_OPP_ID,  0xf);
+               REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf);
        }
 }
 
@@ -361,6 +366,7 @@ void mpc1_mpc_init(struct mpc *mpc)
                REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
                REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
                REG_SET(MPCC_OPP_ID[mpcc_id],  0, MPCC_OPP_ID,  0xf);
+               REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf);
 
                mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id);
        }
@@ -381,6 +387,7 @@ void mpc1_mpc_init_single_inst(struct mpc *mpc, unsigned int mpcc_id)
        REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
        REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
        REG_SET(MPCC_OPP_ID[mpcc_id],  0, MPCC_OPP_ID,  0xf);
+       REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf);
 
        mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id);
 
@@ -453,6 +460,13 @@ void mpc1_read_mpcc_state(
                        MPCC_BUSY, &s->busy);
 }
 
+void mpc1_cursor_lock(struct mpc *mpc, int opp_id, bool lock)
+{
+       struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
+
+       REG_SET(CUR[opp_id], 0, CUR_VUPDATE_LOCK_SET, lock ? 1 : 0);
+}
+
 static const struct mpc_funcs dcn10_mpc_funcs = {
        .read_mpcc_state = mpc1_read_mpcc_state,
        .insert_plane = mpc1_insert_plane,
@@ -464,6 +478,7 @@ static const struct mpc_funcs dcn10_mpc_funcs = {
        .assert_mpcc_idle_before_connect = mpc1_assert_mpcc_idle_before_connect,
        .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw,
        .update_blending = mpc1_update_blending,
+       .cursor_lock = mpc1_cursor_lock,
        .set_denorm = NULL,
        .set_denorm_clamp = NULL,
        .set_output_csc = NULL,
index 962a68e322ee24b5015e3f37ceb9beec600440ab..66a4719c22a0c15a4fe4f2c9696ae16af5fe29d6 100644 (file)
        SRII(MPCC_BG_G_Y, MPCC, inst),\
        SRII(MPCC_BG_R_CR, MPCC, inst),\
        SRII(MPCC_BG_B_CB, MPCC, inst),\
-       SRII(MPCC_BG_B_CB, MPCC, inst),\
-       SRII(MPCC_SM_CONTROL, MPCC, inst)
+       SRII(MPCC_SM_CONTROL, MPCC, inst),\
+       SRII(MPCC_UPDATE_LOCK_SEL, MPCC, inst)
 
 #define MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(inst) \
-       SRII(MUX, MPC_OUT, inst)
+       SRII(MUX, MPC_OUT, inst),\
+       VUPDATE_SRII(CUR, VUPDATE_LOCK_SET, inst)
 
 #define MPC_COMMON_REG_VARIABLE_LIST \
        uint32_t MPCC_TOP_SEL[MAX_MPCC]; \
@@ -55,7 +56,9 @@
        uint32_t MPCC_BG_R_CR[MAX_MPCC]; \
        uint32_t MPCC_BG_B_CB[MAX_MPCC]; \
        uint32_t MPCC_SM_CONTROL[MAX_MPCC]; \
-       uint32_t MUX[MAX_OPP];
+       uint32_t MUX[MAX_OPP]; \
+       uint32_t MPCC_UPDATE_LOCK_SEL[MAX_MPCC]; \
+       uint32_t CUR[MAX_OPP];
 
 #define MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\
        SF(MPCC0_MPCC_TOP_SEL, MPCC_TOP_SEL, mask_sh),\
@@ -78,7 +81,8 @@
        SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FIELD_ALT, mask_sh),\
        SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_FRAME_POL, mask_sh),\
        SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_TOP_POL, mask_sh),\
-       SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh)
+       SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh),\
+       SF(MPCC0_MPCC_UPDATE_LOCK_SEL, MPCC_UPDATE_LOCK_SEL, mask_sh)
 
 #define MPC_REG_FIELD_LIST(type) \
        type MPCC_TOP_SEL;\
        type MPCC_SM_FIELD_ALT;\
        type MPCC_SM_FORCE_NEXT_FRAME_POL;\
        type MPCC_SM_FORCE_NEXT_TOP_POL;\
-       type MPC_OUT_MUX;
+       type MPC_OUT_MUX;\
+       type MPCC_UPDATE_LOCK_SEL;\
+       type CUR_VUPDATE_LOCK_SET;
 
 struct dcn_mpc_registers {
        MPC_COMMON_REG_VARIABLE_LIST
@@ -192,4 +198,6 @@ void mpc1_read_mpcc_state(
                int mpcc_inst,
                struct mpcc_state *s);
 
+void mpc1_cursor_lock(struct mpc *mpc, int opp_id, bool lock);
+
 #endif
index 07265ca7d28cc083eebaaa2381cf3413be78be3e..ba849aa31e6e77346fc6c25f028cf5251929e6a8 100644 (file)
@@ -181,6 +181,14 @@ enum dcn10_clk_src_array_id {
        .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
                                        mm ## block ## id ## _ ## reg_name
 
+#define VUPDATE_SRII(reg_name, block, id)\
+       .reg_name[id] = BASE(mm ## reg_name ## 0 ## _ ## block ## id ## _BASE_IDX) + \
+                                       mm ## reg_name ## 0 ## _ ## block ## id
+
+/* set field/register/bitfield name */
+#define SFRB(field_name, reg_name, bitfield, post_fix)\
+       .field_name = reg_name ## __ ## bitfield ## post_fix
+
 /* NBIO */
 #define NBIO_BASE_INNER(seg) \
        NBIF_BASE__INST0_SEG ## seg
@@ -419,11 +427,13 @@ static const struct dcn_mpc_registers mpc_regs = {
 };
 
 static const struct dcn_mpc_shift mpc_shift = {
-       MPC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT)
+       MPC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT),\
+       SFRB(CUR_VUPDATE_LOCK_SET, CUR0_VUPDATE_LOCK_SET0, CUR0_VUPDATE_LOCK_SET, __SHIFT)
 };
 
 static const struct dcn_mpc_mask mpc_mask = {
-       MPC_COMMON_MASK_SH_LIST_DCN1_0(_MASK),
+       MPC_COMMON_MASK_SH_LIST_DCN1_0(_MASK),\
+       SFRB(CUR_VUPDATE_LOCK_SET, CUR0_VUPDATE_LOCK_SET0, CUR0_VUPDATE_LOCK_SET, _MASK)
 };
 
 #define tg_regs(id)\
index 22f421e82733b04fa91ca859d5d8ab00646e4f4c..a023a4d59f412ed76cb1fc8308c358c8925f8711 100644 (file)
@@ -2294,7 +2294,8 @@ void dcn20_fpga_init_hw(struct dc *dc)
 
        REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
        REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
-       REG_WRITE(REFCLK_CNTL, 0);
+       if (REG(REFCLK_CNTL))
+               REG_WRITE(REFCLK_CNTL, 0);
        //
 
 
index 1e73357eda340acace5542a64e6045d6fb65b791..6a21228893eee21f277557093d7c79bf73b8f1ab 100644 (file)
@@ -52,6 +52,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = {
        .disable_plane = dcn20_disable_plane,
        .pipe_control_lock = dcn20_pipe_control_lock,
        .interdependent_update_lock = dcn10_lock_all_pipes,
+       .cursor_lock = dcn10_cursor_lock,
        .prepare_bandwidth = dcn20_prepare_bandwidth,
        .optimize_bandwidth = dcn20_optimize_bandwidth,
        .update_bandwidth = dcn20_update_bandwidth,
index de9c857ab3e97abf9bd8ca0e53896a391b46e55f..570dfd9a243f732e878fc4b7e3365d9fa3fc28e5 100644 (file)
@@ -545,6 +545,7 @@ const struct mpc_funcs dcn20_mpc_funcs = {
        .mpc_init = mpc1_mpc_init,
        .mpc_init_single_inst = mpc1_mpc_init_single_inst,
        .update_blending = mpc2_update_blending,
+       .cursor_lock = mpc1_cursor_lock,
        .get_mpcc_for_dpp = mpc2_get_mpcc_for_dpp,
        .wait_for_idle = mpc2_assert_idle_mpcc,
        .assert_mpcc_idle_before_connect = mpc2_assert_mpcc_idle_before_connect,
index c78fd5123497b6f14a4b043aba3c01aec9ba4297..496658f420dbdb6cb167059bc3a84f48023b262c 100644 (file)
        SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MAX_G_Y, mask_sh),\
        SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MIN_G_Y, mask_sh),\
        SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MAX_B_CB, mask_sh),\
-       SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MIN_B_CB, mask_sh)
+       SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MIN_B_CB, mask_sh),\
+       SF(CUR_VUPDATE_LOCK_SET0, CUR_VUPDATE_LOCK_SET, mask_sh)
 
 /*
  *     DCN2 MPC_OCSC debug status register:
index 5cdbba0cd87316a7df2611b434f885412e7f4fd4..e4348e3b638985a9d68ef14b7b15a1f9c36696c7 100644 (file)
@@ -508,6 +508,10 @@ enum dcn20_clk_src_array_id {
        .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
                                        mm ## block ## id ## _ ## reg_name
 
+#define VUPDATE_SRII(reg_name, block, id)\
+       .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \
+                                       mm ## reg_name ## _ ## block ## id
+
 /* NBIO */
 #define NBIO_BASE_INNER(seg) \
        NBIO_BASE__INST0_SEG ## seg
@@ -3064,25 +3068,32 @@ validate_out:
        return out;
 }
 
-
-bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
-               bool fast_validate)
+/*
+ * This must be noinline to ensure anything that deals with FP registers
+ * is contained within this call; previously our compiling with hard-float
+ * would result in fp instructions being emitted outside of the boundaries
+ * of the DC_FP_START/END macros, which makes sense as the compiler has no
+ * idea about what is wrapped and what is not
+ *
+ * This is largely just a workaround to avoid breakage introduced with 5.6,
+ * ideally all fp-using code should be moved into its own file, only that
+ * should be compiled with hard-float, and all code exported from there
+ * should be strictly wrapped with DC_FP_START/END
+ */
+static noinline bool dcn20_validate_bandwidth_fp(struct dc *dc,
+               struct dc_state *context, bool fast_validate)
 {
        bool voltage_supported = false;
        bool full_pstate_supported = false;
        bool dummy_pstate_supported = false;
        double p_state_latency_us;
 
-       DC_FP_START();
        p_state_latency_us = context->bw_ctx.dml.soc.dram_clock_change_latency_us;
        context->bw_ctx.dml.soc.disable_dram_clock_change_vactive_support =
                dc->debug.disable_dram_clock_change_vactive_support;
 
        if (fast_validate) {
-               voltage_supported = dcn20_validate_bandwidth_internal(dc, context, true);
-
-               DC_FP_END();
-               return voltage_supported;
+               return dcn20_validate_bandwidth_internal(dc, context, true);
        }
 
        // Best case, we support full UCLK switch latency
@@ -3111,7 +3122,15 @@ bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
 
 restore_dml_state:
        context->bw_ctx.dml.soc.dram_clock_change_latency_us = p_state_latency_us;
+       return voltage_supported;
+}
 
+bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
+               bool fast_validate)
+{
+       bool voltage_supported = false;
+       DC_FP_START();
+       voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate);
        DC_FP_END();
        return voltage_supported;
 }
index b9ff9767e08fd4680f5f8fb512b81dc5fb7936d8..707ce0f28fab3b9fc13576d82aff4efcb137d90e 100644 (file)
@@ -53,6 +53,7 @@ static const struct hw_sequencer_funcs dcn21_funcs = {
        .disable_plane = dcn20_disable_plane,
        .pipe_control_lock = dcn20_pipe_control_lock,
        .interdependent_update_lock = dcn10_lock_all_pipes,
+       .cursor_lock = dcn10_cursor_lock,
        .prepare_bandwidth = dcn20_prepare_bandwidth,
        .optimize_bandwidth = dcn20_optimize_bandwidth,
        .update_bandwidth = dcn20_update_bandwidth,
index b25484aa8222f440f0c0910e7e52139adf10e90d..a721bb401ef0822cfdedbe384e4c08745bc7f3e1 100644 (file)
@@ -284,7 +284,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
        .dram_channel_width_bytes = 4,
        .fabric_datapath_to_dcn_data_return_bytes = 32,
        .dcn_downspread_percent = 0.5,
-       .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,
@@ -340,6 +340,10 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
        .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
                                        mm ## block ## id ## _ ## reg_name
 
+#define VUPDATE_SRII(reg_name, block, id)\
+       .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \
+                                       mm ## reg_name ## _ ## block ## id
+
 /* NBIO */
 #define NBIO_BASE_INNER(seg) \
        NBIF0_BASE__INST0_SEG ## seg
@@ -1374,64 +1378,49 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
 {
        struct dcn21_resource_pool *pool = TO_DCN21_RES_POOL(dc->res_pool);
        struct clk_limit_table *clk_table = &bw_params->clk_table;
-       unsigned int i, j, k;
-       int closest_clk_lvl;
+       struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES];
+       unsigned int i, j, closest_clk_lvl;
 
        // Default clock levels are used for diags, which may lead to overclocking.
-       if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) && !IS_DIAG_DC(dc->ctx->dce_environment)) {
+       if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
                dcn2_1_ip.max_num_otg = pool->base.res_cap->num_timing_generator;
                dcn2_1_ip.max_num_dpp = pool->base.pipe_count;
                dcn2_1_soc.num_chans = bw_params->num_channels;
 
-               /* Vmin: leave lowest DCN clocks, override with dcfclk, fclk, memclk from fuse */
-               dcn2_1_soc.clock_limits[0].state = 0;
-               dcn2_1_soc.clock_limits[0].dcfclk_mhz = clk_table->entries[0].dcfclk_mhz;
-               dcn2_1_soc.clock_limits[0].fabricclk_mhz = clk_table->entries[0].fclk_mhz;
-               dcn2_1_soc.clock_limits[0].socclk_mhz = clk_table->entries[0].socclk_mhz;
-               dcn2_1_soc.clock_limits[0].dram_speed_mts = clk_table->entries[0].memclk_mhz * 2;
-
-               /*
-                * Other levels: find closest DCN clocks that fit the given clock limit using dcfclk
-                * as indicator
-                */
-
-               closest_clk_lvl = -1;
-               /* index currently being filled */
-               k = 1;
-               for (i = 1; i < clk_table->num_entries; i++) {
-                       /* loop backwards, skip duplicate state*/
-                       for (j = dcn2_1_soc.num_states - 1; j >= k; j--) {
+               ASSERT(clk_table->num_entries);
+               for (i = 0; i < clk_table->num_entries; i++) {
+                       /* loop backwards*/
+                       for (closest_clk_lvl = 0, j = dcn2_1_soc.num_states - 1; j >= 0; j--) {
                                if ((unsigned int) dcn2_1_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) {
                                        closest_clk_lvl = j;
                                        break;
                                }
                        }
 
-                       /* if found a lvl that fits, use the DCN clks from it, if not, go to next clk limit*/
-                       if (closest_clk_lvl != -1) {
-                               dcn2_1_soc.clock_limits[k].state = i;
-                               dcn2_1_soc.clock_limits[k].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
-                               dcn2_1_soc.clock_limits[k].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
-                               dcn2_1_soc.clock_limits[k].socclk_mhz = clk_table->entries[i].socclk_mhz;
-                               dcn2_1_soc.clock_limits[k].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2;
-
-                               dcn2_1_soc.clock_limits[k].dispclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
-                               dcn2_1_soc.clock_limits[k].dppclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
-                               dcn2_1_soc.clock_limits[k].dram_bw_per_chan_gbps = dcn2_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
-                               dcn2_1_soc.clock_limits[k].dscclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
-                               dcn2_1_soc.clock_limits[k].dtbclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
-                               dcn2_1_soc.clock_limits[k].phyclk_d18_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
-                               dcn2_1_soc.clock_limits[k].phyclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
-                               k++;
-                       }
+                       clock_limits[i].state = i;
+                       clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
+                       clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
+                       clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
+                       clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2;
+
+                       clock_limits[i].dispclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
+                       clock_limits[i].dppclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
+                       clock_limits[i].dram_bw_per_chan_gbps = dcn2_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
+                       clock_limits[i].dscclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
+                       clock_limits[i].dtbclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
+                       clock_limits[i].phyclk_d18_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
+                       clock_limits[i].phyclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
+               }
+               for (i = 0; i < clk_table->num_entries; i++)
+                       dcn2_1_soc.clock_limits[i] = clock_limits[i];
+               if (clk_table->num_entries) {
+                       dcn2_1_soc.num_states = clk_table->num_entries;
+                       /* duplicate last level */
+                       dcn2_1_soc.clock_limits[dcn2_1_soc.num_states] = dcn2_1_soc.clock_limits[dcn2_1_soc.num_states - 1];
+                       dcn2_1_soc.clock_limits[dcn2_1_soc.num_states].state = dcn2_1_soc.num_states;
                }
-               dcn2_1_soc.num_states = k;
        }
 
-       /* duplicate last level */
-       dcn2_1_soc.clock_limits[dcn2_1_soc.num_states] = dcn2_1_soc.clock_limits[dcn2_1_soc.num_states - 1];
-       dcn2_1_soc.clock_limits[dcn2_1_soc.num_states].state = dcn2_1_soc.num_states;
-
        dml_init_instance(&dc->dml, &dcn2_1_soc, &dcn2_1_ip, DML_PROJECT_DCN21);
 }
 
index a38baa73d4841af90d8ea5381ba4fc9ef7d22861..b8ec08e3b7a36da30e6ae22db50153bb27a3c4b7 100644 (file)
@@ -1200,7 +1200,7 @@ static void dml_rq_dlg_get_dlg_params(
        min_hratio_fact_l = 1.0;
        min_hratio_fact_c = 1.0;
 
-       if (htaps_l <= 1)
+       if (hratio_l <= 1)
                min_hratio_fact_l = 2.0;
        else if (htaps_l <= 6) {
                if ((hratio_l * 2.0) > 4.0)
@@ -1216,7 +1216,7 @@ static void dml_rq_dlg_get_dlg_params(
 
        hscale_pixel_rate_l = min_hratio_fact_l * dppclk_freq_in_mhz;
 
-       if (htaps_c <= 1)
+       if (hratio_c <= 1)
                min_hratio_fact_c = 2.0;
        else if (htaps_c <= 6) {
                if ((hratio_c * 2.0) > 4.0)
@@ -1522,8 +1522,8 @@ static void dml_rq_dlg_get_dlg_params(
 
        disp_dlg_regs->refcyc_per_vm_group_vblank   = get_refcyc_per_vm_group_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz;
        disp_dlg_regs->refcyc_per_vm_group_flip     = get_refcyc_per_vm_group_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz;
-       disp_dlg_regs->refcyc_per_vm_req_vblank     = get_refcyc_per_vm_req_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz;
-       disp_dlg_regs->refcyc_per_vm_req_flip       = get_refcyc_per_vm_req_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz;
+       disp_dlg_regs->refcyc_per_vm_req_vblank     = get_refcyc_per_vm_req_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz * dml_pow(2, 10);
+       disp_dlg_regs->refcyc_per_vm_req_flip       = get_refcyc_per_vm_req_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz * dml_pow(2, 10);
 
        // Clamp to max for now
        if (disp_dlg_regs->refcyc_per_vm_group_vblank >= (unsigned int)dml_pow(2, 23))
index 094afc4c817310332dd78521ee1ebe56e79094b1..50ee8aa7ec3b3317ababfea194699af9d9aaef48 100644 (file)
@@ -210,6 +210,22 @@ struct mpc_funcs {
                struct mpcc_blnd_cfg *blnd_cfg,
                int mpcc_id);
 
+       /*
+        * Lock cursor updates for the specified OPP.
+        * OPP defines the set of MPCC that are locked together for cursor.
+        *
+        * Parameters:
+        * [in]         mpc             - MPC context.
+        * [in]     opp_id      - The OPP to lock cursor updates on
+        * [in]         lock    - lock/unlock the OPP
+        *
+        * Return:  void
+        */
+       void (*cursor_lock)(
+                       struct mpc *mpc,
+                       int opp_id,
+                       bool lock);
+
        struct mpcc* (*get_mpcc_for_dpp)(
                        struct mpc_tree *tree,
                        int dpp_id);
index d4c1fb242c6378a0b8439a7075eba0f288a89fbc..e57467d99d66d956e8f2b27439c9c3573eac2d29 100644 (file)
@@ -86,6 +86,7 @@ struct hw_sequencer_funcs {
                        struct dc_state *context, bool lock);
        void (*set_flip_control_gsl)(struct pipe_ctx *pipe_ctx,
                        bool flip_immediate);
+       void (*cursor_lock)(struct dc *dc, struct pipe_ctx *pipe, bool lock);
 
        /* Timing Related */
        void (*get_position)(struct pipe_ctx **pipe_ctx, int num_pipes,
index c34eba19860a32a9952f26ab094dd7266552c953..6d7bca562eec00cb2093edbf6d09e833a6382206 100644 (file)
 #define ASSERT(expr) ASSERT_CRITICAL(expr)
 
 #else
-#define ASSERT(expr) WARN_ON(!(expr))
+#define ASSERT(expr) WARN_ON_ONCE(!(expr))
 #endif
 
 #define BREAK_TO_DEBUGGER() ASSERT(0)
index 2a12614a12c224d9c7f9c3d532d91a20f8024e4e..e4e5a53b2b4eafe8f655ae5f13d668ac1f55f717 100644 (file)
@@ -1435,7 +1435,8 @@ static int pp_get_asic_baco_capability(void *handle, bool *cap)
        if (!hwmgr)
                return -EINVAL;
 
-       if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_asic_baco_capability)
+       if (!(hwmgr->not_vf && amdgpu_dpm) ||
+               !hwmgr->hwmgr_func->get_asic_baco_capability)
                return 0;
 
        mutex_lock(&hwmgr->smu_lock);
@@ -1452,8 +1453,7 @@ static int pp_get_asic_baco_state(void *handle, int *state)
        if (!hwmgr)
                return -EINVAL;
 
-       if (!(hwmgr->not_vf && amdgpu_dpm) ||
-               !hwmgr->hwmgr_func->get_asic_baco_state)
+       if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_asic_baco_state)
                return 0;
 
        mutex_lock(&hwmgr->smu_lock);
@@ -1470,7 +1470,8 @@ static int pp_set_asic_baco_state(void *handle, int state)
        if (!hwmgr)
                return -EINVAL;
 
-       if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_asic_baco_state)
+       if (!(hwmgr->not_vf && amdgpu_dpm) ||
+               !hwmgr->hwmgr_func->set_asic_baco_state)
                return 0;
 
        mutex_lock(&hwmgr->smu_lock);
index 77c14671866c07f159729b82e31ec1779b7d4f45..719597c5d27d98e070b202fffd31d4413b994fa9 100644 (file)
@@ -984,6 +984,32 @@ static int init_thermal_controller(
                        struct pp_hwmgr *hwmgr,
                        const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
 {
+       hwmgr->thermal_controller.ucType =
+                       powerplay_table->sThermalController.ucType;
+       hwmgr->thermal_controller.ucI2cLine =
+                       powerplay_table->sThermalController.ucI2cLine;
+       hwmgr->thermal_controller.ucI2cAddress =
+                       powerplay_table->sThermalController.ucI2cAddress;
+
+       hwmgr->thermal_controller.fanInfo.bNoFan =
+               (0 != (powerplay_table->sThermalController.ucFanParameters &
+                       ATOM_PP_FANPARAMETERS_NOFAN));
+
+       hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
+               powerplay_table->sThermalController.ucFanParameters &
+               ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
+
+       hwmgr->thermal_controller.fanInfo.ulMinRPM
+               = powerplay_table->sThermalController.ucFanMinRPM * 100UL;
+       hwmgr->thermal_controller.fanInfo.ulMaxRPM
+               = powerplay_table->sThermalController.ucFanMaxRPM * 100UL;
+
+       set_hw_cap(hwmgr,
+                  ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
+                  PHM_PlatformCaps_ThermalController);
+
+       hwmgr->thermal_controller.use_hw_fan_control = 1;
+
        return 0;
 }
 
index 7740488999df78b06326715cc24d580d35286721..4795eb66b2b2355fa6deaaddd456f7ade6f8f75f 100644 (file)
@@ -3804,9 +3804,12 @@ static int smu7_trim_single_dpm_states(struct pp_hwmgr *hwmgr,
 {
        uint32_t i;
 
+       /* force the trim if mclk_switching is disabled to prevent flicker */
+       bool force_trim = (low_limit == high_limit);
        for (i = 0; i < dpm_table->count; i++) {
        /*skip the trim if od is enabled*/
-               if (!hwmgr->od_enabled && (dpm_table->dpm_levels[i].value < low_limit
+               if ((!hwmgr->od_enabled || force_trim)
+                       && (dpm_table->dpm_levels[i].value < low_limit
                        || dpm_table->dpm_levels[i].value > high_limit))
                        dpm_table->dpm_levels[i].enabled = false;
                else
index ff73a735b8882a4844ac87dda3ca75588e6fe453..b0ed1b3fe79a351a82ab984aac7ccee57aff89fd 100644 (file)
@@ -895,12 +895,17 @@ static int renoir_read_sensor(struct smu_context *smu,
 
 static bool renoir_is_dpm_running(struct smu_context *smu)
 {
+       struct amdgpu_device *adev = smu->adev;
+
        /*
         * Util now, the pmfw hasn't exported the interface of SMU
         * feature mask to APU SKU so just force on all the feature
         * at early initial stage.
         */
-       return true;
+       if (adev->in_suspend)
+               return false;
+       else
+               return true;
 
 }
 
index 541c932a60051bb9c00215ca22e7924892c1d355..655ba4fb05dcdf330e53c3548e54681a18a58208 100644 (file)
@@ -1718,6 +1718,12 @@ int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state)
                if (ret)
                        goto out;
 
+               if (ras && ras->supported) {
+                       ret = smu_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL);
+                       if (ret)
+                               goto out;
+               }
+
                /* clear vbios scratch 6 and 7 for coming asic reinit */
                WREG32(adev->bios_scratch_reg_offset + 6, 0);
                WREG32(adev->bios_scratch_reg_offset + 7, 0);
index 2bc6e4f85171697a9fb7ff29831eb5316bba05af..9af39ec958db5eade1a8bdb786381753b6fd7d3b 100644 (file)
@@ -485,6 +485,9 @@ static int anx6345_get_modes(struct drm_connector *connector)
 
        num_modes += drm_add_edid_modes(connector, anx6345->edid);
 
+       /* Driver currently supports only 6bpc */
+       connector->display_info.bpc = 6;
+
 unlock:
        if (power_off)
                anx6345_poweroff(anx6345);
index 70c4b7afed12494951da8fdaa0132733e87ad8bf..9d89ebf3a749d12cd3543971502e357462a55a47 100644 (file)
@@ -3442,8 +3442,12 @@ static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
        drm_dp_queue_down_tx(mgr, txmsg);
 
        ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
-       if (ret > 0 && txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK)
-               ret = -EIO;
+       if (ret > 0) {
+               if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK)
+                       ret = -EIO;
+               else
+                       ret = size;
+       }
 
        kfree(txmsg);
 fail_put:
@@ -4295,6 +4299,7 @@ int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,
        if (pos->vcpi) {
                drm_dp_mst_put_port_malloc(port);
                pos->vcpi = 0;
+               pos->pbn = 0;
        }
 
        return 0;
index 116451101426d40e7acf0c8b002ed4bba823378e..4ede08a84e37238ff893e463710410d13a1b0d12 100644 (file)
@@ -5111,7 +5111,7 @@ static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *d
        struct drm_display_mode *mode;
        unsigned pixel_clock = (timings->pixel_clock[0] |
                                (timings->pixel_clock[1] << 8) |
-                               (timings->pixel_clock[2] << 16));
+                               (timings->pixel_clock[2] << 16)) + 1;
        unsigned hactive = (timings->hactive[0] | timings->hactive[1] << 8) + 1;
        unsigned hblank = (timings->hblank[0] | timings->hblank[1] << 8) + 1;
        unsigned hsync = (timings->hsync[0] | (timings->hsync[1] & 0x7f) << 8) + 1;
index 7f386adcf87256ed70c73a43eae3908188dff5af..910108ccaae1dbc8d8b0aeee6249098ff12665e9 100644 (file)
@@ -241,8 +241,12 @@ static int drm_hdcp_request_srm(struct drm_device *drm_dev,
 
        ret = request_firmware_direct(&fw, (const char *)fw_name,
                                      drm_dev->dev);
-       if (ret < 0)
+       if (ret < 0) {
+               *revoked_ksv_cnt = 0;
+               *revoked_ksv_list = NULL;
+               ret = 0;
                goto exit;
+       }
 
        if (fw->size && fw->data)
                ret = drm_hdcp_srm_update(fw->data, fw->size, revoked_ksv_list,
@@ -287,6 +291,8 @@ int drm_hdcp_check_ksvs_revoked(struct drm_device *drm_dev, u8 *ksvs,
 
        ret = drm_hdcp_request_srm(drm_dev, &revoked_ksv_list,
                                   &revoked_ksv_cnt);
+       if (ret)
+               return ret;
 
        /* revoked_ksv_cnt will be zero when above function failed */
        for (i = 0; i < revoked_ksv_cnt; i++)
index 2c617c98db3a4b12bcf96721f6032b76d9bc3f6f..52db7852827bfddc8c2b732fd00c8e5aedb09ee8 100644 (file)
@@ -3141,9 +3141,6 @@ static void hsw_ddi_pre_enable_dp(struct intel_encoder *encoder,
        intel_dp_set_link_params(intel_dp, crtc_state->port_clock,
                                 crtc_state->lane_count, is_mst);
 
-       intel_dp->regs.dp_tp_ctl = DP_TP_CTL(port);
-       intel_dp->regs.dp_tp_status = DP_TP_STATUS(port);
-
        intel_edp_panel_on(intel_dp);
 
        intel_ddi_clk_select(encoder, crtc_state);
@@ -3848,12 +3845,18 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc);
        enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
+       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
        u32 temp, flags = 0;
 
        /* XXX: DSI transcoder paranoia */
        if (drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder)))
                return;
 
+       if (INTEL_GEN(dev_priv) >= 12) {
+               intel_dp->regs.dp_tp_ctl = TGL_DP_TP_CTL(cpu_transcoder);
+               intel_dp->regs.dp_tp_status = TGL_DP_TP_STATUS(cpu_transcoder);
+       }
+
        intel_dsc_get_config(encoder, pipe_config);
 
        temp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
@@ -4173,6 +4176,7 @@ static const struct drm_encoder_funcs intel_ddi_funcs = {
 static struct intel_connector *
 intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port)
 {
+       struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
        struct intel_connector *connector;
        enum port port = intel_dig_port->base.port;
 
@@ -4183,6 +4187,10 @@ intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port)
        intel_dig_port->dp.output_reg = DDI_BUF_CTL(port);
        intel_dig_port->dp.prepare_link_retrain =
                intel_ddi_prepare_link_retrain;
+       if (INTEL_GEN(dev_priv) < 12) {
+               intel_dig_port->dp.regs.dp_tp_ctl = DP_TP_CTL(port);
+               intel_dig_port->dp.regs.dp_tp_status = DP_TP_STATUS(port);
+       }
 
        if (!intel_dp_init_connector(intel_dig_port, connector)) {
                kfree(connector);
index 246e406bb385edbcf0d44d1c970c037136eff2b5..84ecf8e58523d4e9a60bcd03c834e1d39b968e54 100644 (file)
@@ -4140,7 +4140,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
        {
                .name = "AUX D TBT1",
                .domains = TGL_AUX_D_TBT1_IO_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_tc_phy_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
                        .hsw.regs = &icl_aux_power_well_regs,
@@ -4151,7 +4151,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
        {
                .name = "AUX E TBT2",
                .domains = TGL_AUX_E_TBT2_IO_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_tc_phy_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
                        .hsw.regs = &icl_aux_power_well_regs,
@@ -4162,7 +4162,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
        {
                .name = "AUX F TBT3",
                .domains = TGL_AUX_F_TBT3_IO_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_tc_phy_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
                        .hsw.regs = &icl_aux_power_well_regs,
@@ -4173,7 +4173,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
        {
                .name = "AUX G TBT4",
                .domains = TGL_AUX_G_TBT4_IO_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_tc_phy_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
                        .hsw.regs = &icl_aux_power_well_regs,
@@ -4184,7 +4184,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
        {
                .name = "AUX H TBT5",
                .domains = TGL_AUX_H_TBT5_IO_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_tc_phy_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
                        .hsw.regs = &icl_aux_power_well_regs,
@@ -4195,7 +4195,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
        {
                .name = "AUX I TBT6",
                .domains = TGL_AUX_I_TBT6_IO_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_tc_phy_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
                        .hsw.regs = &icl_aux_power_well_regs,
index 804b1d966f66424ebd5fa5601bbb357feec1c0cb..a2fafd4499f2a67d1b2ae2dfd2748d3f38013268 100644 (file)
@@ -2517,9 +2517,6 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
                                 intel_crtc_has_type(pipe_config,
                                                     INTEL_OUTPUT_DP_MST));
 
-       intel_dp->regs.dp_tp_ctl = DP_TP_CTL(port);
-       intel_dp->regs.dp_tp_status = DP_TP_STATUS(port);
-
        /*
         * There are four kinds of DP registers:
         *
@@ -7836,6 +7833,8 @@ bool intel_dp_init(struct drm_i915_private *dev_priv,
 
        intel_dig_port->dp.output_reg = output_reg;
        intel_dig_port->max_lanes = 4;
+       intel_dig_port->dp.regs.dp_tp_ctl = DP_TP_CTL(port);
+       intel_dig_port->dp.regs.dp_tp_status = DP_TP_STATUS(port);
 
        intel_encoder->type = INTEL_OUTPUT_DP;
        intel_encoder->power_domain = intel_port_to_power_domain(port);
index 3e706bb850a8714a91ca8af57ec56a9aeff31190..dbfa6895795b2e067a08ccae65b355bceab21422 100644 (file)
@@ -342,6 +342,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector)
         */
        if (dev_priv->vbt.backlight.type !=
            INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE &&
+           i915_modparams.enable_dpcd_backlight != 1 &&
            !drm_dp_has_quirk(&intel_dp->desc, intel_dp->edid_quirks,
                              DP_QUIRK_FORCE_DPCD_BACKLIGHT)) {
                DRM_DEV_INFO(dev->dev,
index 2e5d835a9eaa866e0a6c8c94b35ff00cbcf04db7..c125ca9ab9b3a93fa4c27da86f29140e4618e9e2 100644 (file)
@@ -485,8 +485,7 @@ static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv,
        if (!ret)
                goto err_llb;
        else if (ret > 1) {
-               DRM_INFO("Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n");
-
+               DRM_INFO_ONCE("Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n");
        }
 
        fbc->threshold = ret;
index 39930232b25323acdd80fa0136ee585da09c80d2..821411b93dacc4a2f36af15667850f735d5426dd 100644 (file)
@@ -1536,7 +1536,8 @@ bool intel_hdmi_hdcp_check_link(struct intel_digital_port *intel_dig_port)
        intel_de_write(i915, HDCP_RPRIME(i915, cpu_transcoder, port), ri.reg);
 
        /* Wait for Ri prime match */
-       if (wait_for(intel_de_read(i915, HDCP_STATUS(i915, cpu_transcoder, port)) &
+       if (wait_for((intel_de_read(i915, HDCP_STATUS(i915, cpu_transcoder, port)) &
+                     (HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC)) ==
                     (HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC), 1)) {
                DRM_ERROR("Ri' mismatch detected, link check failed (%x)\n",
                          intel_de_read(i915, HDCP_STATUS(i915, cpu_transcoder, port)));
index deda351719db801551ad000cbe164c0774ae834b..33d8861411382e2b38ebdb30e1c2d6fe0bd0ebce 100644 (file)
@@ -2817,19 +2817,25 @@ static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
        }
 }
 
-static bool gen12_plane_supports_mc_ccs(enum plane_id plane_id)
+static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv,
+                                       enum plane_id plane_id)
 {
+       /* Wa_14010477008:tgl[a0..c0] */
+       if (IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_C0))
+               return false;
+
        return plane_id < PLANE_SPRITE4;
 }
 
 static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
                                             u32 format, u64 modifier)
 {
+       struct drm_i915_private *dev_priv = to_i915(_plane->dev);
        struct intel_plane *plane = to_intel_plane(_plane);
 
        switch (modifier) {
        case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
-               if (!gen12_plane_supports_mc_ccs(plane->id))
+               if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id))
                        return false;
                /* fall through */
        case DRM_FORMAT_MOD_LINEAR:
@@ -2998,9 +3004,10 @@ static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
        }
 }
 
-static const u64 *gen12_get_plane_modifiers(enum plane_id plane_id)
+static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv,
+                                           enum plane_id plane_id)
 {
-       if (gen12_plane_supports_mc_ccs(plane_id))
+       if (gen12_plane_supports_mc_ccs(dev_priv, plane_id))
                return gen12_plane_format_modifiers_mc_ccs;
        else
                return gen12_plane_format_modifiers_rc_ccs;
@@ -3070,7 +3077,7 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
 
        plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
        if (INTEL_GEN(dev_priv) >= 12) {
-               modifiers = gen12_get_plane_modifiers(plane_id);
+               modifiers = gen12_get_plane_modifiers(dev_priv, plane_id);
                plane_funcs = &gen12_plane_funcs;
        } else {
                if (plane->has_ccs)
index 0cc40e77bbd2fcb2bb85a01768993a57a08e9a88..4f96c8788a2ec1b396b7b11a35dc377e787260ec 100644 (file)
@@ -368,7 +368,6 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
        struct drm_i915_private *i915 = to_i915(obj->base.dev);
        struct i915_vma *vma;
 
-       GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
        if (!atomic_read(&obj->bind_count))
                return;
 
@@ -400,12 +399,8 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
 void
 i915_gem_object_unpin_from_display_plane(struct i915_vma *vma)
 {
-       struct drm_i915_gem_object *obj = vma->obj;
-
-       assert_object_held(obj);
-
        /* Bump the LRU to try and avoid premature eviction whilst flipping  */
-       i915_gem_object_bump_inactive_ggtt(obj);
+       i915_gem_object_bump_inactive_ggtt(vma->obj);
 
        i915_vma_unpin(vma);
 }
index 37f77aee121212cac2e155fe13f161c74ebbeee6..0158e49bf9bb73cb903c68d9e2ff5e87561bc43d 100644 (file)
@@ -182,21 +182,35 @@ i915_gem_object_fence_prepare(struct drm_i915_gem_object *obj,
                              int tiling_mode, unsigned int stride)
 {
        struct i915_ggtt *ggtt = &to_i915(obj->base.dev)->ggtt;
-       struct i915_vma *vma;
+       struct i915_vma *vma, *vn;
+       LIST_HEAD(unbind);
        int ret = 0;
 
        if (tiling_mode == I915_TILING_NONE)
                return 0;
 
        mutex_lock(&ggtt->vm.mutex);
+
+       spin_lock(&obj->vma.lock);
        for_each_ggtt_vma(vma, obj) {
+               GEM_BUG_ON(vma->vm != &ggtt->vm);
+
                if (i915_vma_fence_prepare(vma, tiling_mode, stride))
                        continue;
 
+               list_move(&vma->vm_link, &unbind);
+       }
+       spin_unlock(&obj->vma.lock);
+
+       list_for_each_entry_safe(vma, vn, &unbind, vm_link) {
                ret = __i915_vma_unbind(vma);
-               if (ret)
+               if (ret) {
+                       /* Restore the remaining vma on an error */
+                       list_splice(&unbind, &ggtt->vm.bound_list);
                        break;
+               }
        }
+
        mutex_unlock(&ggtt->vm.mutex);
 
        return ret;
@@ -268,6 +282,7 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
        }
        mutex_unlock(&obj->mm.lock);
 
+       spin_lock(&obj->vma.lock);
        for_each_ggtt_vma(vma, obj) {
                vma->fence_size =
                        i915_gem_fence_size(i915, vma->size, tiling, stride);
@@ -278,6 +293,7 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
                if (vma->fence)
                        vma->fence->dirty = true;
        }
+       spin_unlock(&obj->vma.lock);
 
        obj->tiling_and_stride = tiling | stride;
        i915_gem_object_unlock(obj);
index 2d0fd50c53124428f8fc19fb4e27f9e55987687e..d4f94ca9ae0dd5fe6258b6cc354f636650f4b8b2 100644 (file)
@@ -1477,8 +1477,10 @@ static int igt_ppgtt_pin_update(void *arg)
                unsigned int page_size = BIT(first);
 
                obj = i915_gem_object_create_internal(dev_priv, page_size);
-               if (IS_ERR(obj))
-                       return PTR_ERR(obj);
+               if (IS_ERR(obj)) {
+                       err = PTR_ERR(obj);
+                       goto out_vm;
+               }
 
                vma = i915_vma_instance(obj, vm, NULL);
                if (IS_ERR(vma)) {
@@ -1531,8 +1533,10 @@ static int igt_ppgtt_pin_update(void *arg)
        }
 
        obj = i915_gem_object_create_internal(dev_priv, PAGE_SIZE);
-       if (IS_ERR(obj))
-               return PTR_ERR(obj);
+       if (IS_ERR(obj)) {
+               err = PTR_ERR(obj);
+               goto out_vm;
+       }
 
        vma = i915_vma_instance(obj, vm, NULL);
        if (IS_ERR(vma)) {
index 07cb83a0d0171a48fbedee19944bb0064b142416..ca0d4f4f3615b6d7ab78392bc3e002818938d63f 100644 (file)
@@ -69,7 +69,13 @@ struct intel_context {
 #define CONTEXT_NOPREEMPT              7
 
        u32 *lrc_reg_state;
-       u64 lrc_desc;
+       union {
+               struct {
+                       u32 lrca;
+                       u32 ccid;
+               };
+               u64 desc;
+       } lrc;
        u32 tag; /* cookie passed to HW to track this context on submission */
 
        /* Time on GPU as tracked by the hw. */
index b469de0dd9b656c25ae3e76dcf086836fd1f624c..a1aa0d3e8be1d5c51badcc555dbe94c92aa78953 100644 (file)
@@ -333,13 +333,4 @@ intel_engine_has_preempt_reset(const struct intel_engine_cs *engine)
        return intel_engine_has_preemption(engine);
 }
 
-static inline bool
-intel_engine_has_timeslices(const struct intel_engine_cs *engine)
-{
-       if (!IS_ACTIVE(CONFIG_DRM_I915_TIMESLICE_DURATION))
-               return false;
-
-       return intel_engine_has_semaphores(engine);
-}
-
 #endif /* _INTEL_RINGBUFFER_H_ */
index 3aa8a652c16dbdd092dba754fad8df057d82ba5b..883a9b7fe88d5a6a0b4398d3a3793b727b015343 100644 (file)
@@ -1295,6 +1295,12 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine,
 
        if (engine->id == RENDER_CLASS && IS_GEN_RANGE(dev_priv, 4, 7))
                drm_printf(m, "\tCCID: 0x%08x\n", ENGINE_READ(engine, CCID));
+       if (HAS_EXECLISTS(dev_priv)) {
+               drm_printf(m, "\tEL_STAT_HI: 0x%08x\n",
+                          ENGINE_READ(engine, RING_EXECLIST_STATUS_HI));
+               drm_printf(m, "\tEL_STAT_LO: 0x%08x\n",
+                          ENGINE_READ(engine, RING_EXECLIST_STATUS_LO));
+       }
        drm_printf(m, "\tRING_START: 0x%08x\n",
                   ENGINE_READ(engine, RING_START));
        drm_printf(m, "\tRING_HEAD:  0x%08x\n",
index 80cdde7128420c21e2b5cbfb9f363d421ac997d5..0be674ae1cf63ff4a2adf665696dca8f8b9b74a1 100644 (file)
@@ -156,6 +156,20 @@ struct intel_engine_execlists {
         */
        struct i915_priolist default_priolist;
 
+       /**
+        * @ccid: identifier for contexts submitted to this engine
+        */
+       u32 ccid;
+
+       /**
+        * @yield: CCID at the time of the last semaphore-wait interrupt.
+        *
+        * Instead of leaving a semaphore busy-spinning on an engine, we would
+        * like to switch to another ready context, i.e. yielding the semaphore
+        * timeslice.
+        */
+       u32 yield;
+
        /**
         * @error_interrupt: CS Master EIR
         *
@@ -295,8 +309,7 @@ struct intel_engine_cs {
        u32 context_size;
        u32 mmio_base;
 
-       unsigned int context_tag;
-#define NUM_CONTEXT_TAG roundup_pow_of_two(2 * EXECLIST_MAX_PORTS)
+       unsigned long context_tag;
 
        struct rb_node uabi_node;
 
@@ -483,10 +496,11 @@ struct intel_engine_cs {
 #define I915_ENGINE_SUPPORTS_STATS   BIT(1)
 #define I915_ENGINE_HAS_PREEMPTION   BIT(2)
 #define I915_ENGINE_HAS_SEMAPHORES   BIT(3)
-#define I915_ENGINE_NEEDS_BREADCRUMB_TASKLET BIT(4)
-#define I915_ENGINE_IS_VIRTUAL       BIT(5)
-#define I915_ENGINE_HAS_RELATIVE_MMIO BIT(6)
-#define I915_ENGINE_REQUIRES_CMD_PARSER BIT(7)
+#define I915_ENGINE_HAS_TIMESLICES   BIT(4)
+#define I915_ENGINE_NEEDS_BREADCRUMB_TASKLET BIT(5)
+#define I915_ENGINE_IS_VIRTUAL       BIT(6)
+#define I915_ENGINE_HAS_RELATIVE_MMIO BIT(7)
+#define I915_ENGINE_REQUIRES_CMD_PARSER BIT(8)
        unsigned int flags;
 
        /*
@@ -584,6 +598,15 @@ intel_engine_has_semaphores(const struct intel_engine_cs *engine)
        return engine->flags & I915_ENGINE_HAS_SEMAPHORES;
 }
 
+static inline bool
+intel_engine_has_timeslices(const struct intel_engine_cs *engine)
+{
+       if (!IS_ACTIVE(CONFIG_DRM_I915_TIMESLICE_DURATION))
+               return false;
+
+       return engine->flags & I915_ENGINE_HAS_TIMESLICES;
+}
+
 static inline bool
 intel_engine_needs_breadcrumb_tasklet(const struct intel_engine_cs *engine)
 {
index f0e7fd95165a7d15058237e578cbb253c76c27d9..0cc7dd54f4f963ae6dc29698c3839a82e1667a0d 100644 (file)
@@ -39,6 +39,15 @@ cs_irq_handler(struct intel_engine_cs *engine, u32 iir)
                }
        }
 
+       if (iir & GT_WAIT_SEMAPHORE_INTERRUPT) {
+               WRITE_ONCE(engine->execlists.yield,
+                          ENGINE_READ_FW(engine, RING_EXECLIST_STATUS_HI));
+               ENGINE_TRACE(engine, "semaphore yield: %08x\n",
+                            engine->execlists.yield);
+               if (del_timer(&engine->execlists.timer))
+                       tasklet = true;
+       }
+
        if (iir & GT_CONTEXT_SWITCH_INTERRUPT)
                tasklet = true;
 
@@ -228,7 +237,8 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
        const u32 irqs =
                GT_CS_MASTER_ERROR_INTERRUPT |
                GT_RENDER_USER_INTERRUPT |
-               GT_CONTEXT_SWITCH_INTERRUPT;
+               GT_CONTEXT_SWITCH_INTERRUPT |
+               GT_WAIT_SEMAPHORE_INTERRUPT;
        struct intel_uncore *uncore = gt->uncore;
        const u32 dmask = irqs << 16 | irqs;
        const u32 smask = irqs << 16;
@@ -366,7 +376,8 @@ void gen8_gt_irq_postinstall(struct intel_gt *gt)
        const u32 irqs =
                GT_CS_MASTER_ERROR_INTERRUPT |
                GT_RENDER_USER_INTERRUPT |
-               GT_CONTEXT_SWITCH_INTERRUPT;
+               GT_CONTEXT_SWITCH_INTERRUPT |
+               GT_WAIT_SEMAPHORE_INTERRUPT;
        const u32 gt_interrupts[] = {
                irqs << GEN8_RCS_IRQ_SHIFT | irqs << GEN8_BCS_IRQ_SHIFT,
                irqs << GEN8_VCS0_IRQ_SHIFT | irqs << GEN8_VCS1_IRQ_SHIFT,
index 683014e7bc51dfff4e68f807e2668e592059fc2d..77420372d8134000af049fef478c4f0c209ba35d 100644 (file)
@@ -456,10 +456,10 @@ assert_priority_queue(const struct i915_request *prev,
  * engine info, SW context ID and SW counter need to form a unique number
  * (Context ID) per lrc.
  */
-static u64
+static u32
 lrc_descriptor(struct intel_context *ce, struct intel_engine_cs *engine)
 {
-       u64 desc;
+       u32 desc;
 
        desc = INTEL_LEGACY_32B_CONTEXT;
        if (i915_vm_is_4lvl(ce->vm))
@@ -470,21 +470,7 @@ lrc_descriptor(struct intel_context *ce, struct intel_engine_cs *engine)
        if (IS_GEN(engine->i915, 8))
                desc |= GEN8_CTX_L3LLC_COHERENT;
 
-       desc |= i915_ggtt_offset(ce->state); /* bits 12-31 */
-       /*
-        * The following 32bits are copied into the OA reports (dword 2).
-        * Consider updating oa_get_render_ctx_id in i915_perf.c when changing
-        * anything below.
-        */
-       if (INTEL_GEN(engine->i915) >= 11) {
-               desc |= (u64)engine->instance << GEN11_ENGINE_INSTANCE_SHIFT;
-                                                               /* bits 48-53 */
-
-               desc |= (u64)engine->class << GEN11_ENGINE_CLASS_SHIFT;
-                                                               /* bits 61-63 */
-       }
-
-       return desc;
+       return i915_ggtt_offset(ce->state) | desc;
 }
 
 static inline unsigned int dword_in_page(void *addr)
@@ -1192,7 +1178,7 @@ static void reset_active(struct i915_request *rq,
        __execlists_update_reg_state(ce, engine, head);
 
        /* We've switched away, so this should be a no-op, but intent matters */
-       ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
+       ce->lrc.desc |= CTX_DESC_FORCE_RESTORE;
 }
 
 static u32 intel_context_get_runtime(const struct intel_context *ce)
@@ -1251,18 +1237,23 @@ __execlists_schedule_in(struct i915_request *rq)
        if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
                execlists_check_context(ce, engine);
 
-       ce->lrc_desc &= ~GENMASK_ULL(47, 37);
        if (ce->tag) {
                /* Use a fixed tag for OA and friends */
-               ce->lrc_desc |= (u64)ce->tag << 32;
+               GEM_BUG_ON(ce->tag <= BITS_PER_LONG);
+               ce->lrc.ccid = ce->tag;
        } else {
                /* We don't need a strict matching tag, just different values */
-               ce->lrc_desc |=
-                       (u64)(++engine->context_tag % NUM_CONTEXT_TAG) <<
-                       GEN11_SW_CTX_ID_SHIFT;
-               BUILD_BUG_ON(NUM_CONTEXT_TAG > GEN12_MAX_CONTEXT_HW_ID);
+               unsigned int tag = ffs(engine->context_tag);
+
+               GEM_BUG_ON(tag == 0 || tag >= BITS_PER_LONG);
+               clear_bit(tag - 1, &engine->context_tag);
+               ce->lrc.ccid = tag << (GEN11_SW_CTX_ID_SHIFT - 32);
+
+               BUILD_BUG_ON(BITS_PER_LONG > GEN12_MAX_CONTEXT_HW_ID);
        }
 
+       ce->lrc.ccid |= engine->execlists.ccid;
+
        __intel_gt_pm_get(engine->gt);
        execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_IN);
        intel_engine_context_in(engine);
@@ -1302,7 +1293,8 @@ static void kick_siblings(struct i915_request *rq, struct intel_context *ce)
 
 static inline void
 __execlists_schedule_out(struct i915_request *rq,
-                        struct intel_engine_cs * const engine)
+                        struct intel_engine_cs * const engine,
+                        unsigned int ccid)
 {
        struct intel_context * const ce = rq->context;
 
@@ -1320,6 +1312,14 @@ __execlists_schedule_out(struct i915_request *rq,
            i915_request_completed(rq))
                intel_engine_add_retire(engine, ce->timeline);
 
+       ccid >>= GEN11_SW_CTX_ID_SHIFT - 32;
+       ccid &= GEN12_MAX_CONTEXT_HW_ID;
+       if (ccid < BITS_PER_LONG) {
+               GEM_BUG_ON(ccid == 0);
+               GEM_BUG_ON(test_bit(ccid - 1, &engine->context_tag));
+               set_bit(ccid - 1, &engine->context_tag);
+       }
+
        intel_context_update_runtime(ce);
        intel_engine_context_out(engine);
        execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT);
@@ -1345,15 +1345,17 @@ execlists_schedule_out(struct i915_request *rq)
 {
        struct intel_context * const ce = rq->context;
        struct intel_engine_cs *cur, *old;
+       u32 ccid;
 
        trace_i915_request_out(rq);
 
+       ccid = rq->context->lrc.ccid;
        old = READ_ONCE(ce->inflight);
        do
                cur = ptr_unmask_bits(old, 2) ? ptr_dec(old) : NULL;
        while (!try_cmpxchg(&ce->inflight, &old, cur));
        if (!cur)
-               __execlists_schedule_out(rq, old);
+               __execlists_schedule_out(rq, old, ccid);
 
        i915_request_put(rq);
 }
@@ -1361,7 +1363,7 @@ execlists_schedule_out(struct i915_request *rq)
 static u64 execlists_update_context(struct i915_request *rq)
 {
        struct intel_context *ce = rq->context;
-       u64 desc = ce->lrc_desc;
+       u64 desc = ce->lrc.desc;
        u32 tail, prev;
 
        /*
@@ -1400,7 +1402,7 @@ static u64 execlists_update_context(struct i915_request *rq)
         */
        wmb();
 
-       ce->lrc_desc &= ~CTX_DESC_FORCE_RESTORE;
+       ce->lrc.desc &= ~CTX_DESC_FORCE_RESTORE;
        return desc;
 }
 
@@ -1754,7 +1756,8 @@ static void defer_active(struct intel_engine_cs *engine)
 }
 
 static bool
-need_timeslice(struct intel_engine_cs *engine, const struct i915_request *rq)
+need_timeslice(const struct intel_engine_cs *engine,
+              const struct i915_request *rq)
 {
        int hint;
 
@@ -1768,6 +1771,32 @@ need_timeslice(struct intel_engine_cs *engine, const struct i915_request *rq)
        return hint >= effective_prio(rq);
 }
 
+static bool
+timeslice_yield(const struct intel_engine_execlists *el,
+               const struct i915_request *rq)
+{
+       /*
+        * Once bitten, forever smitten!
+        *
+        * If the active context ever busy-waited on a semaphore,
+        * it will be treated as a hog until the end of its timeslice (i.e.
+        * until it is scheduled out and replaced by a new submission,
+        * possibly even its own lite-restore). The HW only sends an interrupt
+        * on the first miss, and we do know if that semaphore has been
+        * signaled, or even if it is now stuck on another semaphore. Play
+        * safe, yield if it might be stuck -- it will be given a fresh
+        * timeslice in the near future.
+        */
+       return rq->context->lrc.ccid == READ_ONCE(el->yield);
+}
+
+static bool
+timeslice_expired(const struct intel_engine_execlists *el,
+                 const struct i915_request *rq)
+{
+       return timer_expired(&el->timer) || timeslice_yield(el, rq);
+}
+
 static int
 switch_prio(struct intel_engine_cs *engine, const struct i915_request *rq)
 {
@@ -1783,8 +1812,7 @@ timeslice(const struct intel_engine_cs *engine)
        return READ_ONCE(engine->props.timeslice_duration_ms);
 }
 
-static unsigned long
-active_timeslice(const struct intel_engine_cs *engine)
+static unsigned long active_timeslice(const struct intel_engine_cs *engine)
 {
        const struct intel_engine_execlists *execlists = &engine->execlists;
        const struct i915_request *rq = *execlists->active;
@@ -1946,13 +1974,14 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
 
                        last = NULL;
                } else if (need_timeslice(engine, last) &&
-                          timer_expired(&engine->execlists.timer)) {
+                          timeslice_expired(execlists, last)) {
                        ENGINE_TRACE(engine,
-                                    "expired last=%llx:%lld, prio=%d, hint=%d\n",
+                                    "expired last=%llx:%lld, prio=%d, hint=%d, yield?=%s\n",
                                     last->fence.context,
                                     last->fence.seqno,
                                     last->sched.attr.priority,
-                                    execlists->queue_priority_hint);
+                                    execlists->queue_priority_hint,
+                                    yesno(timeslice_yield(execlists, last)));
 
                        ring_set_paused(engine, 1);
                        defer_active(engine);
@@ -2213,6 +2242,7 @@ done:
                }
                clear_ports(port + 1, last_port - port);
 
+               WRITE_ONCE(execlists->yield, -1);
                execlists_submit_ports(engine);
                set_preempt_timeout(engine, *active);
        } else {
@@ -3043,7 +3073,7 @@ __execlists_context_pin(struct intel_context *ce,
        if (IS_ERR(vaddr))
                return PTR_ERR(vaddr);
 
-       ce->lrc_desc = lrc_descriptor(ce, engine) | CTX_DESC_FORCE_RESTORE;
+       ce->lrc.lrca = lrc_descriptor(ce, engine) | CTX_DESC_FORCE_RESTORE;
        ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
        __execlists_update_reg_state(ce, engine, ce->ring->tail);
 
@@ -3072,7 +3102,7 @@ static void execlists_context_reset(struct intel_context *ce)
                                 ce, ce->engine, ce->ring, true);
        __execlists_update_reg_state(ce, ce->engine, ce->ring->tail);
 
-       ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
+       ce->lrc.desc |= CTX_DESC_FORCE_RESTORE;
 }
 
 static const struct intel_context_ops execlists_context_ops = {
@@ -3541,7 +3571,7 @@ static void enable_execlists(struct intel_engine_cs *engine)
 
        enable_error_interrupt(engine);
 
-       engine->context_tag = 0;
+       engine->context_tag = GENMASK(BITS_PER_LONG - 2, 0);
 }
 
 static bool unexpected_starting_state(struct intel_engine_cs *engine)
@@ -3753,7 +3783,7 @@ out_replay:
                     head, ce->ring->tail);
        __execlists_reset_reg_state(ce, engine);
        __execlists_update_reg_state(ce, engine, head);
-       ce->lrc_desc |= CTX_DESC_FORCE_RESTORE; /* paranoid: GPU was reset! */
+       ce->lrc.desc |= CTX_DESC_FORCE_RESTORE; /* paranoid: GPU was reset! */
 
 unwind:
        /* Push back any incomplete requests for replay after the reset. */
@@ -4369,8 +4399,11 @@ void intel_execlists_set_default_submission(struct intel_engine_cs *engine)
        engine->flags |= I915_ENGINE_SUPPORTS_STATS;
        if (!intel_vgpu_active(engine->i915)) {
                engine->flags |= I915_ENGINE_HAS_SEMAPHORES;
-               if (HAS_LOGICAL_RING_PREEMPTION(engine->i915))
+               if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) {
                        engine->flags |= I915_ENGINE_HAS_PREEMPTION;
+                       if (IS_ACTIVE(CONFIG_DRM_I915_TIMESLICE_DURATION))
+                               engine->flags |= I915_ENGINE_HAS_TIMESLICES;
+               }
        }
 
        if (INTEL_GEN(engine->i915) >= 12)
@@ -4449,6 +4482,7 @@ logical_ring_default_irqs(struct intel_engine_cs *engine)
        engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << shift;
        engine->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift;
        engine->irq_keep_mask |= GT_CS_MASTER_ERROR_INTERRUPT << shift;
+       engine->irq_keep_mask |= GT_WAIT_SEMAPHORE_INTERRUPT << shift;
 }
 
 static void rcs_submission_override(struct intel_engine_cs *engine)
@@ -4516,6 +4550,11 @@ int intel_execlists_submission_setup(struct intel_engine_cs *engine)
        else
                execlists->csb_size = GEN11_CSB_ENTRIES;
 
+       if (INTEL_GEN(engine->i915) >= 11) {
+               execlists->ccid |= engine->instance << (GEN11_ENGINE_INSTANCE_SHIFT - 32);
+               execlists->ccid |= engine->class << (GEN11_ENGINE_CLASS_SHIFT - 32);
+       }
+
        reset_csb_pointers(engine);
 
        /* Finally, take ownership and responsibility for cleanup! */
index cfaf141bac4d86e1f2e8cea1642120ed55f0829d..19542fd9e207e94325e9ea99a70972a0285d9182 100644 (file)
@@ -81,13 +81,14 @@ static void rps_enable_interrupts(struct intel_rps *rps)
                events = (GEN6_PM_RP_UP_THRESHOLD |
                          GEN6_PM_RP_DOWN_THRESHOLD |
                          GEN6_PM_RP_DOWN_TIMEOUT);
-
        WRITE_ONCE(rps->pm_events, events);
+
        spin_lock_irq(&gt->irq_lock);
        gen6_gt_pm_enable_irq(gt, rps->pm_events);
        spin_unlock_irq(&gt->irq_lock);
 
-       set(gt->uncore, GEN6_PMINTRMSK, rps_pm_mask(rps, rps->cur_freq));
+       intel_uncore_write(gt->uncore,
+                          GEN6_PMINTRMSK, rps_pm_mask(rps, rps->last_freq));
 }
 
 static void gen6_rps_reset_interrupts(struct intel_rps *rps)
@@ -120,7 +121,9 @@ static void rps_disable_interrupts(struct intel_rps *rps)
        struct intel_gt *gt = rps_to_gt(rps);
 
        WRITE_ONCE(rps->pm_events, 0);
-       set(gt->uncore, GEN6_PMINTRMSK, rps_pm_sanitize_mask(rps, ~0u));
+
+       intel_uncore_write(gt->uncore,
+                          GEN6_PMINTRMSK, rps_pm_sanitize_mask(rps, ~0u));
 
        spin_lock_irq(&gt->irq_lock);
        gen6_gt_pm_disable_irq(gt, GEN6_PM_RPS_EVENTS);
index 91debbc97c9ad8baa6790749a797d83a7731d284..08b56d7ab4f45054754373b5b47a541755f4c01b 100644 (file)
@@ -521,6 +521,8 @@ int intel_timeline_read_hwsp(struct i915_request *from,
 
        rcu_read_lock();
        cl = rcu_dereference(from->hwsp_cacheline);
+       if (i915_request_completed(from)) /* confirm cacheline is valid */
+               goto unlock;
        if (unlikely(!i915_active_acquire_if_busy(&cl->active)))
                goto unlock; /* seqno wrapped and completed! */
        if (unlikely(i915_request_completed(from)))
index 6f06ba750a0a8e2518d8ce458ad49355955cefda..f95ae15ce865c0fbad7fd7f4a85e655ba9b0c17e 100644 (file)
@@ -929,7 +929,7 @@ create_rewinder(struct intel_context *ce,
                        goto err;
        }
 
-       cs = intel_ring_begin(rq, 10);
+       cs = intel_ring_begin(rq, 14);
        if (IS_ERR(cs)) {
                err = PTR_ERR(cs);
                goto err;
@@ -941,8 +941,8 @@ create_rewinder(struct intel_context *ce,
        *cs++ = MI_SEMAPHORE_WAIT |
                MI_SEMAPHORE_GLOBAL_GTT |
                MI_SEMAPHORE_POLL |
-               MI_SEMAPHORE_SAD_NEQ_SDD;
-       *cs++ = 0;
+               MI_SEMAPHORE_SAD_GTE_SDD;
+       *cs++ = idx;
        *cs++ = offset;
        *cs++ = 0;
 
@@ -951,6 +951,11 @@ create_rewinder(struct intel_context *ce,
        *cs++ = offset + idx * sizeof(u32);
        *cs++ = 0;
 
+       *cs++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT;
+       *cs++ = offset;
+       *cs++ = 0;
+       *cs++ = idx + 1;
+
        intel_ring_advance(rq, cs);
 
        rq->sched.attr.priority = I915_PRIORITY_MASK;
@@ -984,7 +989,7 @@ static int live_timeslice_rewind(void *arg)
 
        for_each_engine(engine, gt, id) {
                enum { A1, A2, B1 };
-               enum { X = 1, Y, Z };
+               enum { X = 1, Z, Y };
                struct i915_request *rq[3] = {};
                struct intel_context *ce;
                unsigned long heartbeat;
@@ -1017,13 +1022,13 @@ static int live_timeslice_rewind(void *arg)
                        goto err;
                }
 
-               rq[0] = create_rewinder(ce, NULL, slot, 1);
+               rq[0] = create_rewinder(ce, NULL, slot, X);
                if (IS_ERR(rq[0])) {
                        intel_context_put(ce);
                        goto err;
                }
 
-               rq[1] = create_rewinder(ce, NULL, slot, 2);
+               rq[1] = create_rewinder(ce, NULL, slot, Y);
                intel_context_put(ce);
                if (IS_ERR(rq[1]))
                        goto err;
@@ -1041,7 +1046,7 @@ static int live_timeslice_rewind(void *arg)
                        goto err;
                }
 
-               rq[2] = create_rewinder(ce, rq[0], slot, 3);
+               rq[2] = create_rewinder(ce, rq[0], slot, Z);
                intel_context_put(ce);
                if (IS_ERR(rq[2]))
                        goto err;
@@ -1055,15 +1060,12 @@ static int live_timeslice_rewind(void *arg)
                GEM_BUG_ON(!timer_pending(&engine->execlists.timer));
 
                /* ELSP[] = { { A:rq1, A:rq2 }, { B:rq1 } } */
-               GEM_BUG_ON(!i915_request_is_active(rq[A1]));
-               GEM_BUG_ON(!i915_request_is_active(rq[A2]));
-               GEM_BUG_ON(!i915_request_is_active(rq[B1]));
-
-               /* Wait for the timeslice to kick in */
-               del_timer(&engine->execlists.timer);
-               tasklet_hi_schedule(&engine->execlists.tasklet);
-               intel_engine_flush_submission(engine);
-
+               if (i915_request_is_active(rq[A2])) { /* semaphore yielded! */
+                       /* Wait for the timeslice to kick in */
+                       del_timer(&engine->execlists.timer);
+                       tasklet_hi_schedule(&engine->execlists.tasklet);
+                       intel_engine_flush_submission(engine);
+               }
                /* -> ELSP[] = { { A:rq1 }, { B:rq1 } } */
                GEM_BUG_ON(!i915_request_is_active(rq[A1]));
                GEM_BUG_ON(!i915_request_is_active(rq[B1]));
index fe7778c28d2d7846c308da40668bf86dd445765c..aa6d56e25a10ae3fa6b3a5d26a16e0d45bd69917 100644 (file)
@@ -217,7 +217,7 @@ static void guc_wq_item_append(struct intel_guc *guc,
 static void guc_add_request(struct intel_guc *guc, struct i915_request *rq)
 {
        struct intel_engine_cs *engine = rq->engine;
-       u32 ctx_desc = lower_32_bits(rq->context->lrc_desc);
+       u32 ctx_desc = rq->context->lrc.ccid;
        u32 ring_tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64);
 
        guc_wq_item_append(guc, engine->guc_id, ctx_desc,
index 074c4efb58eb96e7d25045ddfd1b6a76c1995973..eee530453aa6772d94ea095dfe46bce3db8c7256 100644 (file)
@@ -131,6 +131,7 @@ struct kvmgt_vdev {
        struct work_struct release_work;
        atomic_t released;
        struct vfio_device *vfio_device;
+       struct vfio_group *vfio_group;
 };
 
 static inline struct kvmgt_vdev *kvmgt_vdev(struct intel_vgpu *vgpu)
@@ -151,6 +152,7 @@ static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
                unsigned long size)
 {
        struct drm_i915_private *i915 = vgpu->gvt->gt->i915;
+       struct kvmgt_vdev *vdev = kvmgt_vdev(vgpu);
        int total_pages;
        int npage;
        int ret;
@@ -160,7 +162,7 @@ static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
        for (npage = 0; npage < total_pages; npage++) {
                unsigned long cur_gfn = gfn + npage;
 
-               ret = vfio_unpin_pages(mdev_dev(kvmgt_vdev(vgpu)->mdev), &cur_gfn, 1);
+               ret = vfio_group_unpin_pages(vdev->vfio_group, &cur_gfn, 1);
                drm_WARN_ON(&i915->drm, ret != 1);
        }
 }
@@ -169,6 +171,7 @@ static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
 static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
                unsigned long size, struct page **page)
 {
+       struct kvmgt_vdev *vdev = kvmgt_vdev(vgpu);
        unsigned long base_pfn = 0;
        int total_pages;
        int npage;
@@ -183,8 +186,8 @@ static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
                unsigned long cur_gfn = gfn + npage;
                unsigned long pfn;
 
-               ret = vfio_pin_pages(mdev_dev(kvmgt_vdev(vgpu)->mdev), &cur_gfn, 1,
-                                    IOMMU_READ | IOMMU_WRITE, &pfn);
+               ret = vfio_group_pin_pages(vdev->vfio_group, &cur_gfn, 1,
+                                          IOMMU_READ | IOMMU_WRITE, &pfn);
                if (ret != 1) {
                        gvt_vgpu_err("vfio_pin_pages failed for gfn 0x%lx, ret %d\n",
                                     cur_gfn, ret);
@@ -792,6 +795,7 @@ static int intel_vgpu_open(struct mdev_device *mdev)
        struct kvmgt_vdev *vdev = kvmgt_vdev(vgpu);
        unsigned long events;
        int ret;
+       struct vfio_group *vfio_group;
 
        vdev->iommu_notifier.notifier_call = intel_vgpu_iommu_notifier;
        vdev->group_notifier.notifier_call = intel_vgpu_group_notifier;
@@ -814,6 +818,14 @@ static int intel_vgpu_open(struct mdev_device *mdev)
                goto undo_iommu;
        }
 
+       vfio_group = vfio_group_get_external_user_from_dev(mdev_dev(mdev));
+       if (IS_ERR_OR_NULL(vfio_group)) {
+               ret = !vfio_group ? -EFAULT : PTR_ERR(vfio_group);
+               gvt_vgpu_err("vfio_group_get_external_user_from_dev failed\n");
+               goto undo_register;
+       }
+       vdev->vfio_group = vfio_group;
+
        /* Take a module reference as mdev core doesn't take
         * a reference for vendor driver.
         */
@@ -830,6 +842,10 @@ static int intel_vgpu_open(struct mdev_device *mdev)
        return ret;
 
 undo_group:
+       vfio_group_put_external_user(vdev->vfio_group);
+       vdev->vfio_group = NULL;
+
+undo_register:
        vfio_unregister_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY,
                                        &vdev->group_notifier);
 
@@ -884,6 +900,7 @@ static void __intel_vgpu_release(struct intel_vgpu *vgpu)
        kvmgt_guest_exit(info);
 
        intel_vgpu_release_msi_eventfd_ctx(vgpu);
+       vfio_group_put_external_user(vdev->vfio_group);
 
        vdev->kvm = NULL;
        vgpu->handle = 0;
@@ -2035,33 +2052,14 @@ static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa,
                        void *buf, unsigned long len, bool write)
 {
        struct kvmgt_guest_info *info;
-       struct kvm *kvm;
-       int idx, ret;
-       bool kthread = current->mm == NULL;
 
        if (!handle_valid(handle))
                return -ESRCH;
 
        info = (struct kvmgt_guest_info *)handle;
-       kvm = info->kvm;
-
-       if (kthread) {
-               if (!mmget_not_zero(kvm->mm))
-                       return -EFAULT;
-               use_mm(kvm->mm);
-       }
-
-       idx = srcu_read_lock(&kvm->srcu);
-       ret = write ? kvm_write_guest(kvm, gpa, buf, len) :
-                     kvm_read_guest(kvm, gpa, buf, len);
-       srcu_read_unlock(&kvm->srcu, idx);
-
-       if (kthread) {
-               unuse_mm(kvm->mm);
-               mmput(kvm->mm);
-       }
 
-       return ret;
+       return vfio_dma_rw(kvmgt_vdev(info->vgpu)->vfio_group,
+                          gpa, buf, len, write);
 }
 
 static int kvmgt_read_gpa(unsigned long handle, unsigned long gpa,
index cb11c31840857293ff2d3b7a0d7688e4ccf02e35..6eb6710b35e9ba4d174ceca93f54b3eb91b05954 100644 (file)
@@ -290,7 +290,7 @@ static void
 shadow_context_descriptor_update(struct intel_context *ce,
                                 struct intel_vgpu_workload *workload)
 {
-       u64 desc = ce->lrc_desc;
+       u64 desc = ce->lrc.desc;
 
        /*
         * Update bits 0-11 of the context descriptor which includes flags
@@ -300,7 +300,7 @@ shadow_context_descriptor_update(struct intel_context *ce,
        desc |= (u64)workload->ctx_desc.addressing_mode <<
                GEN8_CTX_ADDRESSING_MODE_SHIFT;
 
-       ce->lrc_desc = desc;
+       ce->lrc.desc = desc;
 }
 
 static int copy_workload_to_ring_buffer(struct intel_vgpu_workload *workload)
index 1f5b9a584f71795ea6cb9869e96338ab6e39d808..62b901ffabf9bd8087b3fe666072e4bc6271b253 100644 (file)
@@ -1507,6 +1507,8 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
        (IS_ICELAKE(p) && IS_REVID(p, since, until))
 
 #define TGL_REVID_A0           0x0
+#define TGL_REVID_B0           0x1
+#define TGL_REVID_C0           0x2
 
 #define IS_TGL_REVID(p, since, until) \
        (IS_TIGERLAKE(p) && IS_REVID(p, since, until))
index 2a4cd0ba546459a622536a7bed16ed4b6e014680..5c8e51d2ba5b3e139581f14f8713b5f555bb64b7 100644 (file)
@@ -1207,8 +1207,6 @@ static void engine_record_registers(struct intel_engine_coredump *ee)
 static void record_request(const struct i915_request *request,
                           struct i915_request_coredump *erq)
 {
-       const struct i915_gem_context *ctx;
-
        erq->flags = request->fence.flags;
        erq->context = request->fence.context;
        erq->seqno = request->fence.seqno;
@@ -1219,9 +1217,13 @@ static void record_request(const struct i915_request *request,
 
        erq->pid = 0;
        rcu_read_lock();
-       ctx = rcu_dereference(request->context->gem_context);
-       if (ctx)
-               erq->pid = pid_nr(ctx->pid);
+       if (!intel_context_is_closed(request->context)) {
+               const struct i915_gem_context *ctx;
+
+               ctx = rcu_dereference(request->context->gem_context);
+               if (ctx)
+                       erq->pid = pid_nr(ctx->pid);
+       }
        rcu_read_unlock();
 }
 
index 9f0653cf05102d896099118c69ed911044ba17cc..8a2b83807ffcddf9190d726bee60aea57413181c 100644 (file)
@@ -3358,9 +3358,10 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
 {
        struct intel_uncore *uncore = &dev_priv->uncore;
 
-       u32 de_pipe_masked = GEN8_PIPE_CDCLK_CRC_DONE;
+       u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) |
+               GEN8_PIPE_CDCLK_CRC_DONE;
        u32 de_pipe_enables;
-       u32 de_port_masked = GEN8_AUX_CHANNEL_A;
+       u32 de_port_masked = gen8_de_port_aux_mask(dev_priv);
        u32 de_port_enables;
        u32 de_misc_masked = GEN8_DE_EDP_PSR;
        enum pipe pipe;
@@ -3368,21 +3369,8 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
        if (INTEL_GEN(dev_priv) <= 10)
                de_misc_masked |= GEN8_DE_MISC_GSE;
 
-       if (INTEL_GEN(dev_priv) >= 9) {
-               de_pipe_masked |= GEN9_DE_PIPE_IRQ_FAULT_ERRORS;
-               de_port_masked |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C |
-                                 GEN9_AUX_CHANNEL_D;
-               if (IS_GEN9_LP(dev_priv))
-                       de_port_masked |= BXT_DE_PORT_GMBUS;
-       } else {
-               de_pipe_masked |= GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
-       }
-
-       if (INTEL_GEN(dev_priv) >= 11)
-               de_port_masked |= ICL_AUX_CHANNEL_E;
-
-       if (IS_CNL_WITH_PORT_F(dev_priv) || INTEL_GEN(dev_priv) >= 11)
-               de_port_masked |= CNL_AUX_CHANNEL_F;
+       if (IS_GEN9_LP(dev_priv))
+               de_port_masked |= BXT_DE_PORT_GMBUS;
 
        de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK |
                                           GEN8_PIPE_FIFO_UNDERRUN;
index 551be589d6f481449718e0d0d50991e957ccf4f5..cf2c01f17da837235dd8f79e1614cf896e814299 100644 (file)
@@ -1310,8 +1310,7 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
                         * dropped by GuC. They won't be part of the context
                         * ID in the OA reports, so squash those lower bits.
                         */
-                       stream->specific_ctx_id =
-                               lower_32_bits(ce->lrc_desc) >> 12;
+                       stream->specific_ctx_id = ce->lrc.lrca >> 12;
 
                        /*
                         * GuC uses the top bit to signal proxy submission, so
@@ -1328,11 +1327,10 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
                        ((1U << GEN11_SW_CTX_ID_WIDTH) - 1) << (GEN11_SW_CTX_ID_SHIFT - 32);
                /*
                 * Pick an unused context id
-                * 0 - (NUM_CONTEXT_TAG - 1) are used by other contexts
+                * 0 - BITS_PER_LONG are used by other contexts
                 * GEN12_MAX_CONTEXT_HW_ID (0x7ff) is used by idle context
                 */
                stream->specific_ctx_id = (GEN12_MAX_CONTEXT_HW_ID - 1) << (GEN11_SW_CTX_ID_SHIFT - 32);
-               BUILD_BUG_ON((GEN12_MAX_CONTEXT_HW_ID - 1) < NUM_CONTEXT_TAG);
                break;
        }
 
@@ -2940,49 +2938,6 @@ void i915_oa_init_reg_state(const struct intel_context *ce,
                gen8_update_reg_state_unlocked(ce, stream);
 }
 
-/**
- * i915_perf_read_locked - &i915_perf_stream_ops->read with error normalisation
- * @stream: An i915 perf stream
- * @file: An i915 perf stream file
- * @buf: destination buffer given by userspace
- * @count: the number of bytes userspace wants to read
- * @ppos: (inout) file seek position (unused)
- *
- * Besides wrapping &i915_perf_stream_ops->read this provides a common place to
- * ensure that if we've successfully copied any data then reporting that takes
- * precedence over any internal error status, so the data isn't lost.
- *
- * For example ret will be -ENOSPC whenever there is more buffered data than
- * can be copied to userspace, but that's only interesting if we weren't able
- * to copy some data because it implies the userspace buffer is too small to
- * receive a single record (and we never split records).
- *
- * Another case with ret == -EFAULT is more of a grey area since it would seem
- * like bad form for userspace to ask us to overrun its buffer, but the user
- * knows best:
- *
- *   http://yarchive.net/comp/linux/partial_reads_writes.html
- *
- * Returns: The number of bytes copied or a negative error code on failure.
- */
-static ssize_t i915_perf_read_locked(struct i915_perf_stream *stream,
-                                    struct file *file,
-                                    char __user *buf,
-                                    size_t count,
-                                    loff_t *ppos)
-{
-       /* Note we keep the offset (aka bytes read) separate from any
-        * error status so that the final check for whether we return
-        * the bytes read with a higher precedence than any error (see
-        * comment below) doesn't need to be handled/duplicated in
-        * stream->ops->read() implementations.
-        */
-       size_t offset = 0;
-       int ret = stream->ops->read(stream, buf, count, &offset);
-
-       return offset ?: (ret ?: -EAGAIN);
-}
-
 /**
  * i915_perf_read - handles read() FOP for i915 perf stream FDs
  * @file: An i915 perf stream file
@@ -3008,7 +2963,8 @@ static ssize_t i915_perf_read(struct file *file,
 {
        struct i915_perf_stream *stream = file->private_data;
        struct i915_perf *perf = stream->perf;
-       ssize_t ret;
+       size_t offset = 0;
+       int ret;
 
        /* To ensure it's handled consistently we simply treat all reads of a
         * disabled stream as an error. In particular it might otherwise lead
@@ -3031,13 +2987,12 @@ static ssize_t i915_perf_read(struct file *file,
                                return ret;
 
                        mutex_lock(&perf->lock);
-                       ret = i915_perf_read_locked(stream, file,
-                                                   buf, count, ppos);
+                       ret = stream->ops->read(stream, buf, count, &offset);
                        mutex_unlock(&perf->lock);
-               } while (ret == -EAGAIN);
+               } while (!offset && !ret);
        } else {
                mutex_lock(&perf->lock);
-               ret = i915_perf_read_locked(stream, file, buf, count, ppos);
+               ret = stream->ops->read(stream, buf, count, &offset);
                mutex_unlock(&perf->lock);
        }
 
@@ -3048,15 +3003,15 @@ static ssize_t i915_perf_read(struct file *file,
         * and read() returning -EAGAIN. Clearing the oa.pollin state here
         * effectively ensures we back off until the next hrtimer callback
         * before reporting another EPOLLIN event.
+        * The exception to this is if ops->read() returned -ENOSPC which means
+        * that more OA data is available than could fit in the user provided
+        * buffer. In this case we want the next poll() call to not block.
         */
-       if (ret >= 0 || ret == -EAGAIN) {
-               /* Maybe make ->pollin per-stream state if we support multiple
-                * concurrent streams in the future.
-                */
+       if (ret != -ENOSPC)
                stream->pollin = false;
-       }
 
-       return ret;
+       /* Possible values for ret are 0, -EFAULT, -ENOSPC, -EIO, ... */
+       return offset ?: (ret ?: -EAGAIN);
 }
 
 static enum hrtimer_restart oa_poll_check_timer_cb(struct hrtimer *hrtimer)
index 59e64acc2c5680afd514b860a258c321728ea2d9..6e12000c4b6b5cd7cb181c8bd2954a8da7d2b574 100644 (file)
@@ -34,8 +34,8 @@
  * Follow the style described here for new macros, and while changing existing
  * macros. Do **not** mass change existing definitions just to update the style.
  *
- * Layout
- * ~~~~~~
+ * File Layout
+ * ~~~~~~~~~~~
  *
  * Keep helper macros near the top. For example, _PIPE() and friends.
  *
@@ -3094,6 +3094,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
 #define GT_BSD_CS_ERROR_INTERRUPT              (1 << 15)
 #define GT_BSD_USER_INTERRUPT                  (1 << 12)
 #define GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 (1 << 11) /* hsw+; rsvd on snb, ivb, vlv */
+#define GT_WAIT_SEMAPHORE_INTERRUPT            REG_BIT(11) /* bdw+ */
 #define GT_CONTEXT_SWITCH_INTERRUPT            (1 <<  8)
 #define GT_RENDER_L3_PARITY_ERROR_INTERRUPT    (1 <<  5) /* !snb */
 #define GT_RENDER_PIPECTL_NOTIFY_INTERRUPT     (1 <<  4)
index 08699fa069aa6f5e8b1f4b34b98b87f12fe1cfe8..2cd7a7e87c0a750ff87db98f9bfce927af88dda6 100644 (file)
@@ -158,16 +158,18 @@ vma_create(struct drm_i915_gem_object *obj,
 
        GEM_BUG_ON(!IS_ALIGNED(vma->size, I915_GTT_PAGE_SIZE));
 
+       spin_lock(&obj->vma.lock);
+
        if (i915_is_ggtt(vm)) {
                if (unlikely(overflows_type(vma->size, u32)))
-                       goto err_vma;
+                       goto err_unlock;
 
                vma->fence_size = i915_gem_fence_size(vm->i915, vma->size,
                                                      i915_gem_object_get_tiling(obj),
                                                      i915_gem_object_get_stride(obj));
                if (unlikely(vma->fence_size < vma->size || /* overflow */
                             vma->fence_size > vm->total))
-                       goto err_vma;
+                       goto err_unlock;
 
                GEM_BUG_ON(!IS_ALIGNED(vma->fence_size, I915_GTT_MIN_ALIGNMENT));
 
@@ -179,8 +181,6 @@ vma_create(struct drm_i915_gem_object *obj,
                __set_bit(I915_VMA_GGTT_BIT, __i915_vma_flags(vma));
        }
 
-       spin_lock(&obj->vma.lock);
-
        rb = NULL;
        p = &obj->vma.tree.rb_node;
        while (*p) {
@@ -225,6 +225,8 @@ vma_create(struct drm_i915_gem_object *obj,
 
        return vma;
 
+err_unlock:
+       spin_unlock(&obj->vma.lock);
 err_vma:
        i915_vma_free(vma);
        return ERR_PTR(-E2BIG);
@@ -1226,18 +1228,6 @@ int __i915_vma_unbind(struct i915_vma *vma)
 
        lockdep_assert_held(&vma->vm->mutex);
 
-       /*
-        * First wait upon any activity as retiring the request may
-        * have side-effects such as unpinning or even unbinding this vma.
-        *
-        * XXX Actually waiting under the vm->mutex is a hinderance and
-        * should be pipelined wherever possible. In cases where that is
-        * unavoidable, we should lift the wait to before the mutex.
-        */
-       ret = i915_vma_sync(vma);
-       if (ret)
-               return ret;
-
        if (i915_vma_is_pinned(vma)) {
                vma_print_allocator(vma, "is pinned");
                return -EAGAIN;
@@ -1311,15 +1301,20 @@ int i915_vma_unbind(struct i915_vma *vma)
        if (!drm_mm_node_allocated(&vma->node))
                return 0;
 
-       if (i915_vma_is_bound(vma, I915_VMA_GLOBAL_BIND))
-               /* XXX not always required: nop_clear_range */
-               wakeref = intel_runtime_pm_get(&vm->i915->runtime_pm);
-
        /* Optimistic wait before taking the mutex */
        err = i915_vma_sync(vma);
        if (err)
                goto out_rpm;
 
+       if (i915_vma_is_pinned(vma)) {
+               vma_print_allocator(vma, "is pinned");
+               return -EAGAIN;
+       }
+
+       if (i915_vma_is_bound(vma, I915_VMA_GLOBAL_BIND))
+               /* XXX not always required: nop_clear_range */
+               wakeref = intel_runtime_pm_get(&vm->i915->runtime_pm);
+
        err = mutex_lock_interruptible(&vm->mutex);
        if (err)
                goto out_rpm;
index 8375054ba27d92b72f6b03a0e15f2703b5befdb5..a52986a9e7a68245f670746e1e3ba32ad90db042 100644 (file)
@@ -4992,7 +4992,7 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state,
         * WaIncreaseLatencyIPCEnabled: kbl,cfl
         * Display WA #1141: kbl,cfl
         */
-       if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) ||
+       if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) &&
            dev_priv->ipc_enabled)
                latency += 4;
 
index 58b5f40a07dd6be16eedab36d8c52d9ff9e2e914..af89c7fc8f59340bad9d38628b0c6f751caed521 100644 (file)
@@ -173,7 +173,7 @@ static int igt_vma_create(void *arg)
                }
 
                nc = 0;
-               for_each_prime_number(num_ctx, 2 * NUM_CONTEXT_TAG) {
+               for_each_prime_number(num_ctx, 2 * BITS_PER_LONG) {
                        for (; nc < num_ctx; nc++) {
                                ctx = mock_context(i915, "mock");
                                if (!ctx)
index 9dfe7cb530e1184c5d158c12622bcd5242dd1fa7..1754c054706906f6a419923b3e239f27aa8a4328 100644 (file)
@@ -843,6 +843,7 @@ static const struct of_device_id ingenic_drm_of_match[] = {
        { .compatible = "ingenic,jz4770-lcd", .data = &jz4770_soc_info },
        { /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, ingenic_drm_of_match);
 
 static struct platform_driver ingenic_drm_driver = {
        .driver = {
index e8c94915a4fcf3936f7a18c7fc9bdabcaa8e6016..64cb6ba4bc42d9ebb19f6dedb1272a36e094185d 100644 (file)
@@ -1034,10 +1034,8 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
                return PTR_ERR(dw_plat_data->regm);
 
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(dev, "Failed to get hdmi top irq\n");
+       if (irq < 0)
                return irq;
-       }
 
        ret = devm_request_threaded_irq(dev, irq, dw_hdmi_top_irq,
                                        dw_hdmi_top_thread_irq, IRQF_SHARED,
index 232a9d7c51e5d20d02277441cee77c4ecfb328a1..e770c9497871bc09086f2b4a7f5ddefe688c2327 100644 (file)
@@ -25,6 +25,9 @@
 MODULE_FIRMWARE("nvidia/gp108/sec2/desc.bin");
 MODULE_FIRMWARE("nvidia/gp108/sec2/image.bin");
 MODULE_FIRMWARE("nvidia/gp108/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/gv100/sec2/desc.bin");
+MODULE_FIRMWARE("nvidia/gv100/sec2/image.bin");
+MODULE_FIRMWARE("nvidia/gv100/sec2/sig.bin");
 
 static const struct nvkm_sec2_fwif
 gp108_sec2_fwif[] = {
index b6ebd95c9ba1ee907a526a472d0ce3700b0c8535..a8295653ceab17303e27a8724bf33b07367f5482 100644 (file)
@@ -56,6 +56,22 @@ tu102_sec2_nofw(struct nvkm_sec2 *sec2, int ver,
        return 0;
 }
 
+MODULE_FIRMWARE("nvidia/tu102/sec2/desc.bin");
+MODULE_FIRMWARE("nvidia/tu102/sec2/image.bin");
+MODULE_FIRMWARE("nvidia/tu102/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/tu104/sec2/desc.bin");
+MODULE_FIRMWARE("nvidia/tu104/sec2/image.bin");
+MODULE_FIRMWARE("nvidia/tu104/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/tu106/sec2/desc.bin");
+MODULE_FIRMWARE("nvidia/tu106/sec2/image.bin");
+MODULE_FIRMWARE("nvidia/tu106/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/tu116/sec2/desc.bin");
+MODULE_FIRMWARE("nvidia/tu116/sec2/image.bin");
+MODULE_FIRMWARE("nvidia/tu116/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/tu117/sec2/desc.bin");
+MODULE_FIRMWARE("nvidia/tu117/sec2/image.bin");
+MODULE_FIRMWARE("nvidia/tu117/sec2/sig.bin");
+
 static const struct nvkm_sec2_fwif
 tu102_sec2_fwif[] = {
        {  0, gp102_sec2_load, &tu102_sec2, &gp102_sec2_acr_1 },
index d1086b2a6892ceb1a15dfc90936fe500d5fae72a..05863b253d6889d47f274b63ad5243c9467a40f0 100644 (file)
@@ -480,9 +480,10 @@ int qxl_hw_surface_alloc(struct qxl_device *qdev,
                return ret;
 
        ret = qxl_release_reserve_list(release, true);
-       if (ret)
+       if (ret) {
+               qxl_release_free(qdev, release);
                return ret;
-
+       }
        cmd = (struct qxl_surface_cmd *)qxl_release_map(qdev, release);
        cmd->type = QXL_SURFACE_CMD_CREATE;
        cmd->flags = QXL_SURF_FLAG_KEEP_DATA;
@@ -499,8 +500,8 @@ int qxl_hw_surface_alloc(struct qxl_device *qdev,
        /* no need to add a release to the fence for this surface bo,
           since it is only released when we ask to destroy the surface
           and it would never signal otherwise */
-       qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
        qxl_release_fence_buffer_objects(release);
+       qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
 
        surf->hw_surf_alloc = true;
        spin_lock(&qdev->surf_id_idr_lock);
@@ -542,9 +543,8 @@ int qxl_hw_surface_dealloc(struct qxl_device *qdev,
        cmd->surface_id = id;
        qxl_release_unmap(qdev, release, &cmd->release_info);
 
-       qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
-
        qxl_release_fence_buffer_objects(release);
+       qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
 
        return 0;
 }
index 09583a08e1414381e759f91cb1c70d0ee26251f8..91f398d51cfadf4e69fd60125147d2d35eb905d1 100644 (file)
@@ -510,8 +510,8 @@ static int qxl_primary_apply_cursor(struct drm_plane *plane)
        cmd->u.set.visible = 1;
        qxl_release_unmap(qdev, release, &cmd->release_info);
 
-       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
        qxl_release_fence_buffer_objects(release);
+       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
 
        return ret;
 
@@ -652,8 +652,8 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
        cmd->u.position.y = plane->state->crtc_y + fb->hot_y;
 
        qxl_release_unmap(qdev, release, &cmd->release_info);
-       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
        qxl_release_fence_buffer_objects(release);
+       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
 
        if (old_cursor_bo != NULL)
                qxl_bo_unpin(old_cursor_bo);
@@ -700,8 +700,8 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane,
        cmd->type = QXL_CURSOR_HIDE;
        qxl_release_unmap(qdev, release, &cmd->release_info);
 
-       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
        qxl_release_fence_buffer_objects(release);
+       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
 }
 
 static void qxl_update_dumb_head(struct qxl_device *qdev,
index 5bebf1ea1c5d0c5b59b1cb3579dc62f93dba0cef..3599db096973e9fd2fb9d0b9e8e102053c31835b 100644 (file)
@@ -209,9 +209,10 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
                goto out_release_backoff;
 
        rects = drawable_set_clipping(qdev, num_clips, clips_bo);
-       if (!rects)
+       if (!rects) {
+               ret = -EINVAL;
                goto out_release_backoff;
-
+       }
        drawable = (struct qxl_drawable *)qxl_release_map(qdev, release);
 
        drawable->clip.type = SPICE_CLIP_TYPE_RECTS;
@@ -242,8 +243,8 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
        }
        qxl_bo_kunmap(clips_bo);
 
-       qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
        qxl_release_fence_buffer_objects(release);
+       qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
 
 out_release_backoff:
        if (ret)
index 43688ecdd8a04d9d4bc3286ae03259c9892626e8..60ab7151b84dce9a2d2d4aa9837345fde2951c5a 100644 (file)
@@ -212,7 +212,8 @@ qxl_image_init_helper(struct qxl_device *qdev,
                break;
        default:
                DRM_ERROR("unsupported image bit depth\n");
-               return -EINVAL; /* TODO: cleanup */
+               qxl_bo_kunmap_atomic_page(qdev, image_bo, ptr);
+               return -EINVAL;
        }
        image->u.bitmap.flags = QXL_BITMAP_TOP_DOWN;
        image->u.bitmap.x = width;
index 8117a45b36102192b3acd09e269faedfb06dc146..72f3f1bbb40c1de0cf3f6a77047530fa2e47ef85 100644 (file)
@@ -261,11 +261,8 @@ static int qxl_process_single_command(struct qxl_device *qdev,
                        apply_surf_reloc(qdev, &reloc_info[i]);
        }
 
+       qxl_release_fence_buffer_objects(release);
        ret = qxl_push_command_ring_release(qdev, release, cmd->type, true);
-       if (ret)
-               qxl_release_backoff_reserve_list(release);
-       else
-               qxl_release_fence_buffer_objects(release);
 
 out_free_bos:
 out_free_release:
index 8e731ed0d9d9f81d4b04bfe5ecd4e139c13bfd51..2f319102ae9f7f39366f54a6ccfe52812af8e9b9 100644 (file)
@@ -676,7 +676,7 @@ drm_sched_get_cleanup_job(struct drm_gpu_scheduler *sched)
         */
        if ((sched->timeout != MAX_SCHEDULE_TIMEOUT &&
            !cancel_delayed_work(&sched->work_tdr)) ||
-           __kthread_should_park(sched->thread))
+           kthread_should_park())
                return NULL;
 
        spin_lock(&sched->job_list_lock);
index 059939789730d893d089634e37daadb866c60387..3eb89f1eb0e1ad44bfde8cb12359111ef5ad68be 100644 (file)
@@ -717,7 +717,7 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder)
        struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
        struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
        struct mipi_dsi_device *device = dsi->device;
-       union phy_configure_opts opts = { };
+       union phy_configure_opts opts = { };
        struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
        u16 delay;
        int err;
index d4ce9bab8c7e61369ab52bc6617d3a6fddeb3610..3221a707e07366c68c03e2945a72b7ddd5298c20 100644 (file)
@@ -379,9 +379,17 @@ static struct drm_crtc_state *tidss_crtc_duplicate_state(struct drm_crtc *crtc)
        return &state->base;
 }
 
+static void tidss_crtc_destroy(struct drm_crtc *crtc)
+{
+       struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
+
+       drm_crtc_cleanup(crtc);
+       kfree(tcrtc);
+}
+
 static const struct drm_crtc_funcs tidss_crtc_funcs = {
        .reset = tidss_crtc_reset,
-       .destroy = drm_crtc_cleanup,
+       .destroy = tidss_crtc_destroy,
        .set_config = drm_atomic_helper_set_config,
        .page_flip = drm_atomic_helper_page_flip,
        .atomic_duplicate_state = tidss_crtc_duplicate_state,
@@ -400,7 +408,7 @@ struct tidss_crtc *tidss_crtc_create(struct tidss_device *tidss,
        bool has_ctm = tidss->feat->vp_feat.color.has_ctm;
        int ret;
 
-       tcrtc = devm_kzalloc(tidss->dev, sizeof(*tcrtc), GFP_KERNEL);
+       tcrtc = kzalloc(sizeof(*tcrtc), GFP_KERNEL);
        if (!tcrtc)
                return ERR_PTR(-ENOMEM);
 
@@ -411,8 +419,10 @@ struct tidss_crtc *tidss_crtc_create(struct tidss_device *tidss,
 
        ret = drm_crtc_init_with_planes(&tidss->ddev, crtc, primary,
                                        NULL, &tidss_crtc_funcs, NULL);
-       if (ret < 0)
+       if (ret < 0) {
+               kfree(tcrtc);
                return ERR_PTR(ret);
+       }
 
        drm_crtc_helper_add(crtc, &tidss_crtc_helper_funcs);
 
index 83785b0a66a9d28740fed7848b6559bbb99dce0f..30bf2a65949cff34f14f5efb6abdf63d71ca71cc 100644 (file)
@@ -55,12 +55,18 @@ static int tidss_encoder_atomic_check(struct drm_encoder *encoder,
        return 0;
 }
 
+static void tidss_encoder_destroy(struct drm_encoder *encoder)
+{
+       drm_encoder_cleanup(encoder);
+       kfree(encoder);
+}
+
 static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
        .atomic_check = tidss_encoder_atomic_check,
 };
 
 static const struct drm_encoder_funcs encoder_funcs = {
-       .destroy = drm_encoder_cleanup,
+       .destroy = tidss_encoder_destroy,
 };
 
 struct drm_encoder *tidss_encoder_create(struct tidss_device *tidss,
@@ -69,7 +75,7 @@ struct drm_encoder *tidss_encoder_create(struct tidss_device *tidss,
        struct drm_encoder *enc;
        int ret;
 
-       enc = devm_kzalloc(tidss->dev, sizeof(*enc), GFP_KERNEL);
+       enc = kzalloc(sizeof(*enc), GFP_KERNEL);
        if (!enc)
                return ERR_PTR(-ENOMEM);
 
@@ -77,8 +83,10 @@ struct drm_encoder *tidss_encoder_create(struct tidss_device *tidss,
 
        ret = drm_encoder_init(&tidss->ddev, enc, &encoder_funcs,
                               encoder_type, NULL);
-       if (ret < 0)
+       if (ret < 0) {
+               kfree(enc);
                return ERR_PTR(ret);
+       }
 
        drm_encoder_helper_add(enc, &encoder_helper_funcs);
 
index ff99b2dd4a17f8681ee0c9f7aa6ecfa2b6837803..798488948fc539716bfe53a5316583b1360ee5ee 100644 (file)
@@ -141,6 +141,14 @@ static void tidss_plane_atomic_disable(struct drm_plane *plane,
        dispc_plane_enable(tidss->dispc, tplane->hw_plane_id, false);
 }
 
+static void drm_plane_destroy(struct drm_plane *plane)
+{
+       struct tidss_plane *tplane = to_tidss_plane(plane);
+
+       drm_plane_cleanup(plane);
+       kfree(tplane);
+}
+
 static const struct drm_plane_helper_funcs tidss_plane_helper_funcs = {
        .atomic_check = tidss_plane_atomic_check,
        .atomic_update = tidss_plane_atomic_update,
@@ -151,7 +159,7 @@ static const struct drm_plane_funcs tidss_plane_funcs = {
        .update_plane = drm_atomic_helper_update_plane,
        .disable_plane = drm_atomic_helper_disable_plane,
        .reset = drm_atomic_helper_plane_reset,
-       .destroy = drm_plane_cleanup,
+       .destroy = drm_plane_destroy,
        .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
 };
@@ -175,7 +183,7 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
                           BIT(DRM_MODE_BLEND_COVERAGE));
        int ret;
 
-       tplane = devm_kzalloc(tidss->dev, sizeof(*tplane), GFP_KERNEL);
+       tplane = kzalloc(sizeof(*tplane), GFP_KERNEL);
        if (!tplane)
                return ERR_PTR(-ENOMEM);
 
@@ -190,7 +198,7 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
                                       formats, num_formats,
                                       NULL, type, NULL);
        if (ret < 0)
-               return ERR_PTR(ret);
+               goto err;
 
        drm_plane_helper_add(&tplane->plane, &tidss_plane_helper_funcs);
 
@@ -203,15 +211,19 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
                                                default_encoding,
                                                default_range);
        if (ret)
-               return ERR_PTR(ret);
+               goto err;
 
        ret = drm_plane_create_alpha_property(&tplane->plane);
        if (ret)
-               return ERR_PTR(ret);
+               goto err;
 
        ret = drm_plane_create_blend_mode_property(&tplane->plane, blend_modes);
        if (ret)
-               return ERR_PTR(ret);
+               goto err;
 
        return tplane;
+
+err:
+       kfree(tplane);
+       return ERR_PTR(ret);
 }
index c1824bdf2418218793b04c0e11ab0e7fefdbc3fa..7879ff58236f1472afb38d55de3ec1782e41fd7b 100644 (file)
@@ -221,6 +221,7 @@ struct virtio_gpu_fpriv {
 /* virtio_ioctl.c */
 #define DRM_VIRTIO_NUM_IOCTLS 10
 extern struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS];
+void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file);
 
 /* virtio_kms.c */
 int virtio_gpu_init(struct drm_device *dev);
index 0d6152c99a27190f538be52eb777d7d4ce973cf8..f0d5a897467752aedbc1ba0ee8dbae6380da3bd2 100644 (file)
@@ -39,6 +39,9 @@ int virtio_gpu_gem_create(struct drm_file *file,
        int ret;
        u32 handle;
 
+       if (vgdev->has_virgl_3d)
+               virtio_gpu_create_context(dev, file);
+
        ret = virtio_gpu_object_create(vgdev, params, &obj, NULL);
        if (ret < 0)
                return ret;
index 336cc9143205de921c4307f076903530abe58e97..512daff920387e5103e37743f2f441641a762dd9 100644 (file)
 
 #include <linux/file.h>
 #include <linux/sync_file.h>
+#include <linux/uaccess.h>
 
 #include <drm/drm_file.h>
 #include <drm/virtgpu_drm.h>
 
 #include "virtgpu_drv.h"
 
-static void virtio_gpu_create_context(struct drm_device *dev,
-                                     struct drm_file *file)
+void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file)
 {
        struct virtio_gpu_device *vgdev = dev->dev_private;
        struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
index 023a030ca7b99e7cba5d2fea111df0d434df852f..0a5c8cf409fb854f65b09a2d04e44b39c0fe79a4 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <linux/virtio.h>
 #include <linux/virtio_config.h>
+#include <linux/virtio_ring.h>
 
 #include <drm/drm_file.h>
 
@@ -52,14 +53,6 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work)
                      events_clear, &events_clear);
 }
 
-static void virtio_gpu_context_destroy(struct virtio_gpu_device *vgdev,
-                                     uint32_t ctx_id)
-{
-       virtio_gpu_cmd_context_destroy(vgdev, ctx_id);
-       virtio_gpu_notify(vgdev);
-       ida_free(&vgdev->ctx_id_ida, ctx_id - 1);
-}
-
 static void virtio_gpu_init_vq(struct virtio_gpu_queue *vgvq,
                               void (*work_func)(struct work_struct *work))
 {
@@ -274,14 +267,17 @@ int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file)
 void virtio_gpu_driver_postclose(struct drm_device *dev, struct drm_file *file)
 {
        struct virtio_gpu_device *vgdev = dev->dev_private;
-       struct virtio_gpu_fpriv *vfpriv;
+       struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
 
        if (!vgdev->has_virgl_3d)
                return;
 
-       vfpriv = file->driver_priv;
+       if (vfpriv->context_created) {
+               virtio_gpu_cmd_context_destroy(vgdev, vfpriv->ctx_id);
+               virtio_gpu_notify(vgdev);
+       }
 
-       virtio_gpu_context_destroy(vgdev, vfpriv->ctx_id);
+       ida_free(&vgdev->ctx_id_ida, vfpriv->ctx_id - 1);
        mutex_destroy(&vfpriv->context_lock);
        kfree(vfpriv);
        file->driver_priv = NULL;
index 7c89edbd6c5a8ae224eeca99b7b7e3440b238e11..34f07371716de2da9a25678aa99959099697a3dc 100644 (file)
@@ -1155,6 +1155,7 @@ config HID_ALPS
 config HID_MCP2221
        tristate "Microchip MCP2221 HID USB-to-I2C/SMbus host support"
        depends on USB_HID && I2C
+       depends on GPIOLIB
        ---help---
        Provides I2C and SMBUS host adapter functionality over USB-HID
        through MCP2221 device.
index fa704153cb00d5f7fa7d0185acd1f953fdd37754..b2ad319a74b9ac228183779324371cc3fd5b7cb7 100644 (file)
@@ -802,6 +802,7 @@ static int alps_probe(struct hid_device *hdev, const struct hid_device_id *id)
                break;
        case HID_DEVICE_ID_ALPS_U1_DUAL:
        case HID_DEVICE_ID_ALPS_U1:
+       case HID_DEVICE_ID_ALPS_U1_UNICORN_LEGACY:
                data->dev_type = U1;
                break;
        default:
index b18b13147a6fe5405399ef4f47b58931058eb3ae..1c71a1aa76b22b4f132004169839e2f91659e3a0 100644 (file)
 #define HID_DEVICE_ID_ALPS_U1_DUAL_PTP 0x121F
 #define HID_DEVICE_ID_ALPS_U1_DUAL_3BTN_PTP    0x1220
 #define HID_DEVICE_ID_ALPS_U1          0x1215
+#define HID_DEVICE_ID_ALPS_U1_UNICORN_LEGACY         0x121E
 #define HID_DEVICE_ID_ALPS_T4_BTNLESS  0x120C
 #define HID_DEVICE_ID_ALPS_1222                0x1222
 
-
 #define USB_VENDOR_ID_AMI              0x046b
 #define USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE      0xff10
 
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349      0x7349
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7      0x73f7
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001      0xa001
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C002      0xc002
 
 #define USB_VENDOR_ID_ELAN             0x04f3
 #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W        0x0401
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2      0xc218
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2    0xc219
 #define USB_DEVICE_ID_LOGITECH_G15_LCD         0xc222
+#define USB_DEVICE_ID_LOGITECH_G11             0xc225
 #define USB_DEVICE_ID_LOGITECH_G15_V2_LCD      0xc227
 #define USB_DEVICE_ID_LOGITECH_G510            0xc22d
 #define USB_DEVICE_ID_LOGITECH_G510_USB_AUDIO  0xc22e
 #define USB_DEVICE_ID_SYMBOL_SCANNER_2 0x1300
 #define USB_DEVICE_ID_SYMBOL_SCANNER_3 0x1200
 
+#define I2C_VENDOR_ID_SYNAPTICS     0x06cb
+#define I2C_PRODUCT_ID_SYNAPTICS_SYNA2393   0x7a13
+
 #define USB_VENDOR_ID_SYNAPTICS                0x06cb
 #define USB_DEVICE_ID_SYNAPTICS_TP     0x0001
 #define USB_DEVICE_ID_SYNAPTICS_INT_TP 0x0002
 #define USB_DEVICE_ID_SYNAPTICS_LTS2   0x1d10
 #define USB_DEVICE_ID_SYNAPTICS_HD     0x0ac3
 #define USB_DEVICE_ID_SYNAPTICS_QUAD_HD        0x1ac3
+#define USB_DEVICE_ID_SYNAPTICS_DELL_K12A      0x2819
 #define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012       0x2968
 #define USB_DEVICE_ID_SYNAPTICS_TP_V103        0x5710
 #define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5   0x81a7
index ad4b5412a9f493f858134f33b7165b70bec92211..ef0cbcd7540d564e91e8f70c03aa947a410ce1c9 100644 (file)
@@ -872,6 +872,10 @@ error_hw_stop:
 }
 
 static const struct hid_device_id lg_g15_devices[] = {
+       /* The G11 is a G15 without the LCD, treat it as a G15 */
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+               USB_DEVICE_ID_LOGITECH_G11),
+               .driver_data = LG_G15 },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
                         USB_DEVICE_ID_LOGITECH_G15_LCD),
                .driver_data = LG_G15 },
index 362805ddf377736927fa95493186698a8d5fad0f..03c720b47306320c6ed32df1e0da97f2cd61e403 100644 (file)
@@ -1922,6 +1922,9 @@ static const struct hid_device_id mt_devices[] = {
        { .driver_data = MT_CLS_EGALAX_SERIAL,
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
+       { .driver_data = MT_CLS_EGALAX,
+               MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
+                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C002) },
 
        /* Elitegroup panel */
        { .driver_data = MT_CLS_SERIAL,
index ebec818344aff5ca50164cef91f785e81d47b6b1..e4cb543de0cdc3524a33ac068536858e328a2bcc 100644 (file)
@@ -163,6 +163,7 @@ static const struct hid_device_id hid_quirks[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2), HID_QUIRK_NO_INIT_REPORTS },
        { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD), HID_QUIRK_NO_INIT_REPORTS },
        { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103), HID_QUIRK_NO_INIT_REPORTS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DELL_K12A), HID_QUIRK_NO_INIT_REPORTS },
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD), HID_QUIRK_BADPAD },
        { HID_USB_DEVICE(USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS), HID_QUIRK_MULTI_INPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882), HID_QUIRK_NOGET },
index 009000c5d55cddfaad101f1b33d5b37497e0f176..294c84e136d72686842516c9422ece66739b724e 100644 (file)
@@ -177,6 +177,8 @@ static const struct i2c_hid_quirks {
                 I2C_HID_QUIRK_BOGUS_IRQ },
        { USB_VENDOR_ID_ALPS_JP, HID_ANY_ID,
                 I2C_HID_QUIRK_RESET_ON_RESUME },
+       { I2C_VENDOR_ID_SYNAPTICS, I2C_PRODUCT_ID_SYNAPTICS_SYNA2393,
+                I2C_HID_QUIRK_RESET_ON_RESUME },
        { USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720,
                I2C_HID_QUIRK_BAD_INPUT_SIZE },
        { 0, 0 }
index c7bc9db5b192e201d437f3adc1959224a1e11bee..17a638f150824a14ca837cac5fa298c52caf0c73 100644 (file)
@@ -682,16 +682,21 @@ static int usbhid_open(struct hid_device *hid)
        struct usbhid_device *usbhid = hid->driver_data;
        int res;
 
+       mutex_lock(&usbhid->mutex);
+
        set_bit(HID_OPENED, &usbhid->iofl);
 
-       if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
-               return 0;
+       if (hid->quirks & HID_QUIRK_ALWAYS_POLL) {
+               res = 0;
+               goto Done;
+       }
 
        res = usb_autopm_get_interface(usbhid->intf);
        /* the device must be awake to reliably request remote wakeup */
        if (res < 0) {
                clear_bit(HID_OPENED, &usbhid->iofl);
-               return -EIO;
+               res = -EIO;
+               goto Done;
        }
 
        usbhid->intf->needs_remote_wakeup = 1;
@@ -725,6 +730,9 @@ static int usbhid_open(struct hid_device *hid)
                msleep(50);
 
        clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
+
+ Done:
+       mutex_unlock(&usbhid->mutex);
        return res;
 }
 
@@ -732,6 +740,8 @@ static void usbhid_close(struct hid_device *hid)
 {
        struct usbhid_device *usbhid = hid->driver_data;
 
+       mutex_lock(&usbhid->mutex);
+
        /*
         * Make sure we don't restart data acquisition due to
         * a resumption we no longer care about by avoiding racing
@@ -743,12 +753,13 @@ static void usbhid_close(struct hid_device *hid)
                clear_bit(HID_IN_POLLING, &usbhid->iofl);
        spin_unlock_irq(&usbhid->lock);
 
-       if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
-               return;
+       if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) {
+               hid_cancel_delayed_stuff(usbhid);
+               usb_kill_urb(usbhid->urbin);
+               usbhid->intf->needs_remote_wakeup = 0;
+       }
 
-       hid_cancel_delayed_stuff(usbhid);
-       usb_kill_urb(usbhid->urbin);
-       usbhid->intf->needs_remote_wakeup = 0;
+       mutex_unlock(&usbhid->mutex);
 }
 
 /*
@@ -1057,6 +1068,8 @@ static int usbhid_start(struct hid_device *hid)
        unsigned int n, insize = 0;
        int ret;
 
+       mutex_lock(&usbhid->mutex);
+
        clear_bit(HID_DISCONNECTED, &usbhid->iofl);
 
        usbhid->bufsize = HID_MIN_BUFFER_SIZE;
@@ -1177,6 +1190,8 @@ static int usbhid_start(struct hid_device *hid)
                usbhid_set_leds(hid);
                device_set_wakeup_enable(&dev->dev, 1);
        }
+
+       mutex_unlock(&usbhid->mutex);
        return 0;
 
 fail:
@@ -1187,6 +1202,7 @@ fail:
        usbhid->urbout = NULL;
        usbhid->urbctrl = NULL;
        hid_free_buffers(dev, hid);
+       mutex_unlock(&usbhid->mutex);
        return ret;
 }
 
@@ -1202,6 +1218,8 @@ static void usbhid_stop(struct hid_device *hid)
                usbhid->intf->needs_remote_wakeup = 0;
        }
 
+       mutex_lock(&usbhid->mutex);
+
        clear_bit(HID_STARTED, &usbhid->iofl);
        spin_lock_irq(&usbhid->lock);   /* Sync with error and led handlers */
        set_bit(HID_DISCONNECTED, &usbhid->iofl);
@@ -1222,6 +1240,8 @@ static void usbhid_stop(struct hid_device *hid)
        usbhid->urbout = NULL;
 
        hid_free_buffers(hid_to_usb_dev(hid), hid);
+
+       mutex_unlock(&usbhid->mutex);
 }
 
 static int usbhid_power(struct hid_device *hid, int lvl)
@@ -1382,6 +1402,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
        INIT_WORK(&usbhid->reset_work, hid_reset);
        timer_setup(&usbhid->io_retry, hid_retry_timeout, 0);
        spin_lock_init(&usbhid->lock);
+       mutex_init(&usbhid->mutex);
 
        ret = hid_add_device(hid);
        if (ret) {
index 8620408bd7afc8e2fe047f36b0420acd4db5d76d..75fe85d3d27a0a25d6f5aad7123bcf527ae13261 100644 (file)
@@ -80,6 +80,7 @@ struct usbhid_device {
        dma_addr_t outbuf_dma;                                          /* Output buffer dma */
        unsigned long last_out;                                                 /* record of last output for timeouts */
 
+       struct mutex mutex;                                             /* start/stop/open/close */
        spinlock_t lock;                                                /* fifo spinlock */
        unsigned long iofl;                                             /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
        struct timer_list io_retry;                                     /* Retry timer */
index 5ded94b7bf684b87359549444c6f1cdddc17bbf2..cd71e713394464632e4c2fa6e11de57eaccab455 100644 (file)
@@ -319,9 +319,11 @@ static void wacom_feature_mapping(struct hid_device *hdev,
                        data[0] = field->report->id;
                        ret = wacom_get_report(hdev, HID_FEATURE_REPORT,
                                               data, n, WAC_CMD_RETRIES);
-                       if (ret == n) {
+                       if (ret == n && features->type == HID_GENERIC) {
                                ret = hid_report_raw_event(hdev,
                                        HID_FEATURE_REPORT, data, n, 0);
+                       } else if (ret == 2 && features->type != HID_GENERIC) {
+                               features->touch_max = data[1];
                        } else {
                                features->touch_max = 16;
                                hid_warn(hdev, "wacom_feature_mapping: "
index d99a9d407671c88ea96decdd0e561c6f8784685a..1c96809b51c909431255eb912d04156d7f5fd8aa 100644 (file)
@@ -1427,11 +1427,13 @@ static void wacom_intuos_pro2_bt_pad(struct wacom_wac *wacom)
 {
        struct input_dev *pad_input = wacom->pad_input;
        unsigned char *data = wacom->data;
+       int nbuttons = wacom->features.numbered_buttons;
 
-       int buttons = data[282] | ((data[281] & 0x40) << 2);
+       int expresskeys = data[282];
+       int center = (data[281] & 0x40) >> 6;
        int ring = data[285] & 0x7F;
        bool ringstatus = data[285] & 0x80;
-       bool prox = buttons || ringstatus;
+       bool prox = expresskeys || center || ringstatus;
 
        /* Fix touchring data: userspace expects 0 at left and increasing clockwise */
        ring = 71 - ring;
@@ -1439,7 +1441,8 @@ static void wacom_intuos_pro2_bt_pad(struct wacom_wac *wacom)
        if (ring > 71)
                ring -= 72;
 
-       wacom_report_numbered_buttons(pad_input, 9, buttons);
+       wacom_report_numbered_buttons(pad_input, nbuttons,
+                                      expresskeys | (center << (nbuttons - 1)));
 
        input_report_abs(pad_input, ABS_WHEEL, ringstatus ? ring : 0);
 
@@ -2637,9 +2640,25 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev,
                        case HID_DG_TIPSWITCH:
                                hid_data->last_slot_field = equivalent_usage;
                                break;
+                       case HID_DG_CONTACTCOUNT:
+                               hid_data->cc_report = report->id;
+                               hid_data->cc_index = i;
+                               hid_data->cc_value_index = j;
+                               break;
                        }
                }
        }
+
+       if (hid_data->cc_report != 0 &&
+           hid_data->cc_index >= 0) {
+               struct hid_field *field = report->field[hid_data->cc_index];
+               int value = field->value[hid_data->cc_value_index];
+               if (value)
+                       hid_data->num_expected = value;
+       }
+       else {
+               hid_data->num_expected = wacom_wac->features.touch_max;
+       }
 }
 
 static void wacom_wac_finger_report(struct hid_device *hdev,
@@ -2649,7 +2668,6 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
        struct wacom_wac *wacom_wac = &wacom->wacom_wac;
        struct input_dev *input = wacom_wac->touch_input;
        unsigned touch_max = wacom_wac->features.touch_max;
-       struct hid_data *hid_data = &wacom_wac->hid_data;
 
        /* If more packets of data are expected, give us a chance to
         * process them rather than immediately syncing a partial
@@ -2663,7 +2681,6 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
 
        input_sync(input);
        wacom_wac->hid_data.num_received = 0;
-       hid_data->num_expected = 0;
 
        /* keep touch state for pen event */
        wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom_wac);
@@ -2738,73 +2755,12 @@ static void wacom_report_events(struct hid_device *hdev,
        }
 }
 
-static void wacom_set_num_expected(struct hid_device *hdev,
-                                  struct hid_report *report,
-                                  int collection_index,
-                                  struct hid_field *field,
-                                  int field_index)
-{
-       struct wacom *wacom = hid_get_drvdata(hdev);
-       struct wacom_wac *wacom_wac = &wacom->wacom_wac;
-       struct hid_data *hid_data = &wacom_wac->hid_data;
-       unsigned int original_collection_level =
-               hdev->collection[collection_index].level;
-       bool end_collection = false;
-       int i;
-
-       if (hid_data->num_expected)
-               return;
-
-       // find the contact count value for this segment
-       for (i = field_index; i < report->maxfield && !end_collection; i++) {
-               struct hid_field *field = report->field[i];
-               unsigned int field_level =
-                       hdev->collection[field->usage[0].collection_index].level;
-               unsigned int j;
-
-               if (field_level != original_collection_level)
-                       continue;
-
-               for (j = 0; j < field->maxusage; j++) {
-                       struct hid_usage *usage = &field->usage[j];
-
-                       if (usage->collection_index != collection_index) {
-                               end_collection = true;
-                               break;
-                       }
-                       if (wacom_equivalent_usage(usage->hid) == HID_DG_CONTACTCOUNT) {
-                               hid_data->cc_report = report->id;
-                               hid_data->cc_index = i;
-                               hid_data->cc_value_index = j;
-
-                               if (hid_data->cc_report != 0 &&
-                                   hid_data->cc_index >= 0) {
-
-                                       struct hid_field *field =
-                                               report->field[hid_data->cc_index];
-                                       int value =
-                                               field->value[hid_data->cc_value_index];
-
-                                       if (value)
-                                               hid_data->num_expected = value;
-                               }
-                       }
-               }
-       }
-
-       if (hid_data->cc_report == 0 || hid_data->cc_index < 0)
-               hid_data->num_expected = wacom_wac->features.touch_max;
-}
-
 static int wacom_wac_collection(struct hid_device *hdev, struct hid_report *report,
                         int collection_index, struct hid_field *field,
                         int field_index)
 {
        struct wacom *wacom = hid_get_drvdata(hdev);
 
-       if (WACOM_FINGER_FIELD(field))
-               wacom_set_num_expected(hdev, report, collection_index, field,
-                                      field_index);
        wacom_report_events(hdev, report, collection_index, field_index);
 
        /*
index 0370364169c4ec2ebc09218395f41615b9f49cd5..501c43c5851dcc503edaff6c19cfc5b0d4df4a66 100644 (file)
@@ -839,6 +839,9 @@ void vmbus_initiate_unload(bool crash)
 {
        struct vmbus_channel_message_header hdr;
 
+       if (xchg(&vmbus_connection.conn_state, DISCONNECTED) == DISCONNECTED)
+               return;
+
        /* Pre-Win2012R2 hosts don't support reconnect */
        if (vmbus_proto_version < VERSION_WIN8_1)
                return;
index 6098e0cbdb4b0ad36f22fd214d2f0f59d08fec31..533c8b82b344d1b035a2cc78ff80476beab87701 100644 (file)
@@ -184,11 +184,7 @@ void hv_synic_enable_regs(unsigned int cpu)
 
        shared_sint.vector = HYPERVISOR_CALLBACK_VECTOR;
        shared_sint.masked = false;
-       if (ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED)
-               shared_sint.auto_eoi = false;
-       else
-               shared_sint.auto_eoi = true;
-
+       shared_sint.auto_eoi = hv_recommend_using_aeoi();
        hv_set_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
 
        /* Enable the global synic bit */
index 8a28785735820b61f6a85adca84f61022c133f3a..ccf752b6659a773584f97b133f0cb1155a1bcfc4 100644 (file)
@@ -11,7 +11,7 @@
 
 #include "hyperv_vmbus.h"
 
-struct dentry *hv_debug_root;
+static struct dentry *hv_debug_root;
 
 static int hv_debugfs_delay_get(void *data, u64 *val)
 {
index e70783e33680f1ec2ffa6b2bf46b266093907e57..f9d14db980cb4d2b65158bdd6ece3c2f5e02516e 100644 (file)
@@ -286,8 +286,8 @@ TRACE_EVENT(vmbus_send_tl_connect_request,
                    __field(int, ret)
                    ),
            TP_fast_assign(
-                   memcpy(__entry->guest_id, &msg->guest_endpoint_id.b, 16);
-                   memcpy(__entry->host_id, &msg->host_service_id.b, 16);
+                   export_guid(__entry->guest_id, &msg->guest_endpoint_id);
+                   export_guid(__entry->host_id, &msg->host_service_id);
                    __entry->ret = ret;
                    ),
            TP_printk("sending guest_endpoint_id %pUl, host_service_id %pUl, "
index f5fa3b3c9baf762c8c02422fbffaa88d859e865b..70b30e223a578be42378342891541b560bae627b 100644 (file)
@@ -292,7 +292,7 @@ struct vmbus_msginfo {
        struct list_head msglist_entry;
 
        /* The message itself */
-       unsigned char msg[0];
+       unsigned char msg[];
 };
 
 
index 029378c27421d1b30a168dbe25c1ba13c4c8de57..e06c6b9555cfb6800bf67910730b79f5870359ed 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/kdebug.h>
 #include <linux/efi.h>
 #include <linux/random.h>
+#include <linux/kernel.h>
 #include <linux/syscore_ops.h>
 #include <clocksource/hyperv_timer.h>
 #include "hyperv_vmbus.h"
@@ -48,14 +49,35 @@ static int hyperv_cpuhp_online;
 
 static void *hv_panic_page;
 
+/*
+ * Boolean to control whether to report panic messages over Hyper-V.
+ *
+ * It can be set via /proc/sys/kernel/hyperv/record_panic_msg
+ */
+static int sysctl_record_panic_msg = 1;
+
+static int hyperv_report_reg(void)
+{
+       return !sysctl_record_panic_msg || !hv_panic_page;
+}
+
 static int hyperv_panic_event(struct notifier_block *nb, unsigned long val,
                              void *args)
 {
        struct pt_regs *regs;
 
-       regs = current_pt_regs();
+       vmbus_initiate_unload(true);
 
-       hyperv_report_panic(regs, val);
+       /*
+        * Hyper-V should be notified only once about a panic.  If we will be
+        * doing hyperv_report_panic_msg() later with kmsg data, don't do
+        * the notification here.
+        */
+       if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE
+           && hyperv_report_reg()) {
+               regs = current_pt_regs();
+               hyperv_report_panic(regs, val, false);
+       }
        return NOTIFY_DONE;
 }
 
@@ -65,7 +87,13 @@ static int hyperv_die_event(struct notifier_block *nb, unsigned long val,
        struct die_args *die = (struct die_args *)args;
        struct pt_regs *regs = die->regs;
 
-       hyperv_report_panic(regs, val);
+       /*
+        * Hyper-V should be notified only once about a panic.  If we will be
+        * doing hyperv_report_panic_msg() later with kmsg data, don't do
+        * the notification here.
+        */
+       if (hyperv_report_reg())
+               hyperv_report_panic(regs, val, true);
        return NOTIFY_DONE;
 }
 
@@ -950,6 +978,9 @@ static int vmbus_resume(struct device *child_device)
 
        return drv->resume(dev);
 }
+#else
+#define vmbus_suspend NULL
+#define vmbus_resume NULL
 #endif /* CONFIG_PM_SLEEP */
 
 /*
@@ -969,11 +1000,22 @@ static void vmbus_device_release(struct device *device)
 }
 
 /*
- * Note: we must use SET_NOIRQ_SYSTEM_SLEEP_PM_OPS rather than
- * SET_SYSTEM_SLEEP_PM_OPS: see the comment before vmbus_bus_pm.
+ * Note: we must use the "noirq" ops: see the comment before vmbus_bus_pm.
+ *
+ * suspend_noirq/resume_noirq are set to NULL to support Suspend-to-Idle: we
+ * shouldn't suspend the vmbus devices upon Suspend-to-Idle, otherwise there
+ * is no way to wake up a Generation-2 VM.
+ *
+ * The other 4 ops are for hibernation.
  */
+
 static const struct dev_pm_ops vmbus_pm = {
-       SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(vmbus_suspend, vmbus_resume)
+       .suspend_noirq  = NULL,
+       .resume_noirq   = NULL,
+       .freeze_noirq   = vmbus_suspend,
+       .thaw_noirq     = vmbus_resume,
+       .poweroff_noirq = vmbus_suspend,
+       .restore_noirq  = vmbus_resume,
 };
 
 /* The one and only one */
@@ -1252,13 +1294,6 @@ static void vmbus_isr(void)
        add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0);
 }
 
-/*
- * Boolean to control whether to report panic messages over Hyper-V.
- *
- * It can be set via /proc/sys/kernel/hyperv/record_panic_msg
- */
-static int sysctl_record_panic_msg = 1;
-
 /*
  * Callback from kmsg_dump. Grab as much as possible from the end of the kmsg
  * buffer and call into Hyper-V to transfer the data.
@@ -1382,19 +1417,29 @@ static int vmbus_bus_init(void)
                        hv_panic_page = (void *)hv_alloc_hyperv_zeroed_page();
                        if (hv_panic_page) {
                                ret = kmsg_dump_register(&hv_kmsg_dumper);
-                               if (ret)
+                               if (ret) {
                                        pr_err("Hyper-V: kmsg dump register "
                                                "error 0x%x\n", ret);
+                                       hv_free_hyperv_page(
+                                           (unsigned long)hv_panic_page);
+                                       hv_panic_page = NULL;
+                               }
                        } else
                                pr_err("Hyper-V: panic message page memory "
                                        "allocation failed");
                }
 
                register_die_notifier(&hyperv_die_block);
-               atomic_notifier_chain_register(&panic_notifier_list,
-                                              &hyperv_panic_block);
        }
 
+       /*
+        * Always register the panic notifier because we need to unload
+        * the VMbus channel connection to prevent any VMbus
+        * activity after the VM panics.
+        */
+       atomic_notifier_chain_register(&panic_notifier_list,
+                              &hyperv_panic_block);
+
        vmbus_request_offers();
 
        return 0;
@@ -1407,7 +1452,6 @@ err_alloc:
        hv_remove_vmbus_irq();
 
        bus_unregister(&hv_bus);
-       hv_free_hyperv_page((unsigned long)hv_panic_page);
        unregister_sysctl_table(hv_ctl_table_hdr);
        hv_ctl_table_hdr = NULL;
        return ret;
@@ -2204,8 +2248,6 @@ static int vmbus_bus_suspend(struct device *dev)
 
        vmbus_initiate_unload(false);
 
-       vmbus_connection.conn_state = DISCONNECTED;
-
        /* Reset the event for the next resume. */
        reinit_completion(&vmbus_connection.ready_for_resume_event);
 
@@ -2253,6 +2295,9 @@ static int vmbus_bus_resume(struct device *dev)
 
        return 0;
 }
+#else
+#define vmbus_bus_suspend NULL
+#define vmbus_bus_resume NULL
 #endif /* CONFIG_PM_SLEEP */
 
 static const struct acpi_device_id vmbus_acpi_device_ids[] = {
@@ -2263,16 +2308,24 @@ static const struct acpi_device_id vmbus_acpi_device_ids[] = {
 MODULE_DEVICE_TABLE(acpi, vmbus_acpi_device_ids);
 
 /*
- * Note: we must use SET_NOIRQ_SYSTEM_SLEEP_PM_OPS rather than
- * SET_SYSTEM_SLEEP_PM_OPS, otherwise NIC SR-IOV can not work, because the
- * "pci_dev_pm_ops" uses the "noirq" callbacks: in the resume path, the
- * pci "noirq" restore callback runs before "non-noirq" callbacks (see
+ * Note: we must use the "no_irq" ops, otherwise hibernation can not work with
+ * PCI device assignment, because "pci_dev_pm_ops" uses the "noirq" ops: in
+ * the resume path, the pci "noirq" restore op runs before "non-noirq" op (see
  * resume_target_kernel() -> dpm_resume_start(), and hibernation_restore() ->
  * dpm_resume_end()). This means vmbus_bus_resume() and the pci-hyperv's
- * resume callback must also run via the "noirq" callbacks.
+ * resume callback must also run via the "noirq" ops.
+ *
+ * Set suspend_noirq/resume_noirq to NULL for Suspend-to-Idle: see the comment
+ * earlier in this file before vmbus_pm.
  */
+
 static const struct dev_pm_ops vmbus_bus_pm = {
-       SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(vmbus_bus_suspend, vmbus_bus_resume)
+       .suspend_noirq  = NULL,
+       .resume_noirq   = NULL,
+       .freeze_noirq   = vmbus_bus_suspend,
+       .thaw_noirq     = vmbus_bus_resume,
+       .poweroff_noirq = vmbus_bus_suspend,
+       .restore_noirq  = vmbus_bus_resume
 };
 
 static struct acpi_driver vmbus_acpi_driver = {
@@ -2289,7 +2342,6 @@ static void hv_kexec_handler(void)
 {
        hv_stimer_global_cleanup();
        vmbus_initiate_unload(false);
-       vmbus_connection.conn_state = DISCONNECTED;
        /* Make sure conn_state is set as hv_synic_cleanup checks for it */
        mb();
        cpuhp_remove_state(hyperv_cpuhp_online);
@@ -2306,7 +2358,6 @@ static void hv_crash_handler(struct pt_regs *regs)
         * doing the cleanup for current CPU only. This should be sufficient
         * for kdump.
         */
-       vmbus_connection.conn_state = DISCONNECTED;
        cpu = smp_processor_id();
        hv_stimer_cleanup(cpu);
        hv_synic_disable_regs(cpu);
index 05a30832c6ba0a3c62411cb79d5375d5ff8b00a8..4c62f900bf7e8f6ae246d5a8b8aacf3b7d65a719 100644 (file)
@@ -412,7 +412,7 @@ config SENSORS_DRIVETEMP
          hard disk drives.
 
          This driver can also be built as a module. If so, the module
-         will be called satatemp.
+         will be called drivetemp.
 
 config SENSORS_DS620
        tristate "Dallas Semiconductor DS620"
index 370d0c74eb012e38ebfcfffbafeeb7ce7f50705f..9179460c2d9d586e1358859a485234126aa7bc8c 100644 (file)
@@ -264,12 +264,18 @@ static int drivetemp_get_scttemp(struct drivetemp_data *st, u32 attr, long *val)
                return err;
        switch (attr) {
        case hwmon_temp_input:
+               if (!temp_is_valid(buf[SCT_STATUS_TEMP]))
+                       return -ENODATA;
                *val = temp_from_sct(buf[SCT_STATUS_TEMP]);
                break;
        case hwmon_temp_lowest:
+               if (!temp_is_valid(buf[SCT_STATUS_TEMP_LOWEST]))
+                       return -ENODATA;
                *val = temp_from_sct(buf[SCT_STATUS_TEMP_LOWEST]);
                break;
        case hwmon_temp_highest:
+               if (!temp_is_valid(buf[SCT_STATUS_TEMP_HIGHEST]))
+                       return -ENODATA;
                *val = temp_from_sct(buf[SCT_STATUS_TEMP_HIGHEST]);
                break;
        default:
index f2d81b0558e5695f871fff22a93c8ceaff902edd..e3f1ebee71306b6ee12f69a7ebf318027df7ef38 100644 (file)
@@ -506,7 +506,7 @@ static int jc42_probe(struct i2c_client *client, const struct i2c_device_id *id)
        }
        data->config = config;
 
-       hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
+       hwmon_dev = devm_hwmon_device_register_with_info(dev, "jc42",
                                                         data, &jc42_chip_info,
                                                         NULL);
        return PTR_ERR_OR_ZERO(hwmon_dev);
index 3f37d5d81fe40e8cdb3bb3f3bb17827fc9833ff4..9915578533bb9665df32ade0956d90e077fab531 100644 (file)
@@ -186,7 +186,7 @@ static long get_raw_temp(struct k10temp_data *data)
        return temp;
 }
 
-const char *k10temp_temp_label[] = {
+static const char *k10temp_temp_label[] = {
        "Tctl",
        "Tdie",
        "Tccd1",
@@ -199,12 +199,12 @@ const char *k10temp_temp_label[] = {
        "Tccd8",
 };
 
-const char *k10temp_in_label[] = {
+static const char *k10temp_in_label[] = {
        "Vcore",
        "Vsoc",
 };
 
-const char *k10temp_curr_label[] = {
+static const char *k10temp_curr_label[] = {
        "Icore",
        "Isoc",
 };
index 4d2315208bb5982f88ab04e489a39ef1baacd74d..0c622711ef7e0e926a20980961e98322d7663d9e 100644 (file)
 #define ISL68137_VOUT_AVS      0x30
 #define RAA_DMPVR2_READ_VMON   0xc8
 
-enum versions {
+enum chips {
        isl68137,
+       isl68220,
+       isl68221,
+       isl68222,
+       isl68223,
+       isl68224,
+       isl68225,
+       isl68226,
+       isl68227,
+       isl68229,
+       isl68233,
+       isl68239,
+       isl69222,
+       isl69223,
+       isl69224,
+       isl69225,
+       isl69227,
+       isl69228,
+       isl69234,
+       isl69236,
+       isl69239,
+       isl69242,
+       isl69243,
+       isl69247,
+       isl69248,
+       isl69254,
+       isl69255,
+       isl69256,
+       isl69259,
+       isl69260,
+       isl69268,
+       isl69269,
+       isl69298,
+       raa228000,
+       raa228004,
+       raa228006,
+       raa228228,
+       raa229001,
+       raa229004,
+};
+
+enum variants {
+       raa_dmpvr1_2rail,
        raa_dmpvr2_1rail,
        raa_dmpvr2_2rail,
        raa_dmpvr2_3rail,
@@ -186,7 +228,7 @@ static int isl68137_probe(struct i2c_client *client,
        memcpy(info, &raa_dmpvr_info, sizeof(*info));
 
        switch (id->driver_data) {
-       case isl68137:
+       case raa_dmpvr1_2rail:
                info->pages = 2;
                info->R[PSC_VOLTAGE_IN] = 3;
                info->func[0] &= ~PMBUS_HAVE_VMON;
@@ -224,11 +266,47 @@ static int isl68137_probe(struct i2c_client *client,
 }
 
 static const struct i2c_device_id raa_dmpvr_id[] = {
-       {"isl68137", isl68137},
-       {"raa_dmpvr2_1rail", raa_dmpvr2_1rail},
-       {"raa_dmpvr2_2rail", raa_dmpvr2_2rail},
-       {"raa_dmpvr2_3rail", raa_dmpvr2_3rail},
-       {"raa_dmpvr2_hv", raa_dmpvr2_hv},
+       {"isl68137", raa_dmpvr1_2rail},
+       {"isl68220", raa_dmpvr2_2rail},
+       {"isl68221", raa_dmpvr2_3rail},
+       {"isl68222", raa_dmpvr2_2rail},
+       {"isl68223", raa_dmpvr2_2rail},
+       {"isl68224", raa_dmpvr2_3rail},
+       {"isl68225", raa_dmpvr2_2rail},
+       {"isl68226", raa_dmpvr2_3rail},
+       {"isl68227", raa_dmpvr2_1rail},
+       {"isl68229", raa_dmpvr2_3rail},
+       {"isl68233", raa_dmpvr2_2rail},
+       {"isl68239", raa_dmpvr2_3rail},
+
+       {"isl69222", raa_dmpvr2_2rail},
+       {"isl69223", raa_dmpvr2_3rail},
+       {"isl69224", raa_dmpvr2_2rail},
+       {"isl69225", raa_dmpvr2_2rail},
+       {"isl69227", raa_dmpvr2_3rail},
+       {"isl69228", raa_dmpvr2_3rail},
+       {"isl69234", raa_dmpvr2_2rail},
+       {"isl69236", raa_dmpvr2_2rail},
+       {"isl69239", raa_dmpvr2_3rail},
+       {"isl69242", raa_dmpvr2_2rail},
+       {"isl69243", raa_dmpvr2_1rail},
+       {"isl69247", raa_dmpvr2_2rail},
+       {"isl69248", raa_dmpvr2_2rail},
+       {"isl69254", raa_dmpvr2_2rail},
+       {"isl69255", raa_dmpvr2_2rail},
+       {"isl69256", raa_dmpvr2_2rail},
+       {"isl69259", raa_dmpvr2_2rail},
+       {"isl69260", raa_dmpvr2_2rail},
+       {"isl69268", raa_dmpvr2_2rail},
+       {"isl69269", raa_dmpvr2_3rail},
+       {"isl69298", raa_dmpvr2_2rail},
+
+       {"raa228000", raa_dmpvr2_hv},
+       {"raa228004", raa_dmpvr2_hv},
+       {"raa228006", raa_dmpvr2_hv},
+       {"raa228228", raa_dmpvr2_2rail},
+       {"raa229001", raa_dmpvr2_2rail},
+       {"raa229004", raa_dmpvr2_2rail},
        {}
 };
 
index 20ef63820c776ef5b0c58eb048e35b72af10d457..f5c00f903df3833a08b4bc90b8456d7cbcf52d6d 100644 (file)
@@ -384,7 +384,6 @@ static int altr_i2c_probe(struct platform_device *pdev)
        struct altr_i2c_dev *idev = NULL;
        struct resource *res;
        int irq, ret;
-       u32 val;
 
        idev = devm_kzalloc(&pdev->dev, sizeof(*idev), GFP_KERNEL);
        if (!idev)
@@ -411,17 +410,17 @@ static int altr_i2c_probe(struct platform_device *pdev)
        init_completion(&idev->msg_complete);
        spin_lock_init(&idev->lock);
 
-       val = device_property_read_u32(idev->dev, "fifo-size",
+       ret = device_property_read_u32(idev->dev, "fifo-size",
                                       &idev->fifo_size);
-       if (val) {
+       if (ret) {
                dev_err(&pdev->dev, "FIFO size set to default of %d\n",
                        ALTR_I2C_DFLT_FIFO_SZ);
                idev->fifo_size = ALTR_I2C_DFLT_FIFO_SZ;
        }
 
-       val = device_property_read_u32(idev->dev, "clock-frequency",
+       ret = device_property_read_u32(idev->dev, "clock-frequency",
                                       &idev->bus_clk_rate);
-       if (val) {
+       if (ret) {
                dev_err(&pdev->dev, "Default to 100kHz\n");
                idev->bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ;        /* default clock rate */
        }
index 5e4800d72e00bc5a4c7a5b98294d22f99a093168..cd3fd5ee5f65d28815b9f2e22981f9f44b50b389 100644 (file)
@@ -349,12 +349,12 @@ static int amd_mp2_pci_probe(struct pci_dev *pci_dev,
        if (!privdata)
                return -ENOMEM;
 
+       privdata->pci_dev = pci_dev;
        rc = amd_mp2_pci_init(privdata, pci_dev);
        if (rc)
                return rc;
 
        mutex_init(&privdata->c2p_lock);
-       privdata->pci_dev = pci_dev;
 
        pm_runtime_set_autosuspend_delay(&pci_dev->dev, 1000);
        pm_runtime_use_autosuspend(&pci_dev->dev);
index 07c1993274c50217da6c1ead198fe3bf857f539f..f51702d86a90e708f11f1d27b89f9a98b49ed1cc 100644 (file)
@@ -603,6 +603,7 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
        /* Ack all interrupts except for Rx done */
        writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE,
               bus->base + ASPEED_I2C_INTR_STS_REG);
+       readl(bus->base + ASPEED_I2C_INTR_STS_REG);
        irq_remaining = irq_received;
 
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
@@ -645,9 +646,11 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
                        irq_received, irq_handled);
 
        /* Ack Rx done */
-       if (irq_received & ASPEED_I2CD_INTR_RX_DONE)
+       if (irq_received & ASPEED_I2CD_INTR_RX_DONE) {
                writel(ASPEED_I2CD_INTR_RX_DONE,
                       bus->base + ASPEED_I2C_INTR_STS_REG);
+               readl(bus->base + ASPEED_I2C_INTR_STS_REG);
+       }
        spin_unlock(&bus->lock);
        return irq_remaining ? IRQ_NONE : IRQ_HANDLED;
 }
index 44be0926b566395798340dc23e59278cbe2310f0..d091a12596ad2c66367d59f6a412fa3b3fdaba7c 100644 (file)
@@ -360,6 +360,9 @@ static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c,
                        value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK);
                        i2c_slave_event(iproc_i2c->slave,
                                        I2C_SLAVE_WRITE_RECEIVED, &value);
+                       if (rx_status == I2C_SLAVE_RX_END)
+                               i2c_slave_event(iproc_i2c->slave,
+                                               I2C_SLAVE_STOP, &value);
                }
        } else if (status & BIT(IS_S_TX_UNDERRUN_SHIFT)) {
                /* Master read other than start */
index c98befe2a92e045c9733fa06b1e0aea48f8d2b78..5536673060cc637d505bcc15cee1c1127e721118 100644 (file)
@@ -354,10 +354,16 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
        adap->dev.of_node = pdev->dev.of_node;
        adap->nr = -1;
 
-       dev_pm_set_driver_flags(&pdev->dev,
-                               DPM_FLAG_SMART_PREPARE |
-                               DPM_FLAG_SMART_SUSPEND |
-                               DPM_FLAG_LEAVE_SUSPENDED);
+       if (dev->flags & ACCESS_NO_IRQ_SUSPEND) {
+               dev_pm_set_driver_flags(&pdev->dev,
+                                       DPM_FLAG_SMART_PREPARE |
+                                       DPM_FLAG_LEAVE_SUSPENDED);
+       } else {
+               dev_pm_set_driver_flags(&pdev->dev,
+                                       DPM_FLAG_SMART_PREPARE |
+                                       DPM_FLAG_SMART_SUSPEND |
+                                       DPM_FLAG_LEAVE_SUSPENDED);
+       }
 
        /* The code below assumes runtime PM to be disabled. */
        WARN_ON(pm_runtime_enabled(&pdev->dev));
index 5cc0b0ec5570bd62aa06544649f1f8375f15eb4b..a6691278206474374c68a5b8786d4cf48f92bd34 100644 (file)
@@ -2273,19 +2273,6 @@ i2c_new_scanned_device(struct i2c_adapter *adap,
 }
 EXPORT_SYMBOL_GPL(i2c_new_scanned_device);
 
-struct i2c_client *
-i2c_new_probed_device(struct i2c_adapter *adap,
-                     struct i2c_board_info *info,
-                     unsigned short const *addr_list,
-                     int (*probe)(struct i2c_adapter *adap, unsigned short addr))
-{
-       struct i2c_client *client;
-
-       client = i2c_new_scanned_device(adap, info, addr_list, probe);
-       return IS_ERR(client) ? NULL : client;
-}
-EXPORT_SYMBOL_GPL(i2c_new_probed_device);
-
 struct i2c_adapter *i2c_get_adapter(int nr)
 {
        struct i2c_adapter *adapter;
index 02981f3d179410c34a188344e4ad34a242014d6d..08ba1a8f05eb347f1614c78006f84a7015888470 100644 (file)
 #define AD7193_CH_AINCOM       0x600 /* AINCOM - AINCOM */
 
 /* ID Register Bit Designations (AD7192_REG_ID) */
-#define ID_AD7190              0x4
-#define ID_AD7192              0x0
-#define ID_AD7193              0x2
-#define ID_AD7195              0x6
+#define CHIPID_AD7190          0x4
+#define CHIPID_AD7192          0x0
+#define CHIPID_AD7193          0x2
+#define CHIPID_AD7195          0x6
 #define AD7192_ID_MASK         0x0F
 
 /* GPOCON Register Bit Designations (AD7192_REG_GPOCON) */
@@ -161,7 +161,20 @@ enum {
        AD7192_SYSCALIB_FULL_SCALE,
 };
 
+enum {
+       ID_AD7190,
+       ID_AD7192,
+       ID_AD7193,
+       ID_AD7195,
+};
+
+struct ad7192_chip_info {
+       unsigned int                    chip_id;
+       const char                      *name;
+};
+
 struct ad7192_state {
+       const struct ad7192_chip_info   *chip_info;
        struct regulator                *avdd;
        struct regulator                *dvdd;
        struct clk                      *mclk;
@@ -172,7 +185,6 @@ struct ad7192_state {
        u32                             conf;
        u32                             scale_avail[8][2];
        u8                              gpocon;
-       u8                              devid;
        u8                              clock_sel;
        struct mutex                    lock;   /* protect sensor state */
        u8                              syscalib_mode[8];
@@ -348,7 +360,7 @@ static int ad7192_setup(struct ad7192_state *st, struct device_node *np)
 
        id &= AD7192_ID_MASK;
 
-       if (id != st->devid)
+       if (id != st->chip_info->chip_id)
                dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X)\n",
                         id);
 
@@ -363,7 +375,7 @@ static int ad7192_setup(struct ad7192_state *st, struct device_node *np)
                st->mode |= AD7192_MODE_REJ60;
 
        refin2_en = of_property_read_bool(np, "adi,refin2-pins-enable");
-       if (refin2_en && st->devid != ID_AD7195)
+       if (refin2_en && st->chip_info->chip_id != CHIPID_AD7195)
                st->conf |= AD7192_CONF_REFSEL;
 
        st->conf &= ~AD7192_CONF_CHOP;
@@ -859,12 +871,31 @@ static const struct iio_chan_spec ad7193_channels[] = {
        IIO_CHAN_SOFT_TIMESTAMP(14),
 };
 
+static const struct ad7192_chip_info ad7192_chip_info_tbl[] = {
+       [ID_AD7190] = {
+               .chip_id = CHIPID_AD7190,
+               .name = "ad7190",
+       },
+       [ID_AD7192] = {
+               .chip_id = CHIPID_AD7192,
+               .name = "ad7192",
+       },
+       [ID_AD7193] = {
+               .chip_id = CHIPID_AD7193,
+               .name = "ad7193",
+       },
+       [ID_AD7195] = {
+               .chip_id = CHIPID_AD7195,
+               .name = "ad7195",
+       },
+};
+
 static int ad7192_channels_config(struct iio_dev *indio_dev)
 {
        struct ad7192_state *st = iio_priv(indio_dev);
 
-       switch (st->devid) {
-       case ID_AD7193:
+       switch (st->chip_info->chip_id) {
+       case CHIPID_AD7193:
                indio_dev->channels = ad7193_channels;
                indio_dev->num_channels = ARRAY_SIZE(ad7193_channels);
                break;
@@ -878,10 +909,10 @@ static int ad7192_channels_config(struct iio_dev *indio_dev)
 }
 
 static const struct of_device_id ad7192_of_match[] = {
-       { .compatible = "adi,ad7190", .data = (void *)ID_AD7190 },
-       { .compatible = "adi,ad7192", .data = (void *)ID_AD7192 },
-       { .compatible = "adi,ad7193", .data = (void *)ID_AD7193 },
-       { .compatible = "adi,ad7195", .data = (void *)ID_AD7195 },
+       { .compatible = "adi,ad7190", .data = &ad7192_chip_info_tbl[ID_AD7190] },
+       { .compatible = "adi,ad7192", .data = &ad7192_chip_info_tbl[ID_AD7192] },
+       { .compatible = "adi,ad7193", .data = &ad7192_chip_info_tbl[ID_AD7193] },
+       { .compatible = "adi,ad7195", .data = &ad7192_chip_info_tbl[ID_AD7195] },
        {}
 };
 MODULE_DEVICE_TABLE(of, ad7192_of_match);
@@ -938,16 +969,16 @@ static int ad7192_probe(struct spi_device *spi)
        }
 
        spi_set_drvdata(spi, indio_dev);
-       st->devid = (unsigned long)of_device_get_match_data(&spi->dev);
+       st->chip_info = of_device_get_match_data(&spi->dev);
        indio_dev->dev.parent = &spi->dev;
-       indio_dev->name = spi_get_device_id(spi)->name;
+       indio_dev->name = st->chip_info->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
        ret = ad7192_channels_config(indio_dev);
        if (ret < 0)
                goto error_disable_dvdd;
 
-       if (st->devid == ID_AD7195)
+       if (st->chip_info->chip_id == CHIPID_AD7195)
                indio_dev->info = &ad7195_info;
        else
                indio_dev->info = &ad7192_info;
index b747db97f78ad5f60a9ea52c8643d29a21de480c..e5691e33032361df9abd0e1638a6c649a8784af4 100644 (file)
@@ -542,7 +542,7 @@ static const struct iio_info ad7797_info = {
        .read_raw = &ad7793_read_raw,
        .write_raw = &ad7793_write_raw,
        .write_raw_get_fmt = &ad7793_write_raw_get_fmt,
-       .attrs = &ad7793_attribute_group,
+       .attrs = &ad7797_attribute_group,
        .validate_trigger = ad_sd_validate_trigger,
 };
 
index 80c3f963527b5cf8997d880aed6a4c0e4676638e..ae622ee6d08cbb7d77ec68b9f01d077de6ddee8a 100644 (file)
@@ -1418,8 +1418,30 @@ static unsigned int stm32_adc_dma_residue(struct stm32_adc *adc)
 static void stm32_adc_dma_buffer_done(void *data)
 {
        struct iio_dev *indio_dev = data;
+       struct stm32_adc *adc = iio_priv(indio_dev);
+       int residue = stm32_adc_dma_residue(adc);
+
+       /*
+        * In DMA mode the trigger services of IIO are not used
+        * (e.g. no call to iio_trigger_poll).
+        * Calling irq handler associated to the hardware trigger is not
+        * relevant as the conversions have already been done. Data
+        * transfers are performed directly in DMA callback instead.
+        * This implementation avoids to call trigger irq handler that
+        * may sleep, in an atomic context (DMA irq handler context).
+        */
+       dev_dbg(&indio_dev->dev, "%s bufi=%d\n", __func__, adc->bufi);
 
-       iio_trigger_poll_chained(indio_dev->trig);
+       while (residue >= indio_dev->scan_bytes) {
+               u16 *buffer = (u16 *)&adc->rx_buf[adc->bufi];
+
+               iio_push_to_buffers(indio_dev, buffer);
+
+               residue -= indio_dev->scan_bytes;
+               adc->bufi += indio_dev->scan_bytes;
+               if (adc->bufi >= adc->rx_buf_sz)
+                       adc->bufi = 0;
+       }
 }
 
 static int stm32_adc_dma_start(struct iio_dev *indio_dev)
@@ -1845,6 +1867,7 @@ static int stm32_adc_probe(struct platform_device *pdev)
 {
        struct iio_dev *indio_dev;
        struct device *dev = &pdev->dev;
+       irqreturn_t (*handler)(int irq, void *p) = NULL;
        struct stm32_adc *adc;
        int ret;
 
@@ -1911,9 +1934,11 @@ static int stm32_adc_probe(struct platform_device *pdev)
        if (ret < 0)
                return ret;
 
+       if (!adc->dma_chan)
+               handler = &stm32_adc_trigger_handler;
+
        ret = iio_triggered_buffer_setup(indio_dev,
-                                        &iio_pollfunc_store_time,
-                                        &stm32_adc_trigger_handler,
+                                        &iio_pollfunc_store_time, handler,
                                         &stm32_adc_buffer_setup_ops);
        if (ret) {
                dev_err(&pdev->dev, "buffer setup failed\n");
index 9a460807d46d13975bac3578300c72fcf75cd05c..abe4b56c847c7db3c362f0c1d5fea0159dacf74b 100644 (file)
@@ -29,7 +29,7 @@ struct ads8344 {
        struct mutex lock;
 
        u8 tx_buf ____cacheline_aligned;
-       u16 rx_buf;
+       u8 rx_buf[3];
 };
 
 #define ADS8344_VOLTAGE_CHANNEL(chan, si)                              \
@@ -89,11 +89,11 @@ static int ads8344_adc_conversion(struct ads8344 *adc, int channel,
 
        udelay(9);
 
-       ret = spi_read(spi, &adc->rx_buf, 2);
+       ret = spi_read(spi, adc->rx_buf, sizeof(adc->rx_buf));
        if (ret)
                return ret;
 
-       return adc->rx_buf;
+       return adc->rx_buf[0] << 9 | adc->rx_buf[1] << 1 | adc->rx_buf[2] >> 7;
 }
 
 static int ads8344_read_raw(struct iio_dev *iio,
index ec227b358cd6f868dbb7d00f4a9e57fabe0ea65f..6fd06e4eff73eb2cb5b0a2729b2f784403fdcb43 100644 (file)
@@ -102,6 +102,16 @@ static const unsigned int XADC_ZYNQ_UNMASK_TIMEOUT = 500;
 
 #define XADC_FLAGS_BUFFERED BIT(0)
 
+/*
+ * The XADC hardware supports a samplerate of up to 1MSPS. Unfortunately it does
+ * not have a hardware FIFO. Which means an interrupt is generated for each
+ * conversion sequence. At 1MSPS sample rate the CPU in ZYNQ7000 is completely
+ * overloaded by the interrupts that it soft-lockups. For this reason the driver
+ * limits the maximum samplerate 150kSPS. At this rate the CPU is fairly busy,
+ * but still responsive.
+ */
+#define XADC_MAX_SAMPLERATE 150000
+
 static void xadc_write_reg(struct xadc *xadc, unsigned int reg,
        uint32_t val)
 {
@@ -674,7 +684,7 @@ static int xadc_trigger_set_state(struct iio_trigger *trigger, bool state)
 
        spin_lock_irqsave(&xadc->lock, flags);
        xadc_read_reg(xadc, XADC_AXI_REG_IPIER, &val);
-       xadc_write_reg(xadc, XADC_AXI_REG_IPISR, val & XADC_AXI_INT_EOS);
+       xadc_write_reg(xadc, XADC_AXI_REG_IPISR, XADC_AXI_INT_EOS);
        if (state)
                val |= XADC_AXI_INT_EOS;
        else
@@ -722,13 +732,14 @@ static int xadc_power_adc_b(struct xadc *xadc, unsigned int seq_mode)
 {
        uint16_t val;
 
+       /* Powerdown the ADC-B when it is not needed. */
        switch (seq_mode) {
        case XADC_CONF1_SEQ_SIMULTANEOUS:
        case XADC_CONF1_SEQ_INDEPENDENT:
-               val = XADC_CONF2_PD_ADC_B;
+               val = 0;
                break;
        default:
-               val = 0;
+               val = XADC_CONF2_PD_ADC_B;
                break;
        }
 
@@ -797,6 +808,16 @@ static int xadc_preenable(struct iio_dev *indio_dev)
        if (ret)
                goto err;
 
+       /*
+        * In simultaneous mode the upper and lower aux channels are samples at
+        * the same time. In this mode the upper 8 bits in the sequencer
+        * register are don't care and the lower 8 bits control two channels
+        * each. As such we must set the bit if either the channel in the lower
+        * group or the upper group is enabled.
+        */
+       if (seq_mode == XADC_CONF1_SEQ_SIMULTANEOUS)
+               scan_mask = ((scan_mask >> 8) | scan_mask) & 0xff0000;
+
        ret = xadc_write_adc_reg(xadc, XADC_REG_SEQ(1), scan_mask >> 16);
        if (ret)
                goto err;
@@ -823,11 +844,27 @@ static const struct iio_buffer_setup_ops xadc_buffer_ops = {
        .postdisable = &xadc_postdisable,
 };
 
+static int xadc_read_samplerate(struct xadc *xadc)
+{
+       unsigned int div;
+       uint16_t val16;
+       int ret;
+
+       ret = xadc_read_adc_reg(xadc, XADC_REG_CONF2, &val16);
+       if (ret)
+               return ret;
+
+       div = (val16 & XADC_CONF2_DIV_MASK) >> XADC_CONF2_DIV_OFFSET;
+       if (div < 2)
+               div = 2;
+
+       return xadc_get_dclk_rate(xadc) / div / 26;
+}
+
 static int xadc_read_raw(struct iio_dev *indio_dev,
        struct iio_chan_spec const *chan, int *val, int *val2, long info)
 {
        struct xadc *xadc = iio_priv(indio_dev);
-       unsigned int div;
        uint16_t val16;
        int ret;
 
@@ -880,41 +917,31 @@ static int xadc_read_raw(struct iio_dev *indio_dev,
                *val = -((273150 << 12) / 503975);
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_SAMP_FREQ:
-               ret = xadc_read_adc_reg(xadc, XADC_REG_CONF2, &val16);
-               if (ret)
+               ret = xadc_read_samplerate(xadc);
+               if (ret < 0)
                        return ret;
 
-               div = (val16 & XADC_CONF2_DIV_MASK) >> XADC_CONF2_DIV_OFFSET;
-               if (div < 2)
-                       div = 2;
-
-               *val = xadc_get_dclk_rate(xadc) / div / 26;
-
+               *val = ret;
                return IIO_VAL_INT;
        default:
                return -EINVAL;
        }
 }
 
-static int xadc_write_raw(struct iio_dev *indio_dev,
-       struct iio_chan_spec const *chan, int val, int val2, long info)
+static int xadc_write_samplerate(struct xadc *xadc, int val)
 {
-       struct xadc *xadc = iio_priv(indio_dev);
        unsigned long clk_rate = xadc_get_dclk_rate(xadc);
        unsigned int div;
 
        if (!clk_rate)
                return -EINVAL;
 
-       if (info != IIO_CHAN_INFO_SAMP_FREQ)
-               return -EINVAL;
-
        if (val <= 0)
                return -EINVAL;
 
        /* Max. 150 kSPS */
-       if (val > 150000)
-               val = 150000;
+       if (val > XADC_MAX_SAMPLERATE)
+               val = XADC_MAX_SAMPLERATE;
 
        val *= 26;
 
@@ -927,7 +954,7 @@ static int xadc_write_raw(struct iio_dev *indio_dev,
         * limit.
         */
        div = clk_rate / val;
-       if (clk_rate / div / 26 > 150000)
+       if (clk_rate / div / 26 > XADC_MAX_SAMPLERATE)
                div++;
        if (div < 2)
                div = 2;
@@ -938,6 +965,17 @@ static int xadc_write_raw(struct iio_dev *indio_dev,
                div << XADC_CONF2_DIV_OFFSET);
 }
 
+static int xadc_write_raw(struct iio_dev *indio_dev,
+       struct iio_chan_spec const *chan, int val, int val2, long info)
+{
+       struct xadc *xadc = iio_priv(indio_dev);
+
+       if (info != IIO_CHAN_INFO_SAMP_FREQ)
+               return -EINVAL;
+
+       return xadc_write_samplerate(xadc, val);
+}
+
 static const struct iio_event_spec xadc_temp_events[] = {
        {
                .type = IIO_EV_TYPE_THRESH,
@@ -1223,6 +1261,21 @@ static int xadc_probe(struct platform_device *pdev)
        if (ret)
                goto err_free_samplerate_trigger;
 
+       /*
+        * Make sure not to exceed the maximum samplerate since otherwise the
+        * resulting interrupt storm will soft-lock the system.
+        */
+       if (xadc->ops->flags & XADC_FLAGS_BUFFERED) {
+               ret = xadc_read_samplerate(xadc);
+               if (ret < 0)
+                       goto err_free_samplerate_trigger;
+               if (ret > XADC_MAX_SAMPLERATE) {
+                       ret = xadc_write_samplerate(xadc, XADC_MAX_SAMPLERATE);
+                       if (ret < 0)
+                               goto err_free_samplerate_trigger;
+               }
+       }
+
        ret = request_irq(xadc->irq, xadc->ops->interrupt_handler, 0,
                        dev_name(&pdev->dev), indio_dev);
        if (ret)
index 0e35ff06f9af9d1d821411a679b2da9d497c0f85..13bdfbbf5f71f0eb38b55324c422837474a3ea7a 100644 (file)
@@ -79,7 +79,7 @@ int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr)
        struct st_sensor_odr_avl odr_out = {0, 0};
        struct st_sensor_data *sdata = iio_priv(indio_dev);
 
-       if (!sdata->sensor_settings->odr.addr)
+       if (!sdata->sensor_settings->odr.mask)
                return 0;
 
        err = st_sensors_match_odr(sdata->sensor_settings, odr, &odr_out);
index a98ea76732e72cf07881fcbbda0dd0224fb2aebe..2d7623b9b2c0ec8b88e46676a40086660c7d0cb7 100644 (file)
@@ -525,7 +525,7 @@ static int ad5770r_channel_config(struct ad5770r_state *st)
                ret = fwnode_property_read_u32(child, "num", &num);
                if (ret)
                        return ret;
-               if (num > AD5770R_MAX_CHANNELS)
+               if (num >= AD5770R_MAX_CHANNELS)
                        return -EINVAL;
 
                ret = fwnode_property_read_u32_array(child,
index 7cb9ff3d3e940018134b08badc9d3f50ab4cf545..0b8d2f7a0165bb6b8e2be85c2af8e18f55a8ec1d 100644 (file)
@@ -1617,6 +1617,10 @@ static int __maybe_unused inv_mpu_resume(struct device *dev)
        if (result)
                goto out_unlock;
 
+       pm_runtime_disable(dev);
+       pm_runtime_set_active(dev);
+       pm_runtime_enable(dev);
+
        result = inv_mpu6050_switch_engine(st, true, st->suspended_sensors);
        if (result)
                goto out_unlock;
@@ -1638,13 +1642,18 @@ static int __maybe_unused inv_mpu_suspend(struct device *dev)
 
        mutex_lock(&st->lock);
 
+       st->suspended_sensors = 0;
+       if (pm_runtime_suspended(dev)) {
+               result = 0;
+               goto out_unlock;
+       }
+
        if (iio_buffer_enabled(indio_dev)) {
                result = inv_mpu6050_prepare_fifo(st, false);
                if (result)
                        goto out_unlock;
        }
 
-       st->suspended_sensors = 0;
        if (st->chip_config.accl_en)
                st->suspended_sensors |= INV_MPU6050_SENSOR_ACCL;
        if (st->chip_config.gyro_en)
index f2113a63721a8619e57ab685cd28864d3b7f8054..41cb20cb3809aa1e02ee8ccd6e1683290050d816 100644 (file)
@@ -337,6 +337,7 @@ enum st_lsm6dsx_fifo_mode {
  * @gain: Configured sensor sensitivity.
  * @odr: Output data rate of the sensor [Hz].
  * @watermark: Sensor watermark level.
+ * @decimator: Sensor decimation factor.
  * @sip: Number of samples in a given pattern.
  * @ts_ref: Sensor timestamp reference for hw one.
  * @ext_info: Sensor settings if it is connected to i2c controller
@@ -350,11 +351,13 @@ struct st_lsm6dsx_sensor {
        u32 odr;
 
        u16 watermark;
+       u8 decimator;
        u8 sip;
        s64 ts_ref;
 
        struct {
                const struct st_lsm6dsx_ext_dev_settings *settings;
+               u32 slv_odr;
                u8 addr;
        } ext_info;
 };
index bb899345f2bbace1ff7655d246af9fc573de5e62..afd00daeefb2d4ae6fb57659cd3085c83193fefe 100644 (file)
@@ -93,6 +93,7 @@ st_lsm6dsx_get_decimator_val(struct st_lsm6dsx_sensor *sensor, u32 max_odr)
                        break;
        }
 
+       sensor->decimator = decimator;
        return i == max_size ? 0 : st_lsm6dsx_decimator_table[i].val;
 }
 
@@ -337,7 +338,7 @@ static inline int st_lsm6dsx_read_block(struct st_lsm6dsx_hw *hw, u8 addr,
 int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
 {
        struct st_lsm6dsx_sensor *acc_sensor, *gyro_sensor, *ext_sensor = NULL;
-       int err, acc_sip, gyro_sip, ts_sip, ext_sip, read_len, offset;
+       int err, sip, acc_sip, gyro_sip, ts_sip, ext_sip, read_len, offset;
        u16 fifo_len, pattern_len = hw->sip * ST_LSM6DSX_SAMPLE_SIZE;
        u16 fifo_diff_mask = hw->settings->fifo_ops.fifo_diff.mask;
        u8 gyro_buff[ST_LSM6DSX_IIO_BUFF_SIZE];
@@ -399,19 +400,20 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
                acc_sip = acc_sensor->sip;
                ts_sip = hw->ts_sip;
                offset = 0;
+               sip = 0;
 
                while (acc_sip > 0 || gyro_sip > 0 || ext_sip > 0) {
-                       if (gyro_sip > 0) {
+                       if (gyro_sip > 0 && !(sip % gyro_sensor->decimator)) {
                                memcpy(gyro_buff, &hw->buff[offset],
                                       ST_LSM6DSX_SAMPLE_SIZE);
                                offset += ST_LSM6DSX_SAMPLE_SIZE;
                        }
-                       if (acc_sip > 0) {
+                       if (acc_sip > 0 && !(sip % acc_sensor->decimator)) {
                                memcpy(acc_buff, &hw->buff[offset],
                                       ST_LSM6DSX_SAMPLE_SIZE);
                                offset += ST_LSM6DSX_SAMPLE_SIZE;
                        }
-                       if (ext_sip > 0) {
+                       if (ext_sip > 0 && !(sip % ext_sensor->decimator)) {
                                memcpy(ext_buff, &hw->buff[offset],
                                       ST_LSM6DSX_SAMPLE_SIZE);
                                offset += ST_LSM6DSX_SAMPLE_SIZE;
@@ -441,18 +443,25 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
                                offset += ST_LSM6DSX_SAMPLE_SIZE;
                        }
 
-                       if (gyro_sip-- > 0)
+                       if (gyro_sip > 0 && !(sip % gyro_sensor->decimator)) {
                                iio_push_to_buffers_with_timestamp(
                                        hw->iio_devs[ST_LSM6DSX_ID_GYRO],
                                        gyro_buff, gyro_sensor->ts_ref + ts);
-                       if (acc_sip-- > 0)
+                               gyro_sip--;
+                       }
+                       if (acc_sip > 0 && !(sip % acc_sensor->decimator)) {
                                iio_push_to_buffers_with_timestamp(
                                        hw->iio_devs[ST_LSM6DSX_ID_ACC],
                                        acc_buff, acc_sensor->ts_ref + ts);
-                       if (ext_sip-- > 0)
+                               acc_sip--;
+                       }
+                       if (ext_sip > 0 && !(sip % ext_sensor->decimator)) {
                                iio_push_to_buffers_with_timestamp(
                                        hw->iio_devs[ST_LSM6DSX_ID_EXT0],
                                        ext_buff, ext_sensor->ts_ref + ts);
+                               ext_sip--;
+                       }
+                       sip++;
                }
        }
 
index 84d219ae6aee5d13e8b540e62da722265f425dc1..4426524b59f28648bf1557bac6709b3b6bc92e3d 100644 (file)
@@ -2036,11 +2036,21 @@ static int st_lsm6dsx_init_hw_timer(struct st_lsm6dsx_hw *hw)
        return 0;
 }
 
-static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw)
+static int st_lsm6dsx_reset_device(struct st_lsm6dsx_hw *hw)
 {
        const struct st_lsm6dsx_reg *reg;
        int err;
 
+       /*
+        * flush hw FIFO before device reset in order to avoid
+        * possible races on interrupt line 1. If the first interrupt
+        * line is asserted during hw reset the device will work in
+        * I3C-only mode (if it is supported)
+        */
+       err = st_lsm6dsx_flush_fifo(hw);
+       if (err < 0 && err != -ENOTSUPP)
+               return err;
+
        /* device sw reset */
        reg = &hw->settings->reset;
        err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
@@ -2059,6 +2069,18 @@ static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw)
 
        msleep(50);
 
+       return 0;
+}
+
+static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw)
+{
+       const struct st_lsm6dsx_reg *reg;
+       int err;
+
+       err = st_lsm6dsx_reset_device(hw);
+       if (err < 0)
+               return err;
+
        /* enable Block Data Update */
        reg = &hw->settings->bdu;
        err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
index 95ddd19d1aa7c369df3cb488805eed726fc33eb8..64ef07a307263a8335fe990c093f6bf4237f7aa8 100644 (file)
@@ -421,7 +421,8 @@ int st_lsm6dsx_shub_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable)
 
        settings = sensor->ext_info.settings;
        if (enable) {
-               err = st_lsm6dsx_shub_set_odr(sensor, sensor->odr);
+               err = st_lsm6dsx_shub_set_odr(sensor,
+                                             sensor->ext_info.slv_odr);
                if (err < 0)
                        return err;
        } else {
@@ -459,7 +460,7 @@ st_lsm6dsx_shub_read_oneshot(struct st_lsm6dsx_sensor *sensor,
        if (err < 0)
                return err;
 
-       delay = 1000000000 / sensor->odr;
+       delay = 1000000000 / sensor->ext_info.slv_odr;
        usleep_range(delay, 2 * delay);
 
        len = min_t(int, sizeof(data), ch->scan_type.realbits >> 3);
@@ -500,8 +501,8 @@ st_lsm6dsx_shub_read_raw(struct iio_dev *iio_dev,
                iio_device_release_direct_mode(iio_dev);
                break;
        case IIO_CHAN_INFO_SAMP_FREQ:
-               *val = sensor->odr / 1000;
-               *val2 = (sensor->odr % 1000) * 1000;
+               *val = sensor->ext_info.slv_odr / 1000;
+               *val2 = (sensor->ext_info.slv_odr % 1000) * 1000;
                ret = IIO_VAL_INT_PLUS_MICRO;
                break;
        case IIO_CHAN_INFO_SCALE:
@@ -535,8 +536,20 @@ st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev,
 
                val = val * 1000 + val2 / 1000;
                err = st_lsm6dsx_shub_get_odr_val(sensor, val, &data);
-               if (!err)
-                       sensor->odr = val;
+               if (!err) {
+                       struct st_lsm6dsx_hw *hw = sensor->hw;
+                       struct st_lsm6dsx_sensor *ref_sensor;
+                       u8 odr_val;
+                       int odr;
+
+                       ref_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
+                       odr = st_lsm6dsx_check_odr(ref_sensor, val, &odr_val);
+                       if (odr < 0)
+                               return odr;
+
+                       sensor->ext_info.slv_odr = val;
+                       sensor->odr = odr;
+               }
                break;
        }
        default:
@@ -613,6 +626,7 @@ st_lsm6dsx_shub_alloc_iiodev(struct st_lsm6dsx_hw *hw,
                             const struct st_lsm6dsx_ext_dev_settings *info,
                             u8 i2c_addr, const char *name)
 {
+       enum st_lsm6dsx_sensor_id ref_id = ST_LSM6DSX_ID_ACC;
        struct iio_chan_spec *ext_channels;
        struct st_lsm6dsx_sensor *sensor;
        struct iio_dev *iio_dev;
@@ -628,7 +642,8 @@ st_lsm6dsx_shub_alloc_iiodev(struct st_lsm6dsx_hw *hw,
        sensor = iio_priv(iio_dev);
        sensor->id = id;
        sensor->hw = hw;
-       sensor->odr = info->odr_table.odr_avl[0].milli_hz;
+       sensor->odr = hw->settings->odr_table[ref_id].odr_avl[0].milli_hz;
+       sensor->ext_info.slv_odr = info->odr_table.odr_avl[0].milli_hz;
        sensor->gain = info->fs_table.fs_avl[0].gain;
        sensor->ext_info.settings = info;
        sensor->ext_info.addr = i2c_addr;
index 2352c426bfb5baf99da6ed5c8b5de8081d45e074..24f7bbff4938fb03e31b8dba2e5a9ab2ffe6a1ce 100644 (file)
@@ -915,14 +915,11 @@ static ssize_t iio_write_channel_info(struct device *dev,
                        return -EINVAL;
                integer = ch;
        } else {
-               ret = iio_str_to_fixpoint(buf, fract_mult, &integer, &fract);
+               ret = __iio_str_to_fixpoint(buf, fract_mult, &integer, &fract,
+                                           scale_db);
                if (ret)
                        return ret;
        }
-       ret = __iio_str_to_fixpoint(buf, fract_mult, &integer, &fract,
-                                   scale_db);
-       if (ret)
-               return ret;
 
        ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
                                         integer, fract, this_attr->address);
index 4794113ecd596c3f551ed7dc08c0e9171191f82b..17f14e0eafe4d484e5657ad138cc89145b925621 100644 (file)
@@ -862,7 +862,7 @@ static struct cm_id_private *cm_alloc_id_priv(struct ib_device *device,
 
        ret = xa_alloc_cyclic_irq(&cm.local_id_table, &id, NULL, xa_limit_32b,
                                  &cm.local_id_next, GFP_KERNEL);
-       if (ret)
+       if (ret < 0)
                goto error;
        cm_id_priv->id.local_id = (__force __be32)id ^ cm.random_id_operand;
 
@@ -1828,11 +1828,9 @@ static void cm_format_mra(struct cm_mra_msg *mra_msg,
 
 static void cm_format_rej(struct cm_rej_msg *rej_msg,
                          struct cm_id_private *cm_id_priv,
-                         enum ib_cm_rej_reason reason,
-                         void *ari,
-                         u8 ari_length,
-                         const void *private_data,
-                         u8 private_data_len)
+                         enum ib_cm_rej_reason reason, void *ari,
+                         u8 ari_length, const void *private_data,
+                         u8 private_data_len, enum ib_cm_state state)
 {
        lockdep_assert_held(&cm_id_priv->lock);
 
@@ -1840,7 +1838,7 @@ static void cm_format_rej(struct cm_rej_msg *rej_msg,
        IBA_SET(CM_REJ_REMOTE_COMM_ID, rej_msg,
                be32_to_cpu(cm_id_priv->id.remote_id));
 
-       switch(cm_id_priv->id.state) {
+       switch (state) {
        case IB_CM_REQ_RCVD:
                IBA_SET(CM_REJ_LOCAL_COMM_ID, rej_msg, be32_to_cpu(0));
                IBA_SET(CM_REJ_MESSAGE_REJECTED, rej_msg, CM_MSG_RESPONSE_REQ);
@@ -1905,8 +1903,9 @@ static void cm_dup_req_handler(struct cm_work *work,
                              cm_id_priv->private_data_len);
                break;
        case IB_CM_TIMEWAIT:
-               cm_format_rej((struct cm_rej_msg *) msg->mad, cm_id_priv,
-                             IB_CM_REJ_STALE_CONN, NULL, 0, NULL, 0);
+               cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv,
+                             IB_CM_REJ_STALE_CONN, NULL, 0, NULL, 0,
+                             IB_CM_TIMEWAIT);
                break;
        default:
                goto unlock;
@@ -2904,6 +2903,7 @@ static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
                              u8 ari_length, const void *private_data,
                              u8 private_data_len)
 {
+       enum ib_cm_state state = cm_id_priv->id.state;
        struct ib_mad_send_buf *msg;
        int ret;
 
@@ -2913,7 +2913,7 @@ static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
            (ari && ari_length > IB_CM_REJ_ARI_LENGTH))
                return -EINVAL;
 
-       switch (cm_id_priv->id.state) {
+       switch (state) {
        case IB_CM_REQ_SENT:
        case IB_CM_MRA_REQ_RCVD:
        case IB_CM_REQ_RCVD:
@@ -2925,7 +2925,8 @@ static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
                if (ret)
                        return ret;
                cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv, reason,
-                             ari, ari_length, private_data, private_data_len);
+                             ari, ari_length, private_data, private_data_len,
+                             state);
                break;
        case IB_CM_REP_SENT:
        case IB_CM_MRA_REP_RCVD:
@@ -2934,7 +2935,8 @@ static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
                if (ret)
                        return ret;
                cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv, reason,
-                             ari, ari_length, private_data, private_data_len);
+                             ari, ari_length, private_data, private_data_len,
+                             state);
                break;
        default:
                pr_debug("%s: local_id %d, cm_id->state: %d\n", __func__,
index 5128cb16bb4856f83f10c7a2dcb758d935418b36..177333d8bcdaeeb3a8e455248715776e892adb40 100644 (file)
@@ -360,7 +360,7 @@ lookup_get_fd_uobject(const struct uverbs_api_object *obj,
         * uverbs_uobject_fd_release(), and the caller is expected to ensure
         * that release is never done while a call to lookup is possible.
         */
-       if (f->f_op != fd_type->fops) {
+       if (f->f_op != fd_type->fops || uobject->ufile != ufile) {
                fput(f);
                return ERR_PTR(-EBADF);
        }
@@ -474,16 +474,15 @@ alloc_begin_fd_uobject(const struct uverbs_api_object *obj,
        filp = anon_inode_getfile(fd_type->name, fd_type->fops, NULL,
                                  fd_type->flags);
        if (IS_ERR(filp)) {
+               uverbs_uobject_put(uobj);
                uobj = ERR_CAST(filp);
-               goto err_uobj;
+               goto err_fd;
        }
        uobj->object = filp;
 
        uobj->id = new_fd;
        return uobj;
 
-err_uobj:
-       uverbs_uobject_put(uobj);
 err_fd:
        put_unused_fd(new_fd);
        return uobj;
@@ -679,7 +678,6 @@ void rdma_lookup_put_uobject(struct ib_uobject *uobj,
                             enum rdma_lookup_mode mode)
 {
        assert_uverbs_usecnt(uobj, mode);
-       uobj->uapi_object->type_class->lookup_put(uobj, mode);
        /*
         * In order to unlock an object, either decrease its usecnt for
         * read access or zero it in case of exclusive access. See
@@ -696,6 +694,7 @@ void rdma_lookup_put_uobject(struct ib_uobject *uobj,
                break;
        }
 
+       uobj->uapi_object->type_class->lookup_put(uobj, mode);
        /* Pairs with the kref obtained by type->lookup_get */
        uverbs_uobject_put(uobj);
 }
index 2d4083bf4a048767775eea73680debe4351f20df..17fc25db031145df82d7af89eade3d3e25d0b2e9 100644 (file)
@@ -820,6 +820,10 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
                        ret = mmget_not_zero(mm);
                        if (!ret) {
                                list_del_init(&priv->list);
+                               if (priv->entry) {
+                                       rdma_user_mmap_entry_put(priv->entry);
+                                       priv->entry = NULL;
+                               }
                                mm = NULL;
                                continue;
                        }
index e8b4b3743661da0c6cfb1681efbe174875f216d4..688f196672215ee4b6c5384443218bb50cc48286 100644 (file)
@@ -1046,7 +1046,7 @@ i40iw_sc_query_rdma_features(struct i40iw_sc_cqp *cqp,
        u64 header;
 
        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
-       if (wqe)
+       if (!wqe)
                return I40IW_ERR_RING_FULL;
 
        set_64bit_val(wqe, 32, feat_mem->pa);
index a66518a5c93868ac2ae3579c89736e1327417f1c..275722cec8c675690c573a000c452abc81f7d0f0 100644 (file)
@@ -1499,8 +1499,9 @@ static int __mlx4_ib_create_default_rules(
        int i;
 
        for (i = 0; i < ARRAY_SIZE(pdefault_rules->rules_create_list); i++) {
+               union ib_flow_spec ib_spec = {};
                int ret;
-               union ib_flow_spec ib_spec;
+
                switch (pdefault_rules->rules_create_list[i]) {
                case 0:
                        /* no rule */
index 1456db4b6295907c47e0b7f2d083819e58b49dc3..2210759843ba88e3e9033d0dd2572a2ab31c1839 100644 (file)
@@ -5558,7 +5558,9 @@ static void to_rdma_ah_attr(struct mlx5_ib_dev *ibdev,
        rdma_ah_set_path_bits(ah_attr, path->grh_mlid & 0x7f);
        rdma_ah_set_static_rate(ah_attr,
                                path->static_rate ? path->static_rate - 5 : 0);
-       if (path->grh_mlid & (1 << 7)) {
+
+       if (path->grh_mlid & (1 << 7) ||
+           ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) {
                u32 tc_fl = be32_to_cpu(path->tclass_flowlabel);
 
                rdma_ah_set_grh(ah_attr, NULL,
index 5724cbbe38b1f2432a3309f3139db548998a6181..04d2e72017fedaefe23ddb25900f583240cac8ca 100644 (file)
@@ -248,8 +248,8 @@ int rvt_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
         */
        if (udata && udata->outlen >= sizeof(__u64)) {
                cq->ip = rvt_create_mmap_info(rdi, sz, udata, u_wc);
-               if (!cq->ip) {
-                       err = -ENOMEM;
+               if (IS_ERR(cq->ip)) {
+                       err = PTR_ERR(cq->ip);
                        goto bail_wc;
                }
 
index 652f4a7efc1bed223d5052bf04eb46d296160888..37853aa3bcf7788eee80c219dc8f42e89b1eae20 100644 (file)
@@ -154,7 +154,7 @@ done:
  * @udata: user data (must be valid!)
  * @obj: opaque pointer to a cq, wq etc
  *
- * Return: rvt_mmap struct on success
+ * Return: rvt_mmap struct on success, ERR_PTR on failure
  */
 struct rvt_mmap_info *rvt_create_mmap_info(struct rvt_dev_info *rdi, u32 size,
                                           struct ib_udata *udata, void *obj)
@@ -166,7 +166,7 @@ struct rvt_mmap_info *rvt_create_mmap_info(struct rvt_dev_info *rdi, u32 size,
 
        ip = kmalloc_node(sizeof(*ip), GFP_KERNEL, rdi->dparms.node);
        if (!ip)
-               return ip;
+               return ERR_PTR(-ENOMEM);
 
        size = PAGE_ALIGN(size);
 
index 0e1b291d2cec8cacaf5a5b0b71113d626572c77d..500a7ee04c44e2afd0ce165b0018a1b46fbb3c2a 100644 (file)
@@ -1244,8 +1244,8 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 
                        qp->ip = rvt_create_mmap_info(rdi, s, udata,
                                                      qp->r_rq.wq);
-                       if (!qp->ip) {
-                               ret = ERR_PTR(-ENOMEM);
+                       if (IS_ERR(qp->ip)) {
+                               ret = ERR_CAST(qp->ip);
                                goto bail_qpn;
                        }
 
index 24fef021d51dbb825135d01c6840339ed6a805ee..f547c115af0369883b099699aa9981aa4f394d7f 100644 (file)
@@ -111,8 +111,8 @@ int rvt_create_srq(struct ib_srq *ibsrq, struct ib_srq_init_attr *srq_init_attr,
                u32 s = sizeof(struct rvt_rwq) + srq->rq.size * sz;
 
                srq->ip = rvt_create_mmap_info(dev, s, udata, srq->rq.wq);
-               if (!srq->ip) {
-                       ret = -ENOMEM;
+               if (IS_ERR(srq->ip)) {
+                       ret = PTR_ERR(srq->ip);
                        goto bail_wq;
                }
 
index ae92c8080967c5bc66919c32db45390d091ac507..9f53aa4feb8782c0880120da0e26fe545e24f46e 100644 (file)
@@ -920,20 +920,27 @@ static int siw_fastreg_mr(struct ib_pd *pd, struct siw_sqe *sqe)
 {
        struct ib_mr *base_mr = (struct ib_mr *)(uintptr_t)sqe->base_mr;
        struct siw_device *sdev = to_siw_dev(pd->device);
-       struct siw_mem *mem = siw_mem_id2obj(sdev, sqe->rkey  >> 8);
+       struct siw_mem *mem;
        int rv = 0;
 
        siw_dbg_pd(pd, "STag 0x%08x\n", sqe->rkey);
 
-       if (unlikely(!mem || !base_mr)) {
+       if (unlikely(!base_mr)) {
                pr_warn("siw: fastreg: STag 0x%08x unknown\n", sqe->rkey);
                return -EINVAL;
        }
+
        if (unlikely(base_mr->rkey >> 8 != sqe->rkey  >> 8)) {
                pr_warn("siw: fastreg: STag 0x%08x: bad MR\n", sqe->rkey);
-               rv = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
+
+       mem = siw_mem_id2obj(sdev, sqe->rkey  >> 8);
+       if (unlikely(!mem)) {
+               pr_warn("siw: fastreg: STag 0x%08x unknown\n", sqe->rkey);
+               return -EINVAL;
+       }
+
        if (unlikely(mem->pd != pd)) {
                pr_warn("siw: fastreg: PD mismatch\n");
                rv = -EINVAL;
index 2adfde8cdf19df99cfc5728aaaf320e73aaf98c9..2a11a63e7217ad93ae718fb0c082e7ccd3e9d6bb 100644 (file)
@@ -96,6 +96,8 @@ static inline void tcs_cmd_gen(struct tcs_cmd *cmd, u64 vote_x, u64 vote_y,
        if (!cmd)
                return;
 
+       memset(cmd, 0, sizeof(*cmd));
+
        if (vote_x == 0 && vote_y == 0)
                valid = false;
 
@@ -112,8 +114,7 @@ static inline void tcs_cmd_gen(struct tcs_cmd *cmd, u64 vote_x, u64 vote_y,
         * Set the wait for completion flag on command that need to be completed
         * before the next command.
         */
-       if (commit)
-               cmd->wait = true;
+       cmd->wait = commit;
 }
 
 static void tcs_list_gen(struct list_head *bcm_list, int bucket,
index a03c6d6833dfc34cf58601b6bda8ebbbc2ee8f73..96fb9ff5ff2e85c58cd140f28b1553a85e2e729f 100644 (file)
@@ -78,7 +78,7 @@ static struct qcom_icc_node *sdm845_osm_l3_nodes[] = {
        [SLAVE_OSM_L3] = &sdm845_osm_l3,
 };
 
-const static struct qcom_icc_desc sdm845_icc_osm_l3 = {
+static const struct qcom_icc_desc sdm845_icc_osm_l3 = {
        .nodes = sdm845_osm_l3_nodes,
        .num_nodes = ARRAY_SIZE(sdm845_osm_l3_nodes),
 };
@@ -91,7 +91,7 @@ static struct qcom_icc_node *sc7180_osm_l3_nodes[] = {
        [SLAVE_OSM_L3] = &sc7180_osm_l3,
 };
 
-const static struct qcom_icc_desc sc7180_icc_osm_l3 = {
+static const struct qcom_icc_desc sc7180_icc_osm_l3 = {
        .nodes = sc7180_osm_l3_nodes,
        .num_nodes = ARRAY_SIZE(sc7180_osm_l3_nodes),
 };
index b013b80caa45286b59c6ce28f58559531cbd042a..f6c7b969520d0a0434461e35c81f6e6cf00a493b 100644 (file)
@@ -192,7 +192,7 @@ static struct qcom_icc_node *aggre1_noc_nodes[] = {
        [SLAVE_ANOC_PCIE_A1NOC_SNOC] = &qns_pcie_a1noc_snoc,
 };
 
-const static struct qcom_icc_desc sdm845_aggre1_noc = {
+static const struct qcom_icc_desc sdm845_aggre1_noc = {
        .nodes = aggre1_noc_nodes,
        .num_nodes = ARRAY_SIZE(aggre1_noc_nodes),
        .bcms = aggre1_noc_bcms,
@@ -220,7 +220,7 @@ static struct qcom_icc_node *aggre2_noc_nodes[] = {
        [SLAVE_SERVICE_A2NOC] = &srvc_aggre2_noc,
 };
 
-const static struct qcom_icc_desc sdm845_aggre2_noc = {
+static const struct qcom_icc_desc sdm845_aggre2_noc = {
        .nodes = aggre2_noc_nodes,
        .num_nodes = ARRAY_SIZE(aggre2_noc_nodes),
        .bcms = aggre2_noc_bcms,
@@ -281,7 +281,7 @@ static struct qcom_icc_node *config_noc_nodes[] = {
        [SLAVE_SERVICE_CNOC] = &srvc_cnoc,
 };
 
-const static struct qcom_icc_desc sdm845_config_noc = {
+static const struct qcom_icc_desc sdm845_config_noc = {
        .nodes = config_noc_nodes,
        .num_nodes = ARRAY_SIZE(config_noc_nodes),
        .bcms = config_noc_bcms,
@@ -297,7 +297,7 @@ static struct qcom_icc_node *dc_noc_nodes[] = {
        [SLAVE_MEM_NOC_CFG] = &qhs_memnoc,
 };
 
-const static struct qcom_icc_desc sdm845_dc_noc = {
+static const struct qcom_icc_desc sdm845_dc_noc = {
        .nodes = dc_noc_nodes,
        .num_nodes = ARRAY_SIZE(dc_noc_nodes),
        .bcms = dc_noc_bcms,
@@ -315,7 +315,7 @@ static struct qcom_icc_node *gladiator_noc_nodes[] = {
        [SLAVE_SERVICE_GNOC] = &srvc_gnoc,
 };
 
-const static struct qcom_icc_desc sdm845_gladiator_noc = {
+static const struct qcom_icc_desc sdm845_gladiator_noc = {
        .nodes = gladiator_noc_nodes,
        .num_nodes = ARRAY_SIZE(gladiator_noc_nodes),
        .bcms = gladiator_noc_bcms,
@@ -350,7 +350,7 @@ static struct qcom_icc_node *mem_noc_nodes[] = {
        [SLAVE_EBI1] = &ebi,
 };
 
-const static struct qcom_icc_desc sdm845_mem_noc = {
+static const struct qcom_icc_desc sdm845_mem_noc = {
        .nodes = mem_noc_nodes,
        .num_nodes = ARRAY_SIZE(mem_noc_nodes),
        .bcms = mem_noc_bcms,
@@ -384,7 +384,7 @@ static struct qcom_icc_node *mmss_noc_nodes[] = {
        [SLAVE_CAMNOC_UNCOMP] = &qns_camnoc_uncomp,
 };
 
-const static struct qcom_icc_desc sdm845_mmss_noc = {
+static const struct qcom_icc_desc sdm845_mmss_noc = {
        .nodes = mmss_noc_nodes,
        .num_nodes = ARRAY_SIZE(mmss_noc_nodes),
        .bcms = mmss_noc_bcms,
@@ -430,7 +430,7 @@ static struct qcom_icc_node *system_noc_nodes[] = {
        [SLAVE_TCU] = &xs_sys_tcu_cfg,
 };
 
-const static struct qcom_icc_desc sdm845_system_noc = {
+static const struct qcom_icc_desc sdm845_system_noc = {
        .nodes = system_noc_nodes,
        .num_nodes = ARRAY_SIZE(system_noc_nodes),
        .bcms = system_noc_bcms,
index 58b4a4dbfc78b9a59f5f26a6683c1aaf03dafebd..2ab07ce17abb49a2964e08e9e8386ff8b79ba58d 100644 (file)
@@ -362,7 +362,7 @@ config IPMMU_VMSA
 
 config SPAPR_TCE_IOMMU
        bool "sPAPR TCE IOMMU Support"
-       depends on PPC_POWERNV || PPC_PSERIES || (PPC && COMPILE_TEST)
+       depends on PPC_POWERNV || PPC_PSERIES
        select IOMMU_API
        help
          Enables bits of IOMMU API required by VFIO. The iommu_ops
@@ -457,7 +457,7 @@ config S390_AP_IOMMU
 
 config MTK_IOMMU
        bool "MTK IOMMU Support"
-       depends on ARM || ARM64 || COMPILE_TEST
+       depends on HAS_DMA
        depends on ARCH_MEDIATEK || COMPILE_TEST
        select ARM_DMA_USE_IOMMU
        select IOMMU_API
index 20cce366e951813908aa2e7cb3cc8bcd474cf6c3..1dc3718560d0e8285695af0a7320e2a6bb131774 100644 (file)
@@ -101,6 +101,8 @@ struct kmem_cache *amd_iommu_irq_cache;
 static void update_domain(struct protection_domain *domain);
 static int protection_domain_init(struct protection_domain *domain);
 static void detach_device(struct device *dev);
+static void update_and_flush_device_table(struct protection_domain *domain,
+                                         struct domain_pgtable *pgtable);
 
 /****************************************************************************
  *
@@ -151,6 +153,26 @@ static struct protection_domain *to_pdomain(struct iommu_domain *dom)
        return container_of(dom, struct protection_domain, domain);
 }
 
+static void amd_iommu_domain_get_pgtable(struct protection_domain *domain,
+                                        struct domain_pgtable *pgtable)
+{
+       u64 pt_root = atomic64_read(&domain->pt_root);
+
+       pgtable->root = (u64 *)(pt_root & PAGE_MASK);
+       pgtable->mode = pt_root & 7; /* lowest 3 bits encode pgtable mode */
+}
+
+static u64 amd_iommu_domain_encode_pgtable(u64 *root, int mode)
+{
+       u64 pt_root;
+
+       /* lowest 3 bits encode pgtable mode */
+       pt_root = mode & 7;
+       pt_root |= (u64)root;
+
+       return pt_root;
+}
+
 static struct iommu_dev_data *alloc_dev_data(u16 devid)
 {
        struct iommu_dev_data *dev_data;
@@ -1397,13 +1419,18 @@ static struct page *free_sub_pt(unsigned long root, int mode,
 
 static void free_pagetable(struct protection_domain *domain)
 {
-       unsigned long root = (unsigned long)domain->pt_root;
+       struct domain_pgtable pgtable;
        struct page *freelist = NULL;
+       unsigned long root;
 
-       BUG_ON(domain->mode < PAGE_MODE_NONE ||
-              domain->mode > PAGE_MODE_6_LEVEL);
+       amd_iommu_domain_get_pgtable(domain, &pgtable);
+       atomic64_set(&domain->pt_root, 0);
 
-       freelist = free_sub_pt(root, domain->mode, freelist);
+       BUG_ON(pgtable.mode < PAGE_MODE_NONE ||
+              pgtable.mode > PAGE_MODE_6_LEVEL);
+
+       root = (unsigned long)pgtable.root;
+       freelist = free_sub_pt(root, pgtable.mode, freelist);
 
        free_page_list(freelist);
 }
@@ -1417,24 +1444,39 @@ static bool increase_address_space(struct protection_domain *domain,
                                   unsigned long address,
                                   gfp_t gfp)
 {
+       struct domain_pgtable pgtable;
        unsigned long flags;
-       bool ret = false;
-       u64 *pte;
+       bool ret = true;
+       u64 *pte, root;
 
        spin_lock_irqsave(&domain->lock, flags);
 
-       if (address <= PM_LEVEL_SIZE(domain->mode) ||
-           WARN_ON_ONCE(domain->mode == PAGE_MODE_6_LEVEL))
+       amd_iommu_domain_get_pgtable(domain, &pgtable);
+
+       if (address <= PM_LEVEL_SIZE(pgtable.mode))
+               goto out;
+
+       ret = false;
+       if (WARN_ON_ONCE(pgtable.mode == PAGE_MODE_6_LEVEL))
                goto out;
 
        pte = (void *)get_zeroed_page(gfp);
        if (!pte)
                goto out;
 
-       *pte             = PM_LEVEL_PDE(domain->mode,
-                                       iommu_virt_to_phys(domain->pt_root));
-       domain->pt_root  = pte;
-       domain->mode    += 1;
+       *pte = PM_LEVEL_PDE(pgtable.mode, iommu_virt_to_phys(pgtable.root));
+
+       pgtable.root  = pte;
+       pgtable.mode += 1;
+       update_and_flush_device_table(domain, &pgtable);
+       domain_flush_complete(domain);
+
+       /*
+        * Device Table needs to be updated and flushed before the new root can
+        * be published.
+        */
+       root = amd_iommu_domain_encode_pgtable(pte, pgtable.mode);
+       atomic64_set(&domain->pt_root, root);
 
        ret = true;
 
@@ -1451,16 +1493,29 @@ static u64 *alloc_pte(struct protection_domain *domain,
                      gfp_t gfp,
                      bool *updated)
 {
+       struct domain_pgtable pgtable;
        int level, end_lvl;
        u64 *pte, *page;
 
        BUG_ON(!is_power_of_2(page_size));
 
-       while (address > PM_LEVEL_SIZE(domain->mode))
-               *updated = increase_address_space(domain, address, gfp) || *updated;
+       amd_iommu_domain_get_pgtable(domain, &pgtable);
+
+       while (address > PM_LEVEL_SIZE(pgtable.mode)) {
+               /*
+                * Return an error if there is no memory to update the
+                * page-table.
+                */
+               if (!increase_address_space(domain, address, gfp))
+                       return NULL;
+
+               /* Read new values to check if update was successful */
+               amd_iommu_domain_get_pgtable(domain, &pgtable);
+       }
+
 
-       level   = domain->mode - 1;
-       pte     = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
+       level   = pgtable.mode - 1;
+       pte     = &pgtable.root[PM_LEVEL_INDEX(level, address)];
        address = PAGE_SIZE_ALIGN(address, page_size);
        end_lvl = PAGE_SIZE_LEVEL(page_size);
 
@@ -1536,16 +1591,19 @@ static u64 *fetch_pte(struct protection_domain *domain,
                      unsigned long address,
                      unsigned long *page_size)
 {
+       struct domain_pgtable pgtable;
        int level;
        u64 *pte;
 
        *page_size = 0;
 
-       if (address > PM_LEVEL_SIZE(domain->mode))
+       amd_iommu_domain_get_pgtable(domain, &pgtable);
+
+       if (address > PM_LEVEL_SIZE(pgtable.mode))
                return NULL;
 
-       level      =  domain->mode - 1;
-       pte        = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
+       level      =  pgtable.mode - 1;
+       pte        = &pgtable.root[PM_LEVEL_INDEX(level, address)];
        *page_size =  PTE_LEVEL_PAGE_SIZE(level);
 
        while (level > 0) {
@@ -1660,7 +1718,13 @@ out:
                unsigned long flags;
 
                spin_lock_irqsave(&dom->lock, flags);
-               update_domain(dom);
+               /*
+                * Flush domain TLB(s) and wait for completion. Any Device-Table
+                * Updates and flushing already happened in
+                * increase_address_space().
+                */
+               domain_flush_tlb_pde(dom);
+               domain_flush_complete(dom);
                spin_unlock_irqrestore(&dom->lock, flags);
        }
 
@@ -1806,6 +1870,7 @@ static void dma_ops_domain_free(struct protection_domain *domain)
 static struct protection_domain *dma_ops_domain_alloc(void)
 {
        struct protection_domain *domain;
+       u64 *pt_root, root;
 
        domain = kzalloc(sizeof(struct protection_domain), GFP_KERNEL);
        if (!domain)
@@ -1814,12 +1879,14 @@ static struct protection_domain *dma_ops_domain_alloc(void)
        if (protection_domain_init(domain))
                goto free_domain;
 
-       domain->mode = PAGE_MODE_3_LEVEL;
-       domain->pt_root = (void *)get_zeroed_page(GFP_KERNEL);
-       domain->flags = PD_DMA_OPS_MASK;
-       if (!domain->pt_root)
+       pt_root = (void *)get_zeroed_page(GFP_KERNEL);
+       if (!pt_root)
                goto free_domain;
 
+       root = amd_iommu_domain_encode_pgtable(pt_root, PAGE_MODE_3_LEVEL);
+       atomic64_set(&domain->pt_root, root);
+       domain->flags = PD_DMA_OPS_MASK;
+
        if (iommu_get_dma_cookie(&domain->domain) == -ENOMEM)
                goto free_domain;
 
@@ -1841,16 +1908,17 @@ static bool dma_ops_domain(struct protection_domain *domain)
 }
 
 static void set_dte_entry(u16 devid, struct protection_domain *domain,
+                         struct domain_pgtable *pgtable,
                          bool ats, bool ppr)
 {
        u64 pte_root = 0;
        u64 flags = 0;
        u32 old_domid;
 
-       if (domain->mode != PAGE_MODE_NONE)
-               pte_root = iommu_virt_to_phys(domain->pt_root);
+       if (pgtable->mode != PAGE_MODE_NONE)
+               pte_root = iommu_virt_to_phys(pgtable->root);
 
-       pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK)
+       pte_root |= (pgtable->mode & DEV_ENTRY_MODE_MASK)
                    << DEV_ENTRY_MODE_SHIFT;
        pte_root |= DTE_FLAG_IR | DTE_FLAG_IW | DTE_FLAG_V | DTE_FLAG_TV;
 
@@ -1923,6 +1991,7 @@ static void clear_dte_entry(u16 devid)
 static void do_attach(struct iommu_dev_data *dev_data,
                      struct protection_domain *domain)
 {
+       struct domain_pgtable pgtable;
        struct amd_iommu *iommu;
        bool ats;
 
@@ -1938,7 +2007,9 @@ static void do_attach(struct iommu_dev_data *dev_data,
        domain->dev_cnt                 += 1;
 
        /* Update device table */
-       set_dte_entry(dev_data->devid, domain, ats, dev_data->iommu_v2);
+       amd_iommu_domain_get_pgtable(domain, &pgtable);
+       set_dte_entry(dev_data->devid, domain, &pgtable,
+                     ats, dev_data->iommu_v2);
        clone_aliases(dev_data->pdev);
 
        device_flush_dte(dev_data);
@@ -2249,23 +2320,36 @@ static int amd_iommu_domain_get_attr(struct iommu_domain *domain,
  *
  *****************************************************************************/
 
-static void update_device_table(struct protection_domain *domain)
+static void update_device_table(struct protection_domain *domain,
+                               struct domain_pgtable *pgtable)
 {
        struct iommu_dev_data *dev_data;
 
        list_for_each_entry(dev_data, &domain->dev_list, list) {
-               set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled,
-                             dev_data->iommu_v2);
+               set_dte_entry(dev_data->devid, domain, pgtable,
+                             dev_data->ats.enabled, dev_data->iommu_v2);
                clone_aliases(dev_data->pdev);
        }
 }
 
+static void update_and_flush_device_table(struct protection_domain *domain,
+                                         struct domain_pgtable *pgtable)
+{
+       update_device_table(domain, pgtable);
+       domain_flush_devices(domain);
+}
+
 static void update_domain(struct protection_domain *domain)
 {
-       update_device_table(domain);
+       struct domain_pgtable pgtable;
 
-       domain_flush_devices(domain);
+       /* Update device table */
+       amd_iommu_domain_get_pgtable(domain, &pgtable);
+       update_and_flush_device_table(domain, &pgtable);
+
+       /* Flush domain TLB(s) and wait for completion */
        domain_flush_tlb_pde(domain);
+       domain_flush_complete(domain);
 }
 
 int __init amd_iommu_init_api(void)
@@ -2375,6 +2459,7 @@ out_err:
 static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
 {
        struct protection_domain *pdomain;
+       u64 *pt_root, root;
 
        switch (type) {
        case IOMMU_DOMAIN_UNMANAGED:
@@ -2382,13 +2467,15 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
                if (!pdomain)
                        return NULL;
 
-               pdomain->mode    = PAGE_MODE_3_LEVEL;
-               pdomain->pt_root = (void *)get_zeroed_page(GFP_KERNEL);
-               if (!pdomain->pt_root) {
+               pt_root = (void *)get_zeroed_page(GFP_KERNEL);
+               if (!pt_root) {
                        protection_domain_free(pdomain);
                        return NULL;
                }
 
+               root = amd_iommu_domain_encode_pgtable(pt_root, PAGE_MODE_3_LEVEL);
+               atomic64_set(&pdomain->pt_root, root);
+
                pdomain->domain.geometry.aperture_start = 0;
                pdomain->domain.geometry.aperture_end   = ~0ULL;
                pdomain->domain.geometry.force_aperture = true;
@@ -2406,7 +2493,7 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
                if (!pdomain)
                        return NULL;
 
-               pdomain->mode = PAGE_MODE_NONE;
+               atomic64_set(&pdomain->pt_root, PAGE_MODE_NONE);
                break;
        default:
                return NULL;
@@ -2418,6 +2505,7 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
 static void amd_iommu_domain_free(struct iommu_domain *dom)
 {
        struct protection_domain *domain;
+       struct domain_pgtable pgtable;
 
        domain = to_pdomain(dom);
 
@@ -2435,7 +2523,9 @@ static void amd_iommu_domain_free(struct iommu_domain *dom)
                dma_ops_domain_free(domain);
                break;
        default:
-               if (domain->mode != PAGE_MODE_NONE)
+               amd_iommu_domain_get_pgtable(domain, &pgtable);
+
+               if (pgtable.mode != PAGE_MODE_NONE)
                        free_pagetable(domain);
 
                if (domain->flags & PD_IOMMUV2_MASK)
@@ -2518,10 +2608,12 @@ static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
                         gfp_t gfp)
 {
        struct protection_domain *domain = to_pdomain(dom);
+       struct domain_pgtable pgtable;
        int prot = 0;
        int ret;
 
-       if (domain->mode == PAGE_MODE_NONE)
+       amd_iommu_domain_get_pgtable(domain, &pgtable);
+       if (pgtable.mode == PAGE_MODE_NONE)
                return -EINVAL;
 
        if (iommu_prot & IOMMU_READ)
@@ -2541,8 +2633,10 @@ static size_t amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
                              struct iommu_iotlb_gather *gather)
 {
        struct protection_domain *domain = to_pdomain(dom);
+       struct domain_pgtable pgtable;
 
-       if (domain->mode == PAGE_MODE_NONE)
+       amd_iommu_domain_get_pgtable(domain, &pgtable);
+       if (pgtable.mode == PAGE_MODE_NONE)
                return 0;
 
        return iommu_unmap_page(domain, iova, page_size);
@@ -2553,9 +2647,11 @@ static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
 {
        struct protection_domain *domain = to_pdomain(dom);
        unsigned long offset_mask, pte_pgsize;
+       struct domain_pgtable pgtable;
        u64 *pte, __pte;
 
-       if (domain->mode == PAGE_MODE_NONE)
+       amd_iommu_domain_get_pgtable(domain, &pgtable);
+       if (pgtable.mode == PAGE_MODE_NONE)
                return iova;
 
        pte = fetch_pte(domain, iova, &pte_pgsize);
@@ -2708,16 +2804,26 @@ EXPORT_SYMBOL(amd_iommu_unregister_ppr_notifier);
 void amd_iommu_domain_direct_map(struct iommu_domain *dom)
 {
        struct protection_domain *domain = to_pdomain(dom);
+       struct domain_pgtable pgtable;
        unsigned long flags;
+       u64 pt_root;
 
        spin_lock_irqsave(&domain->lock, flags);
 
+       /* First save pgtable configuration*/
+       amd_iommu_domain_get_pgtable(domain, &pgtable);
+
        /* Update data structure */
-       domain->mode    = PAGE_MODE_NONE;
+       pt_root = amd_iommu_domain_encode_pgtable(NULL, PAGE_MODE_NONE);
+       atomic64_set(&domain->pt_root, pt_root);
 
        /* Make changes visible to IOMMUs */
        update_domain(domain);
 
+       /* Restore old pgtable in domain->ptroot to free page-table */
+       pt_root = amd_iommu_domain_encode_pgtable(pgtable.root, pgtable.mode);
+       atomic64_set(&domain->pt_root, pt_root);
+
        /* Page-table is not visible to IOMMU anymore, so free it */
        free_pagetable(domain);
 
@@ -2908,9 +3014,11 @@ static u64 *__get_gcr3_pte(u64 *root, int level, int pasid, bool alloc)
 static int __set_gcr3(struct protection_domain *domain, int pasid,
                      unsigned long cr3)
 {
+       struct domain_pgtable pgtable;
        u64 *pte;
 
-       if (domain->mode != PAGE_MODE_NONE)
+       amd_iommu_domain_get_pgtable(domain, &pgtable);
+       if (pgtable.mode != PAGE_MODE_NONE)
                return -EINVAL;
 
        pte = __get_gcr3_pte(domain->gcr3_tbl, domain->glx, pasid, true);
@@ -2924,9 +3032,11 @@ static int __set_gcr3(struct protection_domain *domain, int pasid,
 
 static int __clear_gcr3(struct protection_domain *domain, int pasid)
 {
+       struct domain_pgtable pgtable;
        u64 *pte;
 
-       if (domain->mode != PAGE_MODE_NONE)
+       amd_iommu_domain_get_pgtable(domain, &pgtable);
+       if (pgtable.mode != PAGE_MODE_NONE)
                return -EINVAL;
 
        pte = __get_gcr3_pte(domain->gcr3_tbl, domain->glx, pasid, false);
index 6be3853a5d978e09b8aeebb02daaec01e3a80cc9..2b9a67ecc6ac4e04d7a5ece7634e013e94a46dc4 100644 (file)
@@ -2936,7 +2936,7 @@ static int __init parse_amd_iommu_intr(char *str)
 {
        for (; *str; ++str) {
                if (strncmp(str, "legacy", 6) == 0) {
-                       amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
+                       amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY_GA;
                        break;
                }
                if (strncmp(str, "vapic", 5) == 0) {
index ca8c4522045b35d1c57c76711a2af9cf0f03a439..7a8fdec138bd197d7858aa47aa57ffa532ecdc99 100644 (file)
@@ -468,8 +468,7 @@ struct protection_domain {
                                       iommu core code */
        spinlock_t lock;        /* mostly used to lock the page table*/
        u16 id;                 /* the domain id written to the device table */
-       int mode;               /* paging mode (0-6 levels) */
-       u64 *pt_root;           /* page table root pointer */
+       atomic64_t pt_root;     /* pgtable root and pgtable mode */
        int glx;                /* Number of levels for GCR3 table */
        u64 *gcr3_tbl;          /* Guest CR3 table */
        unsigned long flags;    /* flags to find out type of domain */
@@ -477,6 +476,12 @@ struct protection_domain {
        unsigned dev_iommu[MAX_IOMMUS]; /* per-IOMMU reference count */
 };
 
+/* For decocded pt_root */
+struct domain_pgtable {
+       int mode;
+       u64 *root;
+};
+
 /*
  * Structure where we save information about one hardware AMD IOMMU in the
  * system.
index ef0a5246700e546d025c668aa58b8d5349e14946..0182cff2c7ac75947bf6a2e746cbe0864a8a5c15 100644 (file)
@@ -371,11 +371,11 @@ int dmar_disabled = 0;
 int dmar_disabled = 1;
 #endif /* CONFIG_INTEL_IOMMU_DEFAULT_ON */
 
-#ifdef INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON
+#ifdef CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON
 int intel_iommu_sm = 1;
 #else
 int intel_iommu_sm;
-#endif /* INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON */
+#endif /* CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON */
 
 int intel_iommu_enabled = 0;
 EXPORT_SYMBOL_GPL(intel_iommu_enabled);
index 2b471419e26c3c5c9564cbf8431dcfad9252a9ca..7b375421afba9ad4d91d424ed1eb2d7e51827f4d 100644 (file)
@@ -170,6 +170,7 @@ static struct dev_iommu *dev_iommu_get(struct device *dev)
 
 static void dev_iommu_free(struct device *dev)
 {
+       iommu_fwspec_free(dev);
        kfree(dev->iommu);
        dev->iommu = NULL;
 }
@@ -1428,7 +1429,7 @@ struct iommu_group *iommu_group_get_for_dev(struct device *dev)
 
        return group;
 }
-EXPORT_SYMBOL(iommu_group_get_for_dev);
+EXPORT_SYMBOL_GPL(iommu_group_get_for_dev);
 
 struct iommu_domain *iommu_group_default_domain(struct iommu_group *group)
 {
index 0e2a96467767b531dc615fa0e50ae9217af9d380..5b3b270972f809c62eb11714613e53e75fc63320 100644 (file)
@@ -824,8 +824,11 @@ static int qcom_iommu_device_probe(struct platform_device *pdev)
        qcom_iommu->dev = dev;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res)
+       if (res) {
                qcom_iommu->local_base = devm_ioremap_resource(dev, res);
+               if (IS_ERR(qcom_iommu->local_base))
+                       return PTR_ERR(qcom_iommu->local_base);
+       }
 
        qcom_iommu->iface_clk = devm_clk_get(dev, "iface");
        if (IS_ERR(qcom_iommu->iface_clk)) {
index d5cac4f46ca53e5976184e461af29d75790dedf6..4e1d11af23c81c74ad61a5032fe488c05a7b93fc 100644 (file)
@@ -453,7 +453,7 @@ static int viommu_add_resv_mem(struct viommu_endpoint *vdev,
        if (!region)
                return -ENOMEM;
 
-       list_add(&vdev->resv_regions, &region->list);
+       list_add(&region->list, &vdev->resv_regions);
        return 0;
 }
 
index eb9bce93cd057e84da94dbe73f092f497520998b..fd7c537fb42ac9f6a18c7da4b93cdb5ede304996 100644 (file)
@@ -416,7 +416,7 @@ static const struct irq_domain_ops bcm7038_l1_domain_ops = {
        .map                    = bcm7038_l1_map,
 };
 
-int __init bcm7038_l1_of_init(struct device_node *dn,
+static int __init bcm7038_l1_of_init(struct device_node *dn,
                              struct device_node *parent)
 {
        struct bcm7038_l1_chip *intc;
index 54d142ccc63a3fab9bc41419b4d89bd3862331d5..124251b0ccbae6bcb6b2d7e7b6c8b448b727733a 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/dma-iommu.h>
 #include <linux/efi.h>
 #include <linux/interrupt.h>
+#include <linux/iopoll.h>
 #include <linux/irqdomain.h>
 #include <linux/list.h>
 #include <linux/log2.h>
@@ -3672,6 +3673,20 @@ out:
        return IRQ_SET_MASK_OK_DONE;
 }
 
+static void its_wait_vpt_parse_complete(void)
+{
+       void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
+       u64 val;
+
+       if (!gic_rdists->has_vpend_valid_dirty)
+               return;
+
+       WARN_ON_ONCE(readq_relaxed_poll_timeout(vlpi_base + GICR_VPENDBASER,
+                                               val,
+                                               !(val & GICR_VPENDBASER_Dirty),
+                                               10, 500));
+}
+
 static void its_vpe_schedule(struct its_vpe *vpe)
 {
        void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
@@ -3702,6 +3717,8 @@ static void its_vpe_schedule(struct its_vpe *vpe)
        val |= vpe->idai ? GICR_VPENDBASER_IDAI : 0;
        val |= GICR_VPENDBASER_Valid;
        gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
+
+       its_wait_vpt_parse_complete();
 }
 
 static void its_vpe_deschedule(struct its_vpe *vpe)
@@ -3910,6 +3927,8 @@ static void its_vpe_4_1_schedule(struct its_vpe *vpe,
        val |= FIELD_PREP(GICR_VPENDBASER_4_1_VPEID, vpe->vpe_id);
 
        gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
+
+       its_wait_vpt_parse_complete();
 }
 
 static void its_vpe_4_1_deschedule(struct its_vpe *vpe,
@@ -4035,6 +4054,7 @@ static int its_sgi_set_affinity(struct irq_data *d,
         * not on the host (since they can only be targetting a vPE).
         * Tell the kernel we've done whatever it asked for.
         */
+       irq_data_update_effective_affinity(d, mask_val);
        return IRQ_SET_MASK_OK;
 }
 
index 9dbc81b6f62e99dfa08ac4fe68054b0422959c86..d7006ef18a0da69be1ea8b7e78c1854616218fc5 100644 (file)
@@ -873,6 +873,7 @@ static int __gic_update_rdist_properties(struct redist_region *region,
        gic_data.rdists.has_rvpeid &= !!(typer & GICR_TYPER_RVPEID);
        gic_data.rdists.has_direct_lpi &= (!!(typer & GICR_TYPER_DirectLPIS) |
                                           gic_data.rdists.has_rvpeid);
+       gic_data.rdists.has_vpend_valid_dirty &= !!(typer & GICR_TYPER_DIRTY);
 
        /* Detect non-sensical configurations */
        if (WARN_ON_ONCE(gic_data.rdists.has_rvpeid && !gic_data.rdists.has_vlpis)) {
@@ -893,10 +894,11 @@ static void gic_update_rdist_properties(void)
        if (WARN_ON(gic_data.ppi_nr == UINT_MAX))
                gic_data.ppi_nr = 0;
        pr_info("%d PPIs implemented\n", gic_data.ppi_nr);
-       pr_info("%sVLPI support, %sdirect LPI support, %sRVPEID support\n",
-               !gic_data.rdists.has_vlpis ? "no " : "",
-               !gic_data.rdists.has_direct_lpi ? "no " : "",
-               !gic_data.rdists.has_rvpeid ? "no " : "");
+       if (gic_data.rdists.has_vlpis)
+               pr_info("GICv4 features: %s%s%s\n",
+                       gic_data.rdists.has_direct_lpi ? "DirectLPI " : "",
+                       gic_data.rdists.has_rvpeid ? "RVPEID " : "",
+                       gic_data.rdists.has_vpend_valid_dirty ? "Valid+Dirty " : "");
 }
 
 /* Check whether it's single security state view */
@@ -1620,6 +1622,7 @@ static int __init gic_init_bases(void __iomem *dist_base,
        gic_data.rdists.has_rvpeid = true;
        gic_data.rdists.has_vlpis = true;
        gic_data.rdists.has_direct_lpi = true;
+       gic_data.rdists.has_vpend_valid_dirty = true;
 
        if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdists.rdist)) {
                err = -ENOMEM;
index 6b566bba263bdec3637aa7a8687cf2816e053971..ff7627b577726e6e887df1de1ef88137a5f5c4d0 100644 (file)
@@ -220,10 +220,16 @@ static int mbigen_irq_domain_alloc(struct irq_domain *domain,
        return 0;
 }
 
+static void mbigen_irq_domain_free(struct irq_domain *domain, unsigned int virq,
+                                  unsigned int nr_irqs)
+{
+       platform_msi_domain_free(domain, virq, nr_irqs);
+}
+
 static const struct irq_domain_ops mbigen_domain_ops = {
        .translate      = mbigen_domain_translate,
        .alloc          = mbigen_irq_domain_alloc,
-       .free           = irq_domain_free_irqs_common,
+       .free           = mbigen_irq_domain_free,
 };
 
 static int mbigen_of_create_domain(struct platform_device *pdev,
index ccc7f823911bd3a12e4baa6eb1a8aeabbcaa455a..bc7aebcc96e9cdd1f31eecc435ca9454a40acacc 100644 (file)
@@ -144,12 +144,17 @@ struct meson_gpio_irq_controller {
 static void meson_gpio_irq_update_bits(struct meson_gpio_irq_controller *ctl,
                                       unsigned int reg, u32 mask, u32 val)
 {
+       unsigned long flags;
        u32 tmp;
 
+       spin_lock_irqsave(&ctl->lock, flags);
+
        tmp = readl_relaxed(ctl->base + reg);
        tmp &= ~mask;
        tmp |= val;
        writel_relaxed(tmp, ctl->base + reg);
+
+       spin_unlock_irqrestore(&ctl->lock, flags);
 }
 
 static void meson_gpio_irq_init_dummy(struct meson_gpio_irq_controller *ctl)
@@ -196,14 +201,15 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl,
                               unsigned long  hwirq,
                               u32 **channel_hwirq)
 {
+       unsigned long flags;
        unsigned int idx;
 
-       spin_lock(&ctl->lock);
+       spin_lock_irqsave(&ctl->lock, flags);
 
        /* Find a free channel */
        idx = find_first_zero_bit(ctl->channel_map, NUM_CHANNEL);
        if (idx >= NUM_CHANNEL) {
-               spin_unlock(&ctl->lock);
+               spin_unlock_irqrestore(&ctl->lock, flags);
                pr_err("No channel available\n");
                return -ENOSPC;
        }
@@ -211,6 +217,8 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl,
        /* Mark the channel as used */
        set_bit(idx, ctl->channel_map);
 
+       spin_unlock_irqrestore(&ctl->lock, flags);
+
        /*
         * Setup the mux of the channel to route the signal of the pad
         * to the appropriate input of the GIC
@@ -225,8 +233,6 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl,
         */
        *channel_hwirq = &(ctl->channel_irqs[idx]);
 
-       spin_unlock(&ctl->lock);
-
        pr_debug("hwirq %lu assigned to channel %d - irq %u\n",
                 hwirq, idx, **channel_hwirq);
 
@@ -287,13 +293,9 @@ static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl,
                        val |= REG_EDGE_POL_LOW(params, idx);
        }
 
-       spin_lock(&ctl->lock);
-
        meson_gpio_irq_update_bits(ctl, REG_EDGE_POL,
                                   REG_EDGE_POL_MASK(params, idx), val);
 
-       spin_unlock(&ctl->lock);
-
        return 0;
 }
 
index 547045d89c4bddcc0d113785fab37c42dd19ec8f..91adf771f1859737157af823d231669e99b7f97b 100644 (file)
@@ -66,7 +66,7 @@ struct mvebu_icu_irq_data {
        unsigned int type;
 };
 
-DEFINE_STATIC_KEY_FALSE(legacy_bindings);
+static DEFINE_STATIC_KEY_FALSE(legacy_bindings);
 
 static void mvebu_icu_init(struct mvebu_icu *icu,
                           struct mvebu_icu_msi_data *msi_data,
index c34fb3ae0ff8158890bd563649cd2a25e3718e1b..d0a71febdadce7e4abb8aafea33a4a2186c83d09 100644 (file)
@@ -56,7 +56,7 @@
 #define     CONTEXT_THRESHOLD          0x00
 #define     CONTEXT_CLAIM              0x04
 
-#define        PLIC_DISABLE_THRESHOLD          0xf
+#define        PLIC_DISABLE_THRESHOLD          0x7
 #define        PLIC_ENABLE_THRESHOLD           0
 
 struct plic_priv {
index 8f6e6b08eadf16f10b2a2444695987bd1db8b8bc..7e3ebf6ed2cd141ae6830d3c2dc659db874e3479 100644 (file)
@@ -37,6 +37,7 @@
 #define VINT_ENABLE_SET_OFFSET 0x0
 #define VINT_ENABLE_CLR_OFFSET 0x8
 #define VINT_STATUS_OFFSET     0x18
+#define VINT_STATUS_MASKED_OFFSET      0x20
 
 /**
  * struct ti_sci_inta_event_desc - Description of an event coming to
@@ -116,7 +117,7 @@ static void ti_sci_inta_irq_handler(struct irq_desc *desc)
        chained_irq_enter(irq_desc_get_chip(desc), desc);
 
        val = readq_relaxed(inta->base + vint_desc->vint_id * 0x1000 +
-                           VINT_STATUS_OFFSET);
+                           VINT_STATUS_MASKED_OFFSET);
 
        for_each_set_bit(bit, &val, MAX_EVENTS_PER_VINT) {
                virq = irq_find_mapping(domain, vint_desc->events[bit].hwirq);
index e325e87c05934cd187a78b273688ea8b82baee55..11e8c7d8b6e89d361f8709251722f8d2e9c598c1 100644 (file)
@@ -743,10 +743,10 @@ check_send(struct isar_hw *isar, u8 rdm)
        }
 }
 
-const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", "NODEF4",
+static const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", "NODEF4",
                       "300", "600", "1200", "2400", "4800", "7200",
                       "9600nt", "9600t", "12000", "14400", "WRONG"};
-const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21",
+static const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21",
                       "Bell103", "V23", "Bell202", "V17", "V29", "V27ter"};
 
 static void
index 58fd137b6ae1a041c8503a62bef175a27a70ff16..3e500098132f1307ae82259a2aba1ec324496bf7 100644 (file)
@@ -585,10 +585,12 @@ static struct pgpath *__map_bio(struct multipath *m, struct bio *bio)
 
        /* Do we need to select a new pgpath? */
        pgpath = READ_ONCE(m->current_pgpath);
-       queue_io = test_bit(MPATHF_QUEUE_IO, &m->flags);
-       if (!pgpath || !queue_io)
+       if (!pgpath || !test_bit(MPATHF_QUEUE_IO, &m->flags))
                pgpath = choose_pgpath(m, bio->bi_iter.bi_size);
 
+       /* MPATHF_QUEUE_IO might have been cleared by choose_pgpath. */
+       queue_io = test_bit(MPATHF_QUEUE_IO, &m->flags);
+
        if ((pgpath && queue_io) ||
            (!pgpath && test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))) {
                /* Queue for the daemon to resubmit */
index 49147e634046da9caa4309e2d7ce712b545e131f..fb41b4f23c4891bd816624f18f8d67b51fbd3e6c 100644 (file)
@@ -435,7 +435,7 @@ int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
        fio->level++;
 
        if (type == DM_VERITY_BLOCK_TYPE_METADATA)
-               block += v->data_blocks;
+               block = block - v->hash_start + v->data_blocks;
 
        /*
         * For RS(M, N), the continuous FEC data is divided into blocks of N
index 114927da9cc9a70689e1badf04ebad06dd9a52c8..613c171b1b6d2f37d49b4bfbdc9b55e7bedd0527 100644 (file)
@@ -931,6 +931,24 @@ static int writecache_alloc_entries(struct dm_writecache *wc)
        return 0;
 }
 
+static int writecache_read_metadata(struct dm_writecache *wc, sector_t n_sectors)
+{
+       struct dm_io_region region;
+       struct dm_io_request req;
+
+       region.bdev = wc->ssd_dev->bdev;
+       region.sector = wc->start_sector;
+       region.count = n_sectors;
+       req.bi_op = REQ_OP_READ;
+       req.bi_op_flags = REQ_SYNC;
+       req.mem.type = DM_IO_VMA;
+       req.mem.ptr.vma = (char *)wc->memory_map;
+       req.client = wc->dm_io;
+       req.notify.fn = NULL;
+
+       return dm_io(&req, 1, &region, NULL);
+}
+
 static void writecache_resume(struct dm_target *ti)
 {
        struct dm_writecache *wc = ti->private;
@@ -941,8 +959,18 @@ static void writecache_resume(struct dm_target *ti)
 
        wc_lock(wc);
 
-       if (WC_MODE_PMEM(wc))
+       if (WC_MODE_PMEM(wc)) {
                persistent_memory_invalidate_cache(wc->memory_map, wc->memory_map_size);
+       } else {
+               r = writecache_read_metadata(wc, wc->metadata_sectors);
+               if (r) {
+                       size_t sb_entries_offset;
+                       writecache_error(wc, r, "unable to read metadata: %d", r);
+                       sb_entries_offset = offsetof(struct wc_memory_superblock, entries);
+                       memset((char *)wc->memory_map + sb_entries_offset, -1,
+                              (wc->metadata_sectors << SECTOR_SHIFT) - sb_entries_offset);
+               }
+       }
 
        wc->tree = RB_ROOT;
        INIT_LIST_HEAD(&wc->lru);
@@ -2102,6 +2130,12 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
                ti->error = "Invalid block size";
                goto bad;
        }
+       if (wc->block_size < bdev_logical_block_size(wc->dev->bdev) ||
+           wc->block_size < bdev_logical_block_size(wc->ssd_dev->bdev)) {
+               r = -EINVAL;
+               ti->error = "Block size is smaller than device logical block size";
+               goto bad;
+       }
        wc->block_size_bits = __ffs(wc->block_size);
 
        wc->max_writeback_jobs = MAX_WRITEBACK_JOBS;
@@ -2200,8 +2234,6 @@ invalid_optional:
                        goto bad;
                }
        } else {
-               struct dm_io_region region;
-               struct dm_io_request req;
                size_t n_blocks, n_metadata_blocks;
                uint64_t n_bitmap_bits;
 
@@ -2258,19 +2290,9 @@ invalid_optional:
                        goto bad;
                }
 
-               region.bdev = wc->ssd_dev->bdev;
-               region.sector = wc->start_sector;
-               region.count = wc->metadata_sectors;
-               req.bi_op = REQ_OP_READ;
-               req.bi_op_flags = REQ_SYNC;
-               req.mem.type = DM_IO_VMA;
-               req.mem.ptr.vma = (char *)wc->memory_map;
-               req.client = wc->dm_io;
-               req.notify.fn = NULL;
-
-               r = dm_io(&req, 1, &region, NULL);
+               r = writecache_read_metadata(wc, wc->block_size >> SECTOR_SHIFT);
                if (r) {
-                       ti->error = "Unable to read metadata";
+                       ti->error = "Unable to read first block of metadata";
                        goto bad;
                }
        }
index 668418d7ea770924b778b070d051e1e63a83d213..f620442addf529ea5d7a663f0e57a61b03a3c966 100644 (file)
@@ -1465,6 +1465,13 @@ static const struct mei_cfg mei_me_pch12_cfg = {
        MEI_CFG_DMA_128,
 };
 
+/* LBG with quirk for SPS Firmware exclusion */
+static const struct mei_cfg mei_me_pch12_sps_cfg = {
+       MEI_CFG_PCH8_HFS,
+       MEI_CFG_FW_VER_SUPP,
+       MEI_CFG_FW_SPS,
+};
+
 /* Tiger Lake and newer devices */
 static const struct mei_cfg mei_me_pch15_cfg = {
        MEI_CFG_PCH8_HFS,
@@ -1487,6 +1494,7 @@ static const struct mei_cfg *const mei_cfg_list[] = {
        [MEI_ME_PCH8_CFG] = &mei_me_pch8_cfg,
        [MEI_ME_PCH8_SPS_CFG] = &mei_me_pch8_sps_cfg,
        [MEI_ME_PCH12_CFG] = &mei_me_pch12_cfg,
+       [MEI_ME_PCH12_SPS_CFG] = &mei_me_pch12_sps_cfg,
        [MEI_ME_PCH15_CFG] = &mei_me_pch15_cfg,
 };
 
index 4a8d4dcd5a91b449f8a3a7c1cd8111f186acc5d7..b6b94e2114645f8a18fb503a5d91908e625857de 100644 (file)
@@ -80,6 +80,9 @@ struct mei_me_hw {
  *                         servers platforms with quirk for
  *                         SPS firmware exclusion.
  * @MEI_ME_PCH12_CFG:      Platform Controller Hub Gen12 and newer
+ * @MEI_ME_PCH12_SPS_CFG:  Platform Controller Hub Gen12 and newer
+ *                         servers platforms with quirk for
+ *                         SPS firmware exclusion.
  * @MEI_ME_PCH15_CFG:      Platform Controller Hub Gen15 and newer
  * @MEI_ME_NUM_CFG:        Upper Sentinel.
  */
@@ -93,6 +96,7 @@ enum mei_cfg_idx {
        MEI_ME_PCH8_CFG,
        MEI_ME_PCH8_SPS_CFG,
        MEI_ME_PCH12_CFG,
+       MEI_ME_PCH12_SPS_CFG,
        MEI_ME_PCH15_CFG,
        MEI_ME_NUM_CFG,
 };
index 3d21c38e2dbbbc267db6b069b3cf2be7b5b5883d..a1ed375fed37443084d5eabbcd74faef157ec52d 100644 (file)
@@ -70,7 +70,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
        {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_CFG)},
-       {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH12_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH12_SPS_CFG)},
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, MEI_ME_PCH8_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, MEI_ME_PCH8_CFG)},
@@ -203,11 +203,12 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
        hw = to_me_hw(dev);
        hw->mem_addr = pcim_iomap_table(pdev)[0];
-       hw->irq = pdev->irq;
        hw->read_fws = mei_me_read_fws;
 
        pci_enable_msi(pdev);
 
+       hw->irq = pdev->irq;
+
         /* request and enable interrupt */
        irqflags = pci_dev_msi_enabled(pdev) ? IRQF_ONESHOT : IRQF_SHARED;
 
index 8f201d019f5a4d072255284d31f73c450786c4ef..3bfe72c59864cf24e2b762c7f6618289acf916ee 100644 (file)
@@ -116,7 +116,7 @@ config MIC_COSM
 
 config VOP
        tristate "VOP Driver"
-       depends on VOP_BUS
+       depends on VOP_BUS && VHOST_DPN
        select VHOST_RING
        select VIRTIO
        help
index 5bd0ab8b236a5707040b5c13bb5e204ff3a5938e..baa6314f69b411d80eb97d4d82480203b5338892 100644 (file)
@@ -878,7 +878,7 @@ static int mmc_send_hpi_cmd(struct mmc_card *card)
  *     Issued High Priority Interrupt, and check for card status
  *     until out-of prg-state.
  */
-int mmc_interrupt_hpi(struct mmc_card *card)
+static int mmc_interrupt_hpi(struct mmc_card *card)
 {
        int err;
        u32 status;
index c2239ee2c0ef74ac1c1e6a102388d0d3e6ddf6ab..75934f3c117eba9576ceb7566f21033876eb463b 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/delay.h>
 #include <linux/highmem.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
@@ -349,12 +350,16 @@ static int cqhci_enable(struct mmc_host *mmc, struct mmc_card *card)
 /* CQHCI is idle and should halt immediately, so set a small timeout */
 #define CQHCI_OFF_TIMEOUT 100
 
+static u32 cqhci_read_ctl(struct cqhci_host *cq_host)
+{
+       return cqhci_readl(cq_host, CQHCI_CTL);
+}
+
 static void cqhci_off(struct mmc_host *mmc)
 {
        struct cqhci_host *cq_host = mmc->cqe_private;
-       ktime_t timeout;
-       bool timed_out;
        u32 reg;
+       int err;
 
        if (!cq_host->enabled || !mmc->cqe_on || cq_host->recovery_halt)
                return;
@@ -364,15 +369,9 @@ static void cqhci_off(struct mmc_host *mmc)
 
        cqhci_writel(cq_host, CQHCI_HALT, CQHCI_CTL);
 
-       timeout = ktime_add_us(ktime_get(), CQHCI_OFF_TIMEOUT);
-       while (1) {
-               timed_out = ktime_compare(ktime_get(), timeout) > 0;
-               reg = cqhci_readl(cq_host, CQHCI_CTL);
-               if ((reg & CQHCI_HALT) || timed_out)
-                       break;
-       }
-
-       if (timed_out)
+       err = readx_poll_timeout(cqhci_read_ctl, cq_host, reg,
+                                reg & CQHCI_HALT, 0, CQHCI_OFF_TIMEOUT);
+       if (err < 0)
                pr_err("%s: cqhci: CQE stuck on\n", mmc_hostname(mmc));
        else
                pr_debug("%s: cqhci: CQE off\n", mmc_hostname(mmc));
index 8b038e7b2cd312e2c5e3d123b8a148595aadbe1d..2e58743d83bb5feb4fbe28c531d27605904c476c 100644 (file)
@@ -357,14 +357,6 @@ static void meson_mx_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
                meson_mx_mmc_start_cmd(mmc, mrq->cmd);
 }
 
-static int meson_mx_mmc_card_busy(struct mmc_host *mmc)
-{
-       struct meson_mx_mmc_host *host = mmc_priv(mmc);
-       u32 irqc = readl(host->base + MESON_MX_SDIO_IRQC);
-
-       return !!(irqc & MESON_MX_SDIO_IRQC_FORCE_DATA_DAT_MASK);
-}
-
 static void meson_mx_mmc_read_response(struct mmc_host *mmc,
                                       struct mmc_command *cmd)
 {
@@ -506,7 +498,6 @@ static void meson_mx_mmc_timeout(struct timer_list *t)
 static struct mmc_host_ops meson_mx_mmc_ops = {
        .request                = meson_mx_mmc_request,
        .set_ios                = meson_mx_mmc_set_ios,
-       .card_busy              = meson_mx_mmc_card_busy,
        .get_cd                 = mmc_gpio_get_cd,
        .get_ro                 = mmc_gpio_get_ro,
 };
@@ -570,7 +561,7 @@ static int meson_mx_mmc_add_host(struct meson_mx_mmc_host *host)
        mmc->f_max = clk_round_rate(host->cfg_div_clk,
                                    clk_get_rate(host->parent_clk));
 
-       mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;
+       mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23 | MMC_CAP_WAIT_WHILE_BUSY;
        mmc->ops = &meson_mx_mmc_ops;
 
        ret = mmc_of_parse(mmc);
index 09ff7315eb5ee8dfeb82f97bad4f0ef0300a993b..a8bcb3f16aa403a316ad705a94ad410ed8b6a682 100644 (file)
@@ -2087,6 +2087,8 @@ static int sdhci_msm_probe(struct platform_device *pdev)
                goto clk_disable;
        }
 
+       msm_host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_NEED_RSP_BUSY;
+
        pm_runtime_get_noresume(&pdev->dev);
        pm_runtime_set_active(&pdev->dev);
        pm_runtime_enable(&pdev->dev);
index 525de2454a4de1d9d17b628d6d27a2898eaea36c..2527244c2ae16f1e7c2c11491c4c3be3a49fc9f9 100644 (file)
@@ -601,6 +601,9 @@ static int intel_select_drive_strength(struct mmc_card *card,
        struct sdhci_pci_slot *slot = sdhci_priv(host);
        struct intel_host *intel_host = sdhci_pci_priv(slot);
 
+       if (!(mmc_driver_type_mask(intel_host->drv_strength) & card_drv))
+               return 0;
+
        return intel_host->drv_strength;
 }
 
index 1dea1ba66f7b4e8a05e48a8a0f4fbac8875c2a14..4703cd540c7fd89dc67b6399c37fce24f88fed5a 100644 (file)
@@ -235,6 +235,16 @@ static void xenon_voltage_switch(struct sdhci_host *host)
 {
        /* Wait for 5ms after set 1.8V signal enable bit */
        usleep_range(5000, 5500);
+
+       /*
+        * For some reason the controller's Host Control2 register reports
+        * the bit representing 1.8V signaling as 0 when read after it was
+        * written as 1. Subsequent read reports 1.
+        *
+        * Since this may cause some issues, do an empty read of the Host
+        * Control2 register here to circumvent this.
+        */
+       sdhci_readw(host, SDHCI_HOST_CONTROL2);
 }
 
 static const struct sdhci_ops sdhci_xenon_ops = {
index 06426fc5c990ba1bbdd56564f67b59ce3068e2ce..f781c46cd4af9afc2458a1fe0d53c95bbbb8abfb 100644 (file)
@@ -1483,7 +1483,7 @@ static void __exit most_exit(void)
        ida_destroy(&mdev_id);
 }
 
-module_init(most_init);
+subsys_initcall(most_init);
 module_exit(most_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
index 7ddb742de1fe54428c82effde48c654f27afcf6e..653923896205c2103b9d123ee6c68196c15a0bc2 100644 (file)
@@ -18,3 +18,5 @@ spi-nor-objs                  += winbond.o
 spi-nor-objs                   += xilinx.o
 spi-nor-objs                   += xmc.o
 obj-$(CONFIG_MTD_SPI_NOR)      += spi-nor.o
+
+obj-$(CONFIG_MTD_SPI_NOR)      += controllers/
index 9db0570c5bebbeb0dad6b1097bb4aae6c6dcd233..661c25eb1c46f0f436fcd0b525cea9fceb5c899b 100644 (file)
@@ -50,7 +50,7 @@ config CAIF_HSI
 
 config CAIF_VIRTIO
        tristate "CAIF virtio transport driver"
-       depends on CAIF && HAS_DMA
+       depends on CAIF && HAS_DMA && VHOST_DPN
        select VHOST_RING
        select VIRTIO
        select GENERIC_ALLOCATOR
index 68e2381694b9ebd217a8e31debddcc7097ef6caa..c283593bef17e8b94e7eabb56d34f362e4ecbc4e 100644 (file)
@@ -1474,6 +1474,10 @@ static int b53_arl_rw_op(struct b53_device *dev, unsigned int op)
                reg |= ARLTBL_RW;
        else
                reg &= ~ARLTBL_RW;
+       if (dev->vlan_enabled)
+               reg &= ~ARLTBL_IVL_SVL_SELECT;
+       else
+               reg |= ARLTBL_IVL_SVL_SELECT;
        b53_write8(dev, B53_ARLIO_PAGE, B53_ARLTBL_RW_CTRL, reg);
 
        return b53_arl_op_wait(dev);
@@ -1483,6 +1487,7 @@ static int b53_arl_read(struct b53_device *dev, u64 mac,
                        u16 vid, struct b53_arl_entry *ent, u8 *idx,
                        bool is_valid)
 {
+       DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES);
        unsigned int i;
        int ret;
 
@@ -1490,6 +1495,8 @@ static int b53_arl_read(struct b53_device *dev, u64 mac,
        if (ret)
                return ret;
 
+       bitmap_zero(free_bins, dev->num_arl_entries);
+
        /* Read the bins */
        for (i = 0; i < dev->num_arl_entries; i++) {
                u64 mac_vid;
@@ -1501,13 +1508,24 @@ static int b53_arl_read(struct b53_device *dev, u64 mac,
                           B53_ARLTBL_DATA_ENTRY(i), &fwd_entry);
                b53_arl_to_entry(ent, mac_vid, fwd_entry);
 
-               if (!(fwd_entry & ARLTBL_VALID))
+               if (!(fwd_entry & ARLTBL_VALID)) {
+                       set_bit(i, free_bins);
                        continue;
+               }
                if ((mac_vid & ARLTBL_MAC_MASK) != mac)
                        continue;
+               if (dev->vlan_enabled &&
+                   ((mac_vid >> ARLTBL_VID_S) & ARLTBL_VID_MASK) != vid)
+                       continue;
                *idx = i;
+               return 0;
        }
 
+       if (bitmap_weight(free_bins, dev->num_arl_entries) == 0)
+               return -ENOSPC;
+
+       *idx = find_first_bit(free_bins, dev->num_arl_entries);
+
        return -ENOENT;
 }
 
@@ -1537,10 +1555,21 @@ static int b53_arl_op(struct b53_device *dev, int op, int port,
        if (op)
                return ret;
 
-       /* We could not find a matching MAC, so reset to a new entry */
-       if (ret) {
+       switch (ret) {
+       case -ENOSPC:
+               dev_dbg(dev->dev, "{%pM,%.4d} no space left in ARL\n",
+                       addr, vid);
+               return is_valid ? ret : 0;
+       case -ENOENT:
+               /* We could not find a matching MAC, so reset to a new entry */
+               dev_dbg(dev->dev, "{%pM,%.4d} not found, using idx: %d\n",
+                       addr, vid, idx);
                fwd_entry = 0;
-               idx = 1;
+               break;
+       default:
+               dev_dbg(dev->dev, "{%pM,%.4d} found, using idx: %d\n",
+                       addr, vid, idx);
+               break;
        }
 
        /* For multicast address, the port is a bitmask and the validity
@@ -1558,7 +1587,6 @@ static int b53_arl_op(struct b53_device *dev, int op, int port,
                ent.is_valid = !!(ent.port);
        }
 
-       ent.is_valid = is_valid;
        ent.vid = vid;
        ent.is_static = true;
        ent.is_age = false;
index 2a9f421680aad625d8e12020ce853808685eeb84..c90985c294a2e72888229963b89174e01bb6a978 100644 (file)
 /* ARL Table Read/Write Register (8 bit) */
 #define B53_ARLTBL_RW_CTRL             0x00
 #define    ARLTBL_RW                   BIT(0)
+#define    ARLTBL_IVL_SVL_SELECT       BIT(6)
 #define    ARLTBL_START_DONE           BIT(7)
 
 /* MAC Address Index Register (48 bit) */
  *
  * BCM5325 and BCM5365 share most definitions below
  */
-#define B53_ARLTBL_MAC_VID_ENTRY(n)    (0x10 * (n))
+#define B53_ARLTBL_MAC_VID_ENTRY(n)    ((0x10 * (n)) + 0x10)
 #define   ARLTBL_MAC_MASK              0xffffffffffffULL
 #define   ARLTBL_VID_S                 48
 #define   ARLTBL_VID_MASK_25           0xff
 #define   ARLTBL_VALID_25              BIT(63)
 
 /* ARL Table Data Entry N Registers (32 bit) */
-#define B53_ARLTBL_DATA_ENTRY(n)       ((0x10 * (n)) + 0x08)
+#define B53_ARLTBL_DATA_ENTRY(n)       ((0x10 * (n)) + 0x18)
 #define   ARLTBL_DATA_PORT_ID_MASK     0x1ff
 #define   ARLTBL_TC(tc)                        ((3 & tc) << 11)
 #define   ARLTBL_AGE                   BIT(14)
 #define   ARLTBL_STATIC                        BIT(15)
 #define   ARLTBL_VALID                 BIT(16)
 
+/* Maximum number of bin entries in the ARL for all switches */
+#define B53_ARLTBL_MAX_BIN_ENTRIES     4
+
 /* ARL Search Control Register (8 bit) */
 #define B53_ARL_SRCH_CTL               0x50
 #define B53_ARL_SRCH_CTL_25            0x20
index 2d0d91db0ddb40e1c9d5c271268f343181b4790c..5c444cd722bdcde79e2037ddea815f9ad2780e8f 100644 (file)
@@ -66,58 +66,6 @@ static const struct mt7530_mib_desc mt7530_mib[] = {
        MIB_DESC(1, 0xb8, "RxArlDrop"),
 };
 
-static int
-mt7623_trgmii_write(struct mt7530_priv *priv,  u32 reg, u32 val)
-{
-       int ret;
-
-       ret =  regmap_write(priv->ethernet, TRGMII_BASE(reg), val);
-       if (ret < 0)
-               dev_err(priv->dev,
-                       "failed to priv write register\n");
-       return ret;
-}
-
-static u32
-mt7623_trgmii_read(struct mt7530_priv *priv, u32 reg)
-{
-       int ret;
-       u32 val;
-
-       ret = regmap_read(priv->ethernet, TRGMII_BASE(reg), &val);
-       if (ret < 0) {
-               dev_err(priv->dev,
-                       "failed to priv read register\n");
-               return ret;
-       }
-
-       return val;
-}
-
-static void
-mt7623_trgmii_rmw(struct mt7530_priv *priv, u32 reg,
-                 u32 mask, u32 set)
-{
-       u32 val;
-
-       val = mt7623_trgmii_read(priv, reg);
-       val &= ~mask;
-       val |= set;
-       mt7623_trgmii_write(priv, reg, val);
-}
-
-static void
-mt7623_trgmii_set(struct mt7530_priv *priv, u32 reg, u32 val)
-{
-       mt7623_trgmii_rmw(priv, reg, 0, val);
-}
-
-static void
-mt7623_trgmii_clear(struct mt7530_priv *priv, u32 reg, u32 val)
-{
-       mt7623_trgmii_rmw(priv, reg, val, 0);
-}
-
 static int
 core_read_mmd_indirect(struct mt7530_priv *priv, int prtad, int devad)
 {
@@ -530,27 +478,6 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, int mode)
                for (i = 0 ; i < NUM_TRGMII_CTRL; i++)
                        mt7530_rmw(priv, MT7530_TRGMII_RD(i),
                                   RD_TAP_MASK, RD_TAP(16));
-       else
-               if (priv->id != ID_MT7621)
-                       mt7623_trgmii_set(priv, GSW_INTF_MODE,
-                                         INTF_MODE_TRGMII);
-
-       return 0;
-}
-
-static int
-mt7623_pad_clk_setup(struct dsa_switch *ds)
-{
-       struct mt7530_priv *priv = ds->priv;
-       int i;
-
-       for (i = 0 ; i < NUM_TRGMII_CTRL; i++)
-               mt7623_trgmii_write(priv, GSW_TRGMII_TD_ODT(i),
-                                   TD_DM_DRVP(8) | TD_DM_DRVN(8));
-
-       mt7623_trgmii_set(priv, GSW_TRGMII_RCK_CTRL, RX_RST | RXC_DQSISEL);
-       mt7623_trgmii_clear(priv, GSW_TRGMII_RCK_CTRL, RX_RST);
-
        return 0;
 }
 
@@ -846,8 +773,9 @@ mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
         */
        mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
                   MT7530_PORT_MATRIX_MODE);
-       mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK,
-                  VLAN_ATTR(MT7530_VLAN_TRANSPARENT));
+       mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK | PVC_EG_TAG_MASK,
+                  VLAN_ATTR(MT7530_VLAN_TRANSPARENT) |
+                  PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
 
        for (i = 0; i < MT7530_NUM_PORTS; i++) {
                if (dsa_is_user_port(ds, i) &&
@@ -863,8 +791,8 @@ mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
        if (all_user_ports_removed) {
                mt7530_write(priv, MT7530_PCR_P(MT7530_CPU_PORT),
                             PCR_MATRIX(dsa_user_ports(priv->ds)));
-               mt7530_write(priv, MT7530_PVC_P(MT7530_CPU_PORT),
-                            PORT_SPEC_TAG);
+               mt7530_write(priv, MT7530_PVC_P(MT7530_CPU_PORT), PORT_SPEC_TAG
+                            | PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
        }
 }
 
@@ -890,8 +818,9 @@ mt7530_port_set_vlan_aware(struct dsa_switch *ds, int port)
        /* Set the port as a user port which is to be able to recognize VID
         * from incoming packets before fetching entry within the VLAN table.
         */
-       mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK,
-                  VLAN_ATTR(MT7530_VLAN_USER));
+       mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK | PVC_EG_TAG_MASK,
+                  VLAN_ATTR(MT7530_VLAN_USER) |
+                  PVC_EG_TAG(MT7530_VLAN_EG_DISABLED));
 }
 
 static void
@@ -1303,10 +1232,6 @@ mt7530_setup(struct dsa_switch *ds)
        dn = dsa_to_port(ds, MT7530_CPU_PORT)->master->dev.of_node->parent;
 
        if (priv->id == ID_MT7530) {
-               priv->ethernet = syscon_node_to_regmap(dn);
-               if (IS_ERR(priv->ethernet))
-                       return PTR_ERR(priv->ethernet);
-
                regulator_set_voltage(priv->core_pwr, 1000000, 1000000);
                ret = regulator_enable(priv->core_pwr);
                if (ret < 0) {
@@ -1380,6 +1305,10 @@ mt7530_setup(struct dsa_switch *ds)
                        mt7530_cpu_port_enable(priv, i);
                else
                        mt7530_port_disable(ds, i);
+
+               /* Enable consistent egress tag */
+               mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK,
+                          PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
        }
 
        /* Setup port 5 */
@@ -1468,14 +1397,6 @@ static void mt7530_phylink_mac_config(struct dsa_switch *ds, int port,
                /* Setup TX circuit incluing relevant PAD and driving */
                mt7530_pad_clk_setup(ds, state->interface);
 
-               if (priv->id == ID_MT7530) {
-                       /* Setup RX circuit, relevant PAD and driving on the
-                        * host which must be placed after the setup on the
-                        * device side is all finished.
-                        */
-                       mt7623_pad_clk_setup(ds);
-               }
-
                priv->p6_interface = state->interface;
                break;
        default:
index ef9b52f3152b6e9db072e770e2da85062ef1cdd2..979bb6374678fda639e2da2b732d707145e6ee6b 100644 (file)
@@ -172,9 +172,16 @@ enum mt7530_port_mode {
 /* Register for port vlan control */
 #define MT7530_PVC_P(x)                        (0x2010 + ((x) * 0x100))
 #define  PORT_SPEC_TAG                 BIT(5)
+#define  PVC_EG_TAG(x)                 (((x) & 0x7) << 8)
+#define  PVC_EG_TAG_MASK               PVC_EG_TAG(7)
 #define  VLAN_ATTR(x)                  (((x) & 0x3) << 6)
 #define  VLAN_ATTR_MASK                        VLAN_ATTR(3)
 
+enum mt7530_vlan_port_eg_tag {
+       MT7530_VLAN_EG_DISABLED = 0,
+       MT7530_VLAN_EG_CONSISTENT = 1,
+};
+
 enum mt7530_vlan_port_attr {
        MT7530_VLAN_USER = 0,
        MT7530_VLAN_TRANSPARENT = 3,
@@ -277,7 +284,6 @@ enum mt7530_vlan_port_attr {
 
 /* Registers for TRGMII on the both side */
 #define MT7530_TRGMII_RCK_CTRL         0x7a00
-#define GSW_TRGMII_RCK_CTRL            0x300
 #define  RX_RST                                BIT(31)
 #define  RXC_DQSISEL                   BIT(30)
 #define  DQSI1_TAP_MASK                        (0x7f << 8)
@@ -286,31 +292,24 @@ enum mt7530_vlan_port_attr {
 #define  DQSI0_TAP(x)                  ((x) & 0x7f)
 
 #define MT7530_TRGMII_RCK_RTT          0x7a04
-#define GSW_TRGMII_RCK_RTT             0x304
 #define  DQS1_GATE                     BIT(31)
 #define  DQS0_GATE                     BIT(30)
 
 #define MT7530_TRGMII_RD(x)            (0x7a10 + (x) * 8)
-#define GSW_TRGMII_RD(x)               (0x310 + (x) * 8)
 #define  BSLIP_EN                      BIT(31)
 #define  EDGE_CHK                      BIT(30)
 #define  RD_TAP_MASK                   0x7f
 #define  RD_TAP(x)                     ((x) & 0x7f)
 
-#define GSW_TRGMII_TXCTRL              0x340
 #define MT7530_TRGMII_TXCTRL           0x7a40
 #define  TRAIN_TXEN                    BIT(31)
 #define  TXC_INV                       BIT(30)
 #define  TX_RST                                BIT(28)
 
 #define MT7530_TRGMII_TD_ODT(i)                (0x7a54 + 8 * (i))
-#define GSW_TRGMII_TD_ODT(i)           (0x354 + 8 * (i))
 #define  TD_DM_DRVP(x)                 ((x) & 0xf)
 #define  TD_DM_DRVN(x)                 (((x) & 0xf) << 4)
 
-#define GSW_INTF_MODE                  0x390
-#define  INTF_MODE_TRGMII              BIT(1)
-
 #define MT7530_TRGMII_TCK_CTRL         0x7a78
 #define  TCK_TAP(x)                    (((x) & 0xf) << 8)
 
@@ -443,7 +442,6 @@ static const char *p5_intf_modes(unsigned int p5_interface)
  * @ds:                        The pointer to the dsa core structure
  * @bus:               The bus used for the device and built-in PHY
  * @rstc:              The pointer to reset control used by MCM
- * @ethernet:          The regmap used for access TRGMII-based registers
  * @core_pwr:          The power supplied into the core
  * @io_pwr:            The power supplied into the I/O
  * @reset:             The descriptor for GPIO line tied to its reset pin
@@ -460,7 +458,6 @@ struct mt7530_priv {
        struct dsa_switch       *ds;
        struct mii_bus          *bus;
        struct reset_control    *rstc;
-       struct regmap           *ethernet;
        struct regulator        *core_pwr;
        struct regulator        *io_pwr;
        struct gpio_desc        *reset;
index 6435020d690dd5ae35c7c0fe0b8d0a9fc6c12d16..51185e4d7d15ed548d82ef870cb0f392b6e66d10 100644 (file)
@@ -24,8 +24,8 @@ config NET_DSA_MV88E6XXX_PTP
        bool "PTP support for Marvell 88E6xxx"
        default n
        depends on NET_DSA_MV88E6XXX_GLOBAL2
+       depends on PTP_1588_CLOCK
        imply NETWORK_PHY_TIMESTAMPING
-       imply PTP_1588_CLOCK
        help
          Say Y to enable PTP hardware timestamping on Marvell 88E6xxx switch
          chips that support it.
index 221593261e8feb0a8c2c485da18fc8b4cbc0bb9a..2b4a723c830656f38e5e02b8491b9aae3a8ec91b 100644 (file)
@@ -709,7 +709,8 @@ static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port,
        ops = chip->info->ops;
 
        mv88e6xxx_reg_lock(chip);
-       if (!mv88e6xxx_port_ppu_updates(chip, port) && ops->port_set_link)
+       if ((!mv88e6xxx_port_ppu_updates(chip, port) ||
+            mode == MLO_AN_FIXED) && ops->port_set_link)
                err = ops->port_set_link(chip, port, LINK_FORCED_DOWN);
        mv88e6xxx_reg_unlock(chip);
 
@@ -731,7 +732,7 @@ static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port,
        ops = chip->info->ops;
 
        mv88e6xxx_reg_lock(chip);
-       if (!mv88e6xxx_port_ppu_updates(chip, port)) {
+       if (!mv88e6xxx_port_ppu_updates(chip, port) || mode == MLO_AN_FIXED) {
                /* FIXME: for an automedia port, should we force the link
                 * down here - what if the link comes up due to "other" media
                 * while we're bringing the port up, how is the exclusivity
@@ -3961,7 +3962,6 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
        .serdes_get_stats = mv88e6390_serdes_get_stats,
        .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
        .serdes_get_regs = mv88e6390_serdes_get_regs,
-       .phylink_validate = mv88e6390_phylink_validate,
        .gpio_ops = &mv88e6352_gpio_ops,
        .phylink_validate = mv88e6390_phylink_validate,
 };
@@ -4020,7 +4020,6 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
        .serdes_get_stats = mv88e6390_serdes_get_stats,
        .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
        .serdes_get_regs = mv88e6390_serdes_get_regs,
-       .phylink_validate = mv88e6390_phylink_validate,
        .gpio_ops = &mv88e6352_gpio_ops,
        .phylink_validate = mv88e6390x_phylink_validate,
 };
@@ -4078,7 +4077,6 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
        .serdes_get_stats = mv88e6390_serdes_get_stats,
        .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
        .serdes_get_regs = mv88e6390_serdes_get_regs,
-       .phylink_validate = mv88e6390_phylink_validate,
        .avb_ops = &mv88e6390_avb_ops,
        .ptp_ops = &mv88e6352_ptp_ops,
        .phylink_validate = mv88e6390_phylink_validate,
@@ -4234,7 +4232,6 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
        .serdes_get_stats = mv88e6390_serdes_get_stats,
        .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
        .serdes_get_regs = mv88e6390_serdes_get_regs,
-       .phylink_validate = mv88e6390_phylink_validate,
        .gpio_ops = &mv88e6352_gpio_ops,
        .avb_ops = &mv88e6390_avb_ops,
        .ptp_ops = &mv88e6352_ptp_ops,
index 79ca3aadb86410728a84eb2e32953a7b6acc6de8..e2c6bf0e430e8a9e78d82506b23c5dc6968217ab 100644 (file)
@@ -46,11 +46,8 @@ static int felix_fdb_add(struct dsa_switch *ds, int port,
                         const unsigned char *addr, u16 vid)
 {
        struct ocelot *ocelot = ds->priv;
-       bool vlan_aware;
 
-       vlan_aware = dsa_port_is_vlan_filtering(dsa_to_port(ds, port));
-
-       return ocelot_fdb_add(ocelot, port, addr, vid, vlan_aware);
+       return ocelot_fdb_add(ocelot, port, addr, vid);
 }
 
 static int felix_fdb_del(struct dsa_switch *ds, int port,
@@ -403,6 +400,7 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
        ocelot->stats_layout    = felix->info->stats_layout;
        ocelot->num_stats       = felix->info->num_stats;
        ocelot->shared_queue_sz = felix->info->shared_queue_sz;
+       ocelot->num_mact_rows   = felix->info->num_mact_rows;
        ocelot->vcap_is2_keys   = felix->info->vcap_is2_keys;
        ocelot->vcap_is2_actions= felix->info->vcap_is2_actions;
        ocelot->vcap            = felix->info->vcap;
index 82d46f2600418882df9140fad975a66b54dabff0..9af106513e5308c2a4bad3d108c844af3ad9342e 100644 (file)
@@ -15,6 +15,7 @@ struct felix_info {
        const u32 *const                *map;
        const struct ocelot_ops         *ops;
        int                             shared_queue_sz;
+       int                             num_mact_rows;
        const struct ocelot_stat_layout *stats_layout;
        unsigned int                    num_stats;
        int                             num_ports;
index b4078f3c5c383d1b3f9a5bbb31d6992ff1657a08..8bf395f12b47760f7b3bd73c207f53955d34f815 100644 (file)
@@ -1220,6 +1220,7 @@ struct felix_info felix_info_vsc9959 = {
        .vcap_is2_actions       = vsc9959_vcap_is2_actions,
        .vcap                   = vsc9959_vcap_props,
        .shared_queue_sz        = 128 * 1024,
+       .num_mact_rows          = 2048,
        .num_ports              = 6,
        .switch_pci_bar         = 4,
        .imdio_pci_bar          = 0,
index 0fe1ae173aa1a4b7c583fc087749e2daa3491d78..68c3086af9af810bf4c268c078482c5b20b74a2b 100644 (file)
@@ -20,6 +20,7 @@ tristate "NXP SJA1105 Ethernet switch family support"
 config NET_DSA_SJA1105_PTP
        bool "Support for the PTP clock on the NXP SJA1105 Ethernet switch"
        depends on NET_DSA_SJA1105
+       depends on PTP_1588_CLOCK
        help
          This enables support for timestamping and PTP clock manipulations in
          the SJA1105 DSA driver.
index a22f8e3fc06baefd77202ed15a47f0c072ed3561..bc0e47c1dbb9b6c6460b54fc2fcca924afc6f88f 100644 (file)
 
 /* PTPSYNCTS has no interrupt or update mechanism, because the intended
  * hardware use case is for the timestamp to be collected synchronously,
- * immediately after the CAS_MASTER SJA1105 switch has triggered a CASSYNC
- * pulse on the PTP_CLK pin. When used as a generic extts source, it needs
- * polling and a comparison with the old value. The polling interval is just
- * the Nyquist rate of a canonical PPS input (e.g. from a GPS module).
- * Anything of higher frequency than 1 Hz will be lost, since there is no
- * timestamp FIFO.
+ * immediately after the CAS_MASTER SJA1105 switch has performed a CASSYNC
+ * one-shot toggle (no return to level) on the PTP_CLK pin. When used as a
+ * generic extts source, the PTPSYNCTS register needs polling and a comparison
+ * with the old value. The polling interval is configured as the Nyquist rate
+ * of a signal with 50% duty cycle and 1Hz frequency, which is sadly all that
+ * this hardware can do (but may be enough for some setups). Anything of higher
+ * frequency than 1 Hz will be lost, since there is no timestamp FIFO.
  */
-#define SJA1105_EXTTS_INTERVAL         (HZ / 2)
+#define SJA1105_EXTTS_INTERVAL         (HZ / 4)
 
 /*            This range is actually +/- SJA1105_MAX_ADJ_PPB
  *            divided by 1000 (ppb -> ppm) and with a 16-bit
@@ -754,7 +755,16 @@ static int sja1105_extts_enable(struct sja1105_private *priv,
                return -EOPNOTSUPP;
 
        /* Reject requests with unsupported flags */
-       if (extts->flags)
+       if (extts->flags & ~(PTP_ENABLE_FEATURE |
+                            PTP_RISING_EDGE |
+                            PTP_FALLING_EDGE |
+                            PTP_STRICT_FLAGS))
+               return -EOPNOTSUPP;
+
+       /* We can only enable time stamping on both edges, sadly. */
+       if ((extts->flags & PTP_STRICT_FLAGS) &&
+           (extts->flags & PTP_ENABLE_FEATURE) &&
+           (extts->flags & PTP_EXTTS_EDGES) != PTP_EXTTS_EDGES)
                return -EOPNOTSUPP;
 
        rc = sja1105_change_ptp_clk_pin_func(priv, PTP_PF_EXTTS);
index 97dfd0c67e8475d0f9ff5cfa937ddd6043b9b10d..9e1860d81908db258d76f3db9f0c60d7e6404307 100644 (file)
@@ -69,7 +69,7 @@
  * 16kB.
  */
 #if PAGE_SIZE > SZ_16K
-#define ENA_PAGE_SIZE SZ_16K
+#define ENA_PAGE_SIZE (_AC(SZ_16K, UL))
 #else
 #define ENA_PAGE_SIZE PAGE_SIZE
 #endif
index b71f9b04a51e187ce96fb4073287bc4393901cd9..a87264f95f1a49b39211690da0db147d571d2bcb 100644 (file)
@@ -514,7 +514,7 @@ static void xgbe_isr_task(unsigned long data)
                                xgbe_disable_rx_tx_ints(pdata);
 
                                /* Turn on polling */
-                               __napi_schedule_irqoff(&pdata->napi);
+                               __napi_schedule(&pdata->napi);
                        }
                } else {
                        /* Don't clear Rx/Tx status if doing per channel DMA
index 2edf137a70304e6fa8eb9235d1d8a4d435de6e13..8a70ffe1d32668df7d1935c921fc2461e829d506 100644 (file)
@@ -57,7 +57,7 @@ static const struct aq_board_revision_s hw_atl_boards[] = {
        { AQ_DEVICE_ID_D108,    AQ_HWREV_2,     &hw_atl_ops_b0, &hw_atl_b0_caps_aqc108, },
        { AQ_DEVICE_ID_D109,    AQ_HWREV_2,     &hw_atl_ops_b0, &hw_atl_b0_caps_aqc109, },
 
-       { AQ_DEVICE_ID_AQC100,  AQ_HWREV_ANY,   &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107, },
+       { AQ_DEVICE_ID_AQC100,  AQ_HWREV_ANY,   &hw_atl_ops_b1, &hw_atl_b0_caps_aqc100, },
        { AQ_DEVICE_ID_AQC107,  AQ_HWREV_ANY,   &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107, },
        { AQ_DEVICE_ID_AQC108,  AQ_HWREV_ANY,   &hw_atl_ops_b1, &hw_atl_b0_caps_aqc108, },
        { AQ_DEVICE_ID_AQC109,  AQ_HWREV_ANY,   &hw_atl_ops_b1, &hw_atl_b0_caps_aqc109, },
index af7ce5c5488cbf8052c6392effaafec97f00d8be..b25356e21a1ea281b1db8b1d8b9cb83de8fb72ae 100644 (file)
@@ -664,7 +664,8 @@ static struct sk_buff *bcm_sysport_rx_refill(struct bcm_sysport_priv *priv,
        dma_addr_t mapping;
 
        /* Allocate a new SKB for a new packet */
-       skb = netdev_alloc_skb(priv->netdev, RX_BUF_LENGTH);
+       skb = __netdev_alloc_skb(priv->netdev, RX_BUF_LENGTH,
+                                GFP_ATOMIC | __GFP_NOWARN);
        if (!skb) {
                priv->mib.alloc_rx_buff_failed++;
                netif_err(priv, rx_err, ndev, "SKB alloc failed\n");
@@ -2475,7 +2476,6 @@ static int bcm_sysport_probe(struct platform_device *pdev)
                priv->wol_irq = platform_get_irq(pdev, 1);
        }
        if (priv->irq0 <= 0 || (priv->irq1 <= 0 && !priv->is_lite)) {
-               dev_err(&pdev->dev, "invalid interrupts\n");
                ret = -EINVAL;
                goto err_free_netdev;
        }
index c46c1b1416f7902da038b0896a7ec01456545b0b..6795b6d95f54d2c1854a396a38376bfbe10a3c22 100644 (file)
@@ -202,13 +202,8 @@ static int bgmac_probe(struct platform_device *pdev)
        if (bgmac->irq < 0)
                return bgmac->irq;
 
-       regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "amac_base");
-       if (!regs) {
-               dev_err(&pdev->dev, "Unable to obtain base resource\n");
-               return -EINVAL;
-       }
-
-       bgmac->plat.base = devm_ioremap_resource(&pdev->dev, regs);
+       bgmac->plat.base =
+               devm_platform_ioremap_resource_byname(pdev, "amac_base");
        if (IS_ERR(bgmac->plat.base))
                return PTR_ERR(bgmac->plat.base);
 
index fead64f1ad90e3d2688775e86d90a51805ffa254..d1a83716d9345d3d45b4466cc78fee7192b20cf6 100644 (file)
@@ -6642,7 +6642,7 @@ static int bnxt_alloc_ctx_pg_tbls(struct bnxt *bp,
        int rc;
 
        if (!mem_size)
-               return 0;
+               return -EINVAL;
 
        ctx_pg->nr_pages = DIV_ROUND_UP(mem_size, BNXT_PAGE_SIZE);
        if (ctx_pg->nr_pages > MAX_CTX_TOTAL_PAGES) {
@@ -9780,6 +9780,7 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
                                           netdev_features_t features)
 {
        struct bnxt *bp = netdev_priv(dev);
+       netdev_features_t vlan_features;
 
        if ((features & NETIF_F_NTUPLE) && !bnxt_rfs_capable(bp))
                features &= ~NETIF_F_NTUPLE;
@@ -9796,12 +9797,14 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
        /* Both CTAG and STAG VLAN accelaration on the RX side have to be
         * turned on or off together.
         */
-       if ((features & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) !=
-           (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) {
+       vlan_features = features & (NETIF_F_HW_VLAN_CTAG_RX |
+                                   NETIF_F_HW_VLAN_STAG_RX);
+       if (vlan_features != (NETIF_F_HW_VLAN_CTAG_RX |
+                             NETIF_F_HW_VLAN_STAG_RX)) {
                if (dev->features & NETIF_F_HW_VLAN_CTAG_RX)
                        features &= ~(NETIF_F_HW_VLAN_CTAG_RX |
                                      NETIF_F_HW_VLAN_STAG_RX);
-               else
+               else if (vlan_features)
                        features |= NETIF_F_HW_VLAN_CTAG_RX |
                                    NETIF_F_HW_VLAN_STAG_RX;
        }
@@ -12212,12 +12215,15 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
                bnxt_ulp_start(bp, err);
        }
 
-       if (result != PCI_ERS_RESULT_RECOVERED && netif_running(netdev))
-               dev_close(netdev);
+       if (result != PCI_ERS_RESULT_RECOVERED) {
+               if (netif_running(netdev))
+                       dev_close(netdev);
+               pci_disable_device(pdev);
+       }
 
        rtnl_unlock();
 
-       return PCI_ERS_RESULT_RECOVERED;
+       return result;
 }
 
 /**
index f2caa2756f5b26014e5501eebbad387ff2612ed4..f6a3250ef1c55442bc672833e663af751567afdc 100644 (file)
@@ -1066,7 +1066,6 @@ struct bnxt_vf_info {
 #define BNXT_VF_LINK_FORCED    0x4
 #define BNXT_VF_LINK_UP                0x8
 #define BNXT_VF_TRUST          0x10
-       u32     func_flags; /* func cfg flags */
        u32     min_tx_rate;
        u32     max_tx_rate;
        void    *hwrm_cmd_req_addr;
index 95f893f2a74dc8c2fe2e7c8178f1bb55cb1e2b28..d5c8bd49383acc376cd2cc7d58472cad3c026739 100644 (file)
@@ -43,7 +43,7 @@ static inline void bnxt_link_bp_to_dl(struct bnxt *bp, struct devlink *dl)
 #define BNXT_NVM_CFG_VER_BITS          24
 #define BNXT_NVM_CFG_VER_BYTES         4
 
-#define BNXT_MSIX_VEC_MAX      1280
+#define BNXT_MSIX_VEC_MAX      512
 #define BNXT_MSIX_VEC_MIN_MAX  128
 
 enum bnxt_nvm_dir_type {
index 6ea3df6da18cd7ca006b79b9ac95c50f99a6b7bf..cea2f9958a1df50766582ffbc4c876a9edd0c87b 100644 (file)
@@ -85,11 +85,10 @@ int bnxt_set_vf_spoofchk(struct net_device *dev, int vf_id, bool setting)
        if (old_setting == setting)
                return 0;
 
-       func_flags = vf->func_flags;
        if (setting)
-               func_flags |= FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_ENABLE;
+               func_flags = FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_ENABLE;
        else
-               func_flags |= FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_DISABLE;
+               func_flags = FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_DISABLE;
        /*TODO: if the driver supports VLAN filter on guest VLAN,
         * the spoof check should also include vlan anti-spoofing
         */
@@ -98,7 +97,6 @@ int bnxt_set_vf_spoofchk(struct net_device *dev, int vf_id, bool setting)
        req.flags = cpu_to_le32(func_flags);
        rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        if (!rc) {
-               vf->func_flags = func_flags;
                if (setting)
                        vf->flags |= BNXT_VF_SPOOFCHK;
                else
@@ -228,7 +226,6 @@ int bnxt_set_vf_mac(struct net_device *dev, int vf_id, u8 *mac)
        memcpy(vf->mac_addr, mac, ETH_ALEN);
        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
        req.fid = cpu_to_le16(vf->fw_fid);
-       req.flags = cpu_to_le32(vf->func_flags);
        req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_MAC_ADDR);
        memcpy(req.dflt_mac_addr, mac, ETH_ALEN);
        return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
@@ -266,7 +263,6 @@ int bnxt_set_vf_vlan(struct net_device *dev, int vf_id, u16 vlan_id, u8 qos,
 
        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
        req.fid = cpu_to_le16(vf->fw_fid);
-       req.flags = cpu_to_le32(vf->func_flags);
        req.dflt_vlan = cpu_to_le16(vlan_tag);
        req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_VLAN);
        rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
@@ -305,7 +301,6 @@ int bnxt_set_vf_bw(struct net_device *dev, int vf_id, int min_tx_rate,
                return 0;
        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
        req.fid = cpu_to_le16(vf->fw_fid);
-       req.flags = cpu_to_le32(vf->func_flags);
        req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_MAX_BW);
        req.max_bw = cpu_to_le32(max_tx_rate);
        req.enables |= cpu_to_le32(FUNC_CFG_REQ_ENABLES_MIN_BW);
@@ -477,7 +472,6 @@ static void __bnxt_set_vf_params(struct bnxt *bp, int vf_id)
        vf = &bp->pf.vf[vf_id];
        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
        req.fid = cpu_to_le16(vf->fw_fid);
-       req.flags = cpu_to_le32(vf->func_flags);
 
        if (is_valid_ether_addr(vf->mac_addr)) {
                req.enables |= cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_MAC_ADDR);
index d975338bf78df35dfb6fd5a82961f89dde1621bb..79636c78127cdb503403f14994ae488af3d34bae 100644 (file)
@@ -934,6 +934,8 @@ static void bcmgenet_get_ethtool_stats(struct net_device *dev,
        if (netif_running(dev))
                bcmgenet_update_mib_counters(priv);
 
+       dev->netdev_ops->ndo_get_stats(dev);
+
        for (i = 0; i < BCMGENET_STATS_LEN; i++) {
                const struct bcmgenet_stats *s;
                char *p;
@@ -1622,7 +1624,8 @@ static struct sk_buff *bcmgenet_rx_refill(struct bcmgenet_priv *priv,
        dma_addr_t mapping;
 
        /* Allocate a new Rx skb */
-       skb = netdev_alloc_skb(priv->dev, priv->rx_buf_len + SKB_ALIGNMENT);
+       skb = __netdev_alloc_skb(priv->dev, priv->rx_buf_len + SKB_ALIGNMENT,
+                                GFP_ATOMIC | __GFP_NOWARN);
        if (!skb) {
                priv->mib.alloc_rx_buff_failed++;
                netif_err(priv, rx_err, priv->dev,
@@ -3156,6 +3159,7 @@ static struct net_device_stats *bcmgenet_get_stats(struct net_device *dev)
        dev->stats.rx_packets = rx_packets;
        dev->stats.rx_errors = rx_errors;
        dev->stats.rx_missed_errors = rx_errors;
+       dev->stats.rx_dropped = rx_dropped;
        return &dev->stats;
 }
 
index 53b50c24d9c9535dad9a5c5b9e5b983822183fe3..2c4c12b03502dc7cf80dbedbda7b8e592b52197e 100644 (file)
@@ -35,8 +35,8 @@ config MACB
 config MACB_USE_HWSTAMP
        bool "Use IEEE 1588 hwstamp"
        depends on MACB
+       depends on PTP_1588_CLOCK
        default y
-       imply PTP_1588_CLOCK
        ---help---
          Enable IEEE 1588 Precision Time Protocol (PTP) support for MACB.
 
index a0e8c5bbabc018cf0243f88e888a03a75da133a1..36290a8e2a84684886ef719aa2c4a558c1821f01 100644 (file)
@@ -334,8 +334,10 @@ static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
        int status;
 
        status = pm_runtime_get_sync(&bp->pdev->dev);
-       if (status < 0)
+       if (status < 0) {
+               pm_runtime_put_noidle(&bp->pdev->dev);
                goto mdio_pm_exit;
+       }
 
        status = macb_mdio_wait_for_idle(bp);
        if (status < 0)
@@ -386,8 +388,10 @@ static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
        int status;
 
        status = pm_runtime_get_sync(&bp->pdev->dev);
-       if (status < 0)
+       if (status < 0) {
+               pm_runtime_put_noidle(&bp->pdev->dev);
                goto mdio_pm_exit;
+       }
 
        status = macb_mdio_wait_for_idle(bp);
        if (status < 0)
@@ -3816,8 +3820,10 @@ static int at91ether_open(struct net_device *dev)
        int ret;
 
        ret = pm_runtime_get_sync(&lp->pdev->dev);
-       if (ret < 0)
+       if (ret < 0) {
+               pm_runtime_put_noidle(&lp->pdev->dev);
                return ret;
+       }
 
        /* Clear internal statistics */
        ctl = macb_readl(lp, NCR);
@@ -4172,15 +4178,9 @@ static int fu540_c000_clk_init(struct platform_device *pdev, struct clk **pclk,
 
 static int fu540_c000_init(struct platform_device *pdev)
 {
-       struct resource *res;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!res)
-               return -ENODEV;
-
-       mgmt->reg = ioremap(res->start, resource_size(res));
-       if (!mgmt->reg)
-               return -ENOMEM;
+       mgmt->reg = devm_platform_ioremap_resource(pdev, 1);
+       if (IS_ERR(mgmt->reg))
+               return PTR_ERR(mgmt->reg);
 
        return macb_init(pdev);
 }
index 6a700d34019e303e9d8a301a9c6876e320d99578..4520e7ee00fe1a24aff0e7674e0536879b2f1236 100644 (file)
@@ -54,7 +54,7 @@ config        THUNDER_NIC_RGX
 config CAVIUM_PTP
        tristate "Cavium PTP coprocessor as PTP clock"
        depends on 64BIT && PCI
-       imply PTP_1588_CLOCK
+       depends on PTP_1588_CLOCK
        ---help---
          This driver adds support for the Precision Time Protocol Clocks and
          Timestamping coprocessor (PTP) found on Cavium processors.
index 19c11568113a635fe43b252a2721002894b19dec..7b9cd69f9844002e099dc34b59c72481ef9bbb24 100644 (file)
@@ -1049,9 +1049,9 @@ static void cudbg_t4_fwcache(struct cudbg_init *pdbg_init,
        }
 }
 
-static unsigned long cudbg_mem_region_size(struct cudbg_init *pdbg_init,
-                                          struct cudbg_error *cudbg_err,
-                                          u8 mem_type)
+static int cudbg_mem_region_size(struct cudbg_init *pdbg_init,
+                                struct cudbg_error *cudbg_err,
+                                u8 mem_type, unsigned long *region_size)
 {
        struct adapter *padap = pdbg_init->adap;
        struct cudbg_meminfo mem_info;
@@ -1060,15 +1060,23 @@ static unsigned long cudbg_mem_region_size(struct cudbg_init *pdbg_init,
 
        memset(&mem_info, 0, sizeof(struct cudbg_meminfo));
        rc = cudbg_fill_meminfo(padap, &mem_info);
-       if (rc)
+       if (rc) {
+               cudbg_err->sys_err = rc;
                return rc;
+       }
 
        cudbg_t4_fwcache(pdbg_init, cudbg_err);
        rc = cudbg_meminfo_get_mem_index(padap, &mem_info, mem_type, &mc_idx);
-       if (rc)
+       if (rc) {
+               cudbg_err->sys_err = rc;
                return rc;
+       }
+
+       if (region_size)
+               *region_size = mem_info.avail[mc_idx].limit -
+                              mem_info.avail[mc_idx].base;
 
-       return mem_info.avail[mc_idx].limit - mem_info.avail[mc_idx].base;
+       return 0;
 }
 
 static int cudbg_collect_mem_region(struct cudbg_init *pdbg_init,
@@ -1076,7 +1084,12 @@ static int cudbg_collect_mem_region(struct cudbg_init *pdbg_init,
                                    struct cudbg_error *cudbg_err,
                                    u8 mem_type)
 {
-       unsigned long size = cudbg_mem_region_size(pdbg_init, cudbg_err, mem_type);
+       unsigned long size = 0;
+       int rc;
+
+       rc = cudbg_mem_region_size(pdbg_init, cudbg_err, mem_type, &size);
+       if (rc)
+               return rc;
 
        return cudbg_read_fw_mem(pdbg_init, dbg_buff, mem_type, size,
                                 cudbg_err);
index af1f40cbccc882ee83d15c4fbd7fd7394350b6af..f5bc996ac77d5b04dd86a00169364ced14a2453a 100644 (file)
@@ -311,32 +311,17 @@ static int cxgb4_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
  */
 static int cxgb4_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
 {
-       struct adapter *adapter = (struct adapter *)container_of(ptp,
-                                  struct adapter, ptp_clock_info);
-       struct fw_ptp_cmd c;
+       struct adapter *adapter = container_of(ptp, struct adapter,
+                                              ptp_clock_info);
        u64 ns;
-       int err;
-
-       memset(&c, 0, sizeof(c));
-       c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PTP_CMD) |
-                                    FW_CMD_REQUEST_F |
-                                    FW_CMD_READ_F |
-                                    FW_PTP_CMD_PORTID_V(0));
-       c.retval_len16 = cpu_to_be32(FW_CMD_LEN16_V(sizeof(c) / 16));
-       c.u.ts.sc = FW_PTP_SC_GET_TIME;
 
-       err = t4_wr_mbox(adapter, adapter->mbox, &c, sizeof(c), &c);
-       if (err < 0) {
-               dev_err(adapter->pdev_dev,
-                       "PTP: %s error %d\n", __func__, -err);
-               return err;
-       }
+       ns = t4_read_reg(adapter, T5_PORT_REG(0, MAC_PORT_PTP_SUM_LO_A));
+       ns |= (u64)t4_read_reg(adapter,
+                              T5_PORT_REG(0, MAC_PORT_PTP_SUM_HI_A)) << 32;
 
        /* convert to timespec*/
-       ns = be64_to_cpu(c.u.ts.tm);
        *ts = ns_to_timespec64(ns);
-
-       return err;
+       return 0;
 }
 
 /**
index f5dd34db4b54527cd7c1415c0ec89529683a925a..6516c45864b359b53e37a8a44e475b6b9b1f7c17 100644 (file)
@@ -2207,6 +2207,9 @@ static void ethofld_hard_xmit(struct net_device *dev,
        if (unlikely(skip_eotx_wr)) {
                start = (u64 *)wr;
                eosw_txq->state = next_state;
+               eosw_txq->cred -= wrlen16;
+               eosw_txq->ncompl++;
+               eosw_txq->last_compl = 0;
                goto write_wr_headers;
        }
 
@@ -2365,6 +2368,34 @@ netdev_tx_t t4_start_xmit(struct sk_buff *skb, struct net_device *dev)
        return cxgb4_eth_xmit(skb, dev);
 }
 
+static void eosw_txq_flush_pending_skbs(struct sge_eosw_txq *eosw_txq)
+{
+       int pktcount = eosw_txq->pidx - eosw_txq->last_pidx;
+       int pidx = eosw_txq->pidx;
+       struct sk_buff *skb;
+
+       if (!pktcount)
+               return;
+
+       if (pktcount < 0)
+               pktcount += eosw_txq->ndesc;
+
+       while (pktcount--) {
+               pidx--;
+               if (pidx < 0)
+                       pidx += eosw_txq->ndesc;
+
+               skb = eosw_txq->desc[pidx].skb;
+               if (skb) {
+                       dev_consume_skb_any(skb);
+                       eosw_txq->desc[pidx].skb = NULL;
+                       eosw_txq->inuse--;
+               }
+       }
+
+       eosw_txq->pidx = eosw_txq->last_pidx + 1;
+}
+
 /**
  * cxgb4_ethofld_send_flowc - Send ETHOFLD flowc request to bind eotid to tc.
  * @dev - netdevice
@@ -2440,9 +2471,11 @@ int cxgb4_ethofld_send_flowc(struct net_device *dev, u32 eotid, u32 tc)
                                            FW_FLOWC_MNEM_EOSTATE_CLOSING :
                                            FW_FLOWC_MNEM_EOSTATE_ESTABLISHED);
 
-       eosw_txq->cred -= len16;
-       eosw_txq->ncompl++;
-       eosw_txq->last_compl = 0;
+       /* Free up any pending skbs to ensure there's room for
+        * termination FLOWC.
+        */
+       if (tc == FW_SCHED_CLS_NONE)
+               eosw_txq_flush_pending_skbs(eosw_txq);
 
        ret = eosw_txq_enqueue(eosw_txq, skb);
        if (ret) {
@@ -2695,6 +2728,7 @@ static void ofldtxq_stop(struct sge_uld_txq *q, struct fw_wr_hdr *wr)
  *     is ever running at a time ...
  */
 static void service_ofldq(struct sge_uld_txq *q)
+       __must_hold(&q->sendq.lock)
 {
        u64 *pos, *before, *end;
        int credits;
index 239f678a94ed5817af132825078838fb883564e0..2a3480fc1d91493dd3813b28e585ef571c942f4b 100644 (file)
@@ -3742,7 +3742,7 @@ int t4_phy_fw_ver(struct adapter *adap, int *phy_fw_ver)
                 FW_PARAMS_PARAM_Z_V(FW_PARAMS_PARAM_DEV_PHYFW_VERSION));
        ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1,
                              &param, &val);
-       if (ret < 0)
+       if (ret)
                return ret;
        *phy_fw_ver = val;
        return 0;
index bb20e50ddb848960c1db04c5905133543c6b893b..4a9fcd6c226c73d6f1f3df545cefbd899198e9bc 100644 (file)
 
 #define MAC_PORT_CFG2_A 0x818
 
+#define MAC_PORT_PTP_SUM_LO_A 0x990
+#define MAC_PORT_PTP_SUM_HI_A 0x994
+
 #define MPS_CMN_CTL_A  0x9000
 
 #define COUNTPAUSEMCRX_S    5
index 48ea658aa1a6d74a4e27759f673800f80d7a86c3..15efc294f51356b55eedfee9f45dad1f7a86a916 100644 (file)
@@ -1277,7 +1277,7 @@ static const struct net_device_ops tulip_netdev_ops = {
 #endif
 };
 
-const struct pci_device_id early_486_chipsets[] = {
+static const struct pci_device_id early_486_chipsets[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424) },
        { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496) },
        { },
index ebc635f8a4cc498fa4ba147905c68b5a3450941b..15f37c5b8dc14360810c1e6e3da3a8c17d9ecc02 100644 (file)
@@ -74,8 +74,8 @@ err_pci_mem_reg:
        pci_disable_device(pdev);
 err_pci_enable:
 err_mdiobus_alloc:
-       iounmap(port_regs);
 err_hw_alloc:
+       iounmap(port_regs);
 err_ioremap:
        return err;
 }
index bd898f5b4da53e0412ce941ceb00f83559356d18..e74dd1f86bbae8ef45eaca6a71c80f5324f9f5c5 100644 (file)
@@ -488,6 +488,12 @@ struct fec_enet_priv_rx_q {
        struct  sk_buff *rx_skbuff[RX_RING_SIZE];
 };
 
+struct fec_stop_mode_gpr {
+       struct regmap *gpr;
+       u8 reg;
+       u8 bit;
+};
+
 /* The FEC buffer descriptors track the ring buffers.  The rx_bd_base and
  * tx_bd_base always point to the base of the buffer descriptors.  The
  * cur_rx and cur_tx point to the currently available buffer.
@@ -562,6 +568,7 @@ struct fec_enet_private {
        int hwts_tx_en;
        struct delayed_work time_keep;
        struct regulator *reg_phy;
+       struct fec_stop_mode_gpr stop_gpr;
 
        unsigned int tx_align;
        unsigned int rx_align;
index c1c267b61647af88c36a73304a21770fee1df310..dc6f8763a5d4062c33bd553ce0899079833113be 100644 (file)
@@ -62,6 +62,8 @@
 #include <linux/if_vlan.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/prefetch.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 #include <soc/imx/cpuidle.h>
 
 #include <asm/cacheflush.h>
@@ -84,6 +86,56 @@ static void fec_enet_itr_coal_init(struct net_device *ndev);
 #define FEC_ENET_OPD_V 0xFFF0
 #define FEC_MDIO_PM_TIMEOUT  100 /* ms */
 
+struct fec_devinfo {
+       u32 quirks;
+       u8 stop_gpr_reg;
+       u8 stop_gpr_bit;
+};
+
+static const struct fec_devinfo fec_imx25_info = {
+       .quirks = FEC_QUIRK_USE_GASKET | FEC_QUIRK_MIB_CLEAR |
+                 FEC_QUIRK_HAS_FRREG,
+};
+
+static const struct fec_devinfo fec_imx27_info = {
+       .quirks = FEC_QUIRK_MIB_CLEAR | FEC_QUIRK_HAS_FRREG,
+};
+
+static const struct fec_devinfo fec_imx28_info = {
+       .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME |
+                 FEC_QUIRK_SINGLE_MDIO | FEC_QUIRK_HAS_RACC |
+                 FEC_QUIRK_HAS_FRREG,
+};
+
+static const struct fec_devinfo fec_imx6q_info = {
+       .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
+                 FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
+                 FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 |
+                 FEC_QUIRK_HAS_RACC,
+       .stop_gpr_reg = 0x34,
+       .stop_gpr_bit = 27,
+};
+
+static const struct fec_devinfo fec_mvf600_info = {
+       .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC,
+};
+
+static const struct fec_devinfo fec_imx6x_info = {
+       .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
+                 FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
+                 FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
+                 FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
+                 FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE,
+};
+
+static const struct fec_devinfo fec_imx6ul_info = {
+       .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
+                 FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
+                 FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR007885 |
+                 FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC |
+                 FEC_QUIRK_HAS_COALESCE,
+};
+
 static struct platform_device_id fec_devtype[] = {
        {
                /* keep it for coldfire */
@@ -91,39 +143,25 @@ static struct platform_device_id fec_devtype[] = {
                .driver_data = 0,
        }, {
                .name = "imx25-fec",
-               .driver_data = FEC_QUIRK_USE_GASKET | FEC_QUIRK_MIB_CLEAR |
-                              FEC_QUIRK_HAS_FRREG,
+               .driver_data = (kernel_ulong_t)&fec_imx25_info,
        }, {
                .name = "imx27-fec",
-               .driver_data = FEC_QUIRK_MIB_CLEAR | FEC_QUIRK_HAS_FRREG,
+               .driver_data = (kernel_ulong_t)&fec_imx27_info,
        }, {
                .name = "imx28-fec",
-               .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME |
-                               FEC_QUIRK_SINGLE_MDIO | FEC_QUIRK_HAS_RACC |
-                               FEC_QUIRK_HAS_FRREG,
+               .driver_data = (kernel_ulong_t)&fec_imx28_info,
        }, {
                .name = "imx6q-fec",
-               .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
-                               FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
-                               FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 |
-                               FEC_QUIRK_HAS_RACC,
+               .driver_data = (kernel_ulong_t)&fec_imx6q_info,
        }, {
                .name = "mvf600-fec",
-               .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC,
+               .driver_data = (kernel_ulong_t)&fec_mvf600_info,
        }, {
                .name = "imx6sx-fec",
-               .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
-                               FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
-                               FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
-                               FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
-                               FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE,
+               .driver_data = (kernel_ulong_t)&fec_imx6x_info,
        }, {
                .name = "imx6ul-fec",
-               .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
-                               FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
-                               FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR007885 |
-                               FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC |
-                               FEC_QUIRK_HAS_COALESCE,
+               .driver_data = (kernel_ulong_t)&fec_imx6ul_info,
        }, {
                /* sentinel */
        }
@@ -1092,11 +1130,28 @@ fec_restart(struct net_device *ndev)
 
 }
 
+static void fec_enet_stop_mode(struct fec_enet_private *fep, bool enabled)
+{
+       struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
+       struct fec_stop_mode_gpr *stop_gpr = &fep->stop_gpr;
+
+       if (stop_gpr->gpr) {
+               if (enabled)
+                       regmap_update_bits(stop_gpr->gpr, stop_gpr->reg,
+                                          BIT(stop_gpr->bit),
+                                          BIT(stop_gpr->bit));
+               else
+                       regmap_update_bits(stop_gpr->gpr, stop_gpr->reg,
+                                          BIT(stop_gpr->bit), 0);
+       } else if (pdata && pdata->sleep_mode_enable) {
+               pdata->sleep_mode_enable(enabled);
+       }
+}
+
 static void
 fec_stop(struct net_device *ndev)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
-       struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
        u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);
        u32 val;
 
@@ -1125,9 +1180,7 @@ fec_stop(struct net_device *ndev)
                val = readl(fep->hwp + FEC_ECNTRL);
                val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
                writel(val, fep->hwp + FEC_ECNTRL);
-
-               if (pdata && pdata->sleep_mode_enable)
-                       pdata->sleep_mode_enable(true);
+               fec_enet_stop_mode(fep, true);
        }
        writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
 
@@ -3398,6 +3451,37 @@ static int fec_enet_get_irq_cnt(struct platform_device *pdev)
        return irq_cnt;
 }
 
+static int fec_enet_init_stop_mode(struct fec_enet_private *fep,
+                                  struct fec_devinfo *dev_info,
+                                  struct device_node *np)
+{
+       struct device_node *gpr_np;
+       int ret = 0;
+
+       if (!dev_info)
+               return 0;
+
+       gpr_np = of_parse_phandle(np, "gpr", 0);
+       if (!gpr_np)
+               return 0;
+
+       fep->stop_gpr.gpr = syscon_node_to_regmap(gpr_np);
+       if (IS_ERR(fep->stop_gpr.gpr)) {
+               dev_err(&fep->pdev->dev, "could not find gpr regmap\n");
+               ret = PTR_ERR(fep->stop_gpr.gpr);
+               fep->stop_gpr.gpr = NULL;
+               goto out;
+       }
+
+       fep->stop_gpr.reg = dev_info->stop_gpr_reg;
+       fep->stop_gpr.bit = dev_info->stop_gpr_bit;
+
+out:
+       of_node_put(gpr_np);
+
+       return ret;
+}
+
 static int
 fec_probe(struct platform_device *pdev)
 {
@@ -3413,6 +3497,7 @@ fec_probe(struct platform_device *pdev)
        int num_rx_qs;
        char irq_name[8];
        int irq_cnt;
+       struct fec_devinfo *dev_info;
 
        fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
 
@@ -3430,7 +3515,9 @@ fec_probe(struct platform_device *pdev)
        of_id = of_match_device(fec_dt_ids, &pdev->dev);
        if (of_id)
                pdev->id_entry = of_id->data;
-       fep->quirks = pdev->id_entry->driver_data;
+       dev_info = (struct fec_devinfo *)pdev->id_entry->driver_data;
+       if (dev_info)
+               fep->quirks = dev_info->quirks;
 
        fep->netdev = ndev;
        fep->num_rx_queues = num_rx_qs;
@@ -3464,6 +3551,10 @@ fec_probe(struct platform_device *pdev)
        if (of_get_property(np, "fsl,magic-packet", NULL))
                fep->wol_flag |= FEC_WOL_HAS_MAGIC_PACKET;
 
+       ret = fec_enet_init_stop_mode(fep, dev_info, np);
+       if (ret)
+               goto failed_stop_mode;
+
        phy_node = of_parse_phandle(np, "phy-handle", 0);
        if (!phy_node && of_phy_is_fixed_link(np)) {
                ret = of_phy_register_fixed_link(np);
@@ -3632,6 +3723,7 @@ failed_clk:
        if (of_phy_is_fixed_link(np))
                of_phy_deregister_fixed_link(np);
        of_node_put(phy_node);
+failed_stop_mode:
 failed_phy:
        dev_id--;
 failed_ioremap:
@@ -3709,7 +3801,6 @@ static int __maybe_unused fec_resume(struct device *dev)
 {
        struct net_device *ndev = dev_get_drvdata(dev);
        struct fec_enet_private *fep = netdev_priv(ndev);
-       struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
        int ret;
        int val;
 
@@ -3727,8 +3818,8 @@ static int __maybe_unused fec_resume(struct device *dev)
                        goto failed_clk;
                }
                if (fep->wol_flag & FEC_WOL_FLAG_ENABLE) {
-                       if (pdata && pdata->sleep_mode_enable)
-                               pdata->sleep_mode_enable(false);
+                       fec_enet_stop_mode(fep, false);
+
                        val = readl(fep->hwp + FEC_ECNTRL);
                        val &= ~(FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
                        writel(val, fep->hwp + FEC_ECNTRL);
index 4bd33245bad625d7bffb7a7002dc776effd3e956..3de549c6c6930204bbc11d18c81c9ff0ac927c75 100644 (file)
@@ -2189,7 +2189,8 @@ static void __ibmvnic_reset(struct work_struct *work)
                                rc = do_hard_reset(adapter, rwi, reset_state);
                                rtnl_unlock();
                        }
-               } else {
+               } else if (!(rwi->reset_reason == VNIC_RESET_FATAL &&
+                               adapter->from_passive_init)) {
                        rc = do_reset(adapter, rwi, reset_state);
                }
                kfree(rwi);
index f7103356ef56288efb05b58b7671bb8f23d465ca..0d51cbc88028b797c3afdae8be1555553110c553 100644 (file)
@@ -1476,7 +1476,7 @@ static bool e1000_check_64k_bound(struct e1000_adapter *adapter, void *start,
        if (hw->mac_type == e1000_82545 ||
            hw->mac_type == e1000_ce4100 ||
            hw->mac_type == e1000_82546) {
-               return ((begin ^ (end - 1)) >> 16) != 0 ? false : true;
+               return ((begin ^ (end - 1)) >> 16) == 0;
        }
 
        return true;
index 8c3e753bfb9d4883953003a7a834fe50c3ca56ee..2a037ec244b945aa04f7f263f77177c069b6ce6a 100644 (file)
@@ -1611,7 +1611,7 @@ static int i40e_config_rss_aq(struct i40e_vsi *vsi, const u8 *seed,
                }
        }
        if (lut) {
-               bool pf_lut = vsi->type == I40E_VSI_MAIN ? true : false;
+               bool pf_lut = vsi->type == I40E_VSI_MAIN;
 
                ret = i40e_aq_set_rss_lut(hw, vsi->id, pf_lut, lut, lut_size);
                if (ret) {
@@ -11436,7 +11436,7 @@ static int i40e_get_rss_aq(struct i40e_vsi *vsi, const u8 *seed,
        }
 
        if (lut) {
-               bool pf_lut = vsi->type == I40E_VSI_MAIN ? true : false;
+               bool pf_lut = vsi->type == I40E_VSI_MAIN;
 
                ret = i40e_aq_get_rss_lut(hw, vsi->id, pf_lut, lut, lut_size);
                if (ret) {
index 5be61f73b6abb79268e6b5e85a2f8f3c5c382831..51889770958d841f93c130e045fc10eca45c6cbc 100644 (file)
@@ -5383,7 +5383,7 @@ static int __init mvneta_driver_init(void)
 {
        int ret;
 
-       ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "net/mvmeta:online",
+       ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "net/mvneta:online",
                                      mvneta_cpu_online,
                                      mvneta_cpu_down_prepare);
        if (ret < 0)
index 8972cdd559e85c1989389ad7c008f17c43a829fb..7352244c5e68b5902e711d22206ff264737070a8 100644 (file)
@@ -1428,6 +1428,9 @@ int mvpp2_ethtool_cls_rule_del(struct mvpp2_port *port,
        struct mvpp2_ethtool_fs *efs;
        int ret;
 
+       if (info->fs.location >= MVPP2_N_RFS_ENTRIES_PER_FLOW)
+               return -EINVAL;
+
        efs = port->rfs_rules[info->fs.location];
        if (!efs)
                return -EINVAL;
index 1fa60e985b43aeca4c2d0d41d79d3751b3b5b407..2b5dad2ec650c0874ada85d02c1abfce20cae784 100644 (file)
@@ -4329,6 +4329,8 @@ static int mvpp2_ethtool_get_rxfh_context(struct net_device *dev, u32 *indir,
 
        if (!mvpp22_rss_is_supported())
                return -EOPNOTSUPP;
+       if (rss_context >= MVPP22_N_RSS_TABLES)
+               return -EINVAL;
 
        if (hfunc)
                *hfunc = ETH_RSS_HASH_CRC32;
index 8d28f90acfe76d5a79130ba62b1578dce95b05be..09047109d0daac60bc85e6f64c5bce3cb91764d8 100644 (file)
@@ -65,6 +65,17 @@ u32 mtk_r32(struct mtk_eth *eth, unsigned reg)
        return __raw_readl(eth->base + reg);
 }
 
+u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned reg)
+{
+       u32 val;
+
+       val = mtk_r32(eth, reg);
+       val &= ~mask;
+       val |= set;
+       mtk_w32(eth, val, reg);
+       return reg;
+}
+
 static int mtk_mdio_busy_wait(struct mtk_eth *eth)
 {
        unsigned long t_start = jiffies;
@@ -193,7 +204,7 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode,
        struct mtk_mac *mac = container_of(config, struct mtk_mac,
                                           phylink_config);
        struct mtk_eth *eth = mac->hw;
-       u32 mcr_cur, mcr_new, sid;
+       u32 mcr_cur, mcr_new, sid, i;
        int val, ge_mode, err;
 
        /* MT76x8 has no hardware settings between for the MAC */
@@ -255,6 +266,17 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode,
                                    PHY_INTERFACE_MODE_TRGMII)
                                        mtk_gmac0_rgmii_adjust(mac->hw,
                                                               state->speed);
+
+                               /* mt7623_pad_clk_setup */
+                               for (i = 0 ; i < NUM_TRGMII_CTRL; i++)
+                                       mtk_w32(mac->hw,
+                                               TD_DM_DRVP(8) | TD_DM_DRVN(8),
+                                               TRGMII_TD_ODT(i));
+
+                               /* Assert/release MT7623 RXC reset */
+                               mtk_m32(mac->hw, 0, RXC_RST | RXC_DQSISEL,
+                                       TRGMII_RCK_CTRL);
+                               mtk_m32(mac->hw, RXC_RST, 0, TRGMII_RCK_CTRL);
                        }
                }
 
index 85830fe14a1b474613b6b2306b0cf28e49c59a97..454cfcd465fdafae17e4c5340d5b432431d6a6d5 100644 (file)
 #define DQSI0(x)               ((x << 0) & GENMASK(6, 0))
 #define DQSI1(x)               ((x << 8) & GENMASK(14, 8))
 #define RXCTL_DMWTLAT(x)       ((x << 16) & GENMASK(18, 16))
+#define RXC_RST                        BIT(31)
 #define RXC_DQSISEL            BIT(30)
 #define RCK_CTRL_RGMII_1000    (RXC_DQSISEL | RXCTL_DMWTLAT(2) | DQSI1(16))
 #define RCK_CTRL_RGMII_10_100  RXCTL_DMWTLAT(2)
 
+#define NUM_TRGMII_CTRL                5
+
 /* TRGMII RXC control register */
 #define TRGMII_TCK_CTRL                0x10340
 #define TXCTL_DMWTLAT(x)       ((x << 16) & GENMASK(18, 16))
 #define TCK_CTRL_RGMII_1000    TXCTL_DMWTLAT(2)
 #define TCK_CTRL_RGMII_10_100  (TXC_INV | TXCTL_DMWTLAT(2))
 
+/* TRGMII TX Drive Strength */
+#define TRGMII_TD_ODT(i)       (0x10354 + 8 * (i))
+#define  TD_DM_DRVP(x)         ((x) & 0xf)
+#define  TD_DM_DRVN(x)         (((x) & 0xf) << 4)
+
 /* TRGMII Interface mode register */
 #define INTF_MODE              0x10390
 #define TRGMII_INTF_DIS                BIT(0)
index 4d5ca302c067126b8627cb4809485b45c10e2460..a30edb436f4af11526e04c09623840288ebe4a29 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <linux/moduleparam.h>
+#include <linux/indirect_call_wrapper.h>
 
 #include "mlx4_en.h"
 
@@ -261,6 +262,10 @@ static void mlx4_en_stamp_wqe(struct mlx4_en_priv *priv,
        }
 }
 
+INDIRECT_CALLABLE_DECLARE(u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
+                                                  struct mlx4_en_tx_ring *ring,
+                                                  int index, u64 timestamp,
+                                                  int napi_mode));
 
 u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
                         struct mlx4_en_tx_ring *ring,
@@ -329,6 +334,11 @@ u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
        return tx_info->nr_txbb;
 }
 
+INDIRECT_CALLABLE_DECLARE(u32 mlx4_en_recycle_tx_desc(struct mlx4_en_priv *priv,
+                                                     struct mlx4_en_tx_ring *ring,
+                                                     int index, u64 timestamp,
+                                                     int napi_mode));
+
 u32 mlx4_en_recycle_tx_desc(struct mlx4_en_priv *priv,
                            struct mlx4_en_tx_ring *ring,
                            int index, u64 timestamp,
@@ -449,7 +459,9 @@ bool mlx4_en_process_tx_cq(struct net_device *dev,
                                timestamp = mlx4_en_get_cqe_ts(cqe);
 
                        /* free next descriptor */
-                       last_nr_txbb = ring->free_tx_desc(
+                       last_nr_txbb = INDIRECT_CALL_2(ring->free_tx_desc,
+                                                      mlx4_en_free_tx_desc,
+                                                      mlx4_en_recycle_tx_desc,
                                        priv, ring, ring_index,
                                        timestamp, napi_budget);
 
index 5716c3d2bb86aac7317e06ee0b89184e14238881..c72c4e1ea383b81a0b3e5f4eb791e87e715e9f6f 100644 (file)
@@ -2550,6 +2550,7 @@ static int mlx4_allocate_default_counters(struct mlx4_dev *dev)
 
                if (!err || err == -ENOSPC) {
                        priv->def_counter[port] = idx;
+                       err = 0;
                } else if (err == -ENOENT) {
                        err = 0;
                        continue;
@@ -2600,7 +2601,8 @@ int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx, u8 usage)
                                   MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
                if (!err)
                        *idx = get_param_l(&out_param);
-
+               if (WARN_ON(err == -ENOSPC))
+                       err = -EINVAL;
                return err;
        }
        return __mlx4_counter_alloc(dev, idx);
index 312e0a1ad43d7330ac26fbce72109b80592178ca..7d69a3061f1789d0804cff1f0c7f612ff02ed465 100644 (file)
@@ -7,10 +7,10 @@ config MLX5_CORE
        tristate "Mellanox 5th generation network adapters (ConnectX series) core driver"
        depends on PCI
        select NET_DEVLINK
-       imply PTP_1588_CLOCK
-       imply VXLAN
-       imply MLXFW
-       imply PCI_HYPERV_INTERFACE
+       depends on VXLAN || !VXLAN
+       depends on MLXFW || !MLXFW
+       depends on PTP_1588_CLOCK || !PTP_1588_CLOCK
+       depends on PCI_HYPERV_INTERFACE || !PCI_HYPERV_INTERFACE
        default n
        ---help---
          Core driver for low level functionality of the ConnectX-4 and
index 34cba97f7bf4891a2bb26e10cf3c31d30cd40550..cede5bdfd598e49b44ce133b61bc6509faf923fa 100644 (file)
@@ -888,7 +888,6 @@ static void cmd_work_handler(struct work_struct *work)
        }
 
        cmd->ent_arr[ent->idx] = ent;
-       set_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state);
        lay = get_inst(cmd, ent->idx);
        ent->lay = lay;
        memset(lay, 0, sizeof(*lay));
@@ -910,6 +909,7 @@ static void cmd_work_handler(struct work_struct *work)
 
        if (ent->callback)
                schedule_delayed_work(&ent->cb_timeout_work, cb_timeout);
+       set_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state);
 
        /* Skip sending command to fw if internal error */
        if (pci_channel_offline(dev->pdev) ||
@@ -922,6 +922,10 @@ static void cmd_work_handler(struct work_struct *work)
                MLX5_SET(mbox_out, ent->out, syndrome, drv_synd);
 
                mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
+               /* no doorbell, no need to keep the entry */
+               free_ent(cmd, ent->idx);
+               if (ent->callback)
+                       free_cmd(ent);
                return;
        }
 
index bdeb291f6b679ac53b1fb4e67b944b7783054ed3..e94f0c4d74a724fb621cd102780e56e62ae87292 100644 (file)
@@ -23,7 +23,10 @@ static int mlx5_devlink_flash_update(struct devlink *devlink,
        if (err)
                return err;
 
-       return mlx5_firmware_flash(dev, fw, extack);
+       err = mlx5_firmware_flash(dev, fw, extack);
+       release_firmware(fw);
+
+       return err;
 }
 
 static u8 mlx5_fw_ver_major(u32 version)
index c9c9b479bda5214f27d8245450e5efce2aefc01e..5ce6ebbc7f109908f746d56b5f85313e6dbb425b 100644 (file)
@@ -935,7 +935,7 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
                return NULL;
        }
 
-       tracer = kzalloc(sizeof(*tracer), GFP_KERNEL);
+       tracer = kvzalloc(sizeof(*tracer), GFP_KERNEL);
        if (!tracer)
                return ERR_PTR(-ENOMEM);
 
@@ -982,7 +982,7 @@ destroy_workqueue:
        tracer->dev = NULL;
        destroy_workqueue(tracer->work_queue);
 free_tracer:
-       kfree(tracer);
+       kvfree(tracer);
        return ERR_PTR(err);
 }
 
@@ -1061,7 +1061,7 @@ void mlx5_fw_tracer_destroy(struct mlx5_fw_tracer *tracer)
        mlx5_fw_tracer_destroy_log_buf(tracer);
        flush_workqueue(tracer->work_queue);
        destroy_workqueue(tracer->work_queue);
-       kfree(tracer);
+       kvfree(tracer);
 }
 
 static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data)
index 12a61bf82c14f8267b39afa0e194459e1a4b34b5..23701c0e36ec38c3533deb67c64e62da9b50bbf3 100644 (file)
@@ -367,6 +367,7 @@ enum {
        MLX5E_SQ_STATE_AM,
        MLX5E_SQ_STATE_TLS,
        MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE,
+       MLX5E_SQ_STATE_PENDING_XSK_TX,
 };
 
 struct mlx5e_sq_wqe_info {
@@ -960,7 +961,7 @@ void mlx5e_page_release_dynamic(struct mlx5e_rq *rq,
 void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe);
 void mlx5e_handle_rx_cqe_mpwrq(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe);
 bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq);
-void mlx5e_poll_ico_cq(struct mlx5e_cq *cq);
+int mlx5e_poll_ico_cq(struct mlx5e_cq *cq);
 bool mlx5e_post_rx_mpwqes(struct mlx5e_rq *rq);
 void mlx5e_dealloc_rx_wqe(struct mlx5e_rq *rq, u16 ix);
 void mlx5e_dealloc_rx_mpwqe(struct mlx5e_rq *rq, u16 ix);
index ad3e3a65d403c1e776e18b97e569e9e180add40b..a172c5e39710b78362fadfd1db499da4786e4638 100644 (file)
@@ -12,6 +12,7 @@
 #include <net/flow_offload.h>
 #include <net/netfilter/nf_flow_table.h>
 #include <linux/workqueue.h>
+#include <linux/xarray.h>
 
 #include "esw/chains.h"
 #include "en/tc_ct.h"
@@ -35,7 +36,7 @@ struct mlx5_tc_ct_priv {
        struct mlx5_eswitch *esw;
        const struct net_device *netdev;
        struct idr fte_ids;
-       struct idr tuple_ids;
+       struct xarray tuple_ids;
        struct rhashtable zone_ht;
        struct mlx5_flow_table *ct;
        struct mlx5_flow_table *ct_nat;
@@ -67,11 +68,9 @@ struct mlx5_ct_ft {
        struct nf_flowtable *nf_ft;
        struct mlx5_tc_ct_priv *ct_priv;
        struct rhashtable ct_entries_ht;
-       struct list_head ct_entries_list;
 };
 
 struct mlx5_ct_entry {
-       struct list_head list;
        u16 zone;
        struct rhash_head node;
        struct flow_rule *flow_rule;
@@ -240,7 +239,7 @@ mlx5_tc_ct_entry_del_rule(struct mlx5_tc_ct_priv *ct_priv,
 
        mlx5_eswitch_del_offloaded_rule(esw, zone_rule->rule, attr);
        mlx5_modify_header_dealloc(esw->dev, attr->modify_hdr);
-       idr_remove(&ct_priv->tuple_ids, zone_rule->tupleid);
+       xa_erase(&ct_priv->tuple_ids, zone_rule->tupleid);
 }
 
 static void
@@ -485,7 +484,7 @@ mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv,
        struct mlx5_esw_flow_attr *attr = &zone_rule->attr;
        struct mlx5_eswitch *esw = ct_priv->esw;
        struct mlx5_flow_spec *spec = NULL;
-       u32 tupleid = 1;
+       u32 tupleid;
        int err;
 
        zone_rule->nat = nat;
@@ -495,12 +494,12 @@ mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv,
                return -ENOMEM;
 
        /* Get tuple unique id */
-       err = idr_alloc_u32(&ct_priv->tuple_ids, zone_rule, &tupleid,
-                           TUPLE_ID_MAX, GFP_KERNEL);
+       err = xa_alloc(&ct_priv->tuple_ids, &tupleid, zone_rule,
+                      XA_LIMIT(1, TUPLE_ID_MAX), GFP_KERNEL);
        if (err) {
                netdev_warn(ct_priv->netdev,
                            "Failed to allocate tuple id, err: %d\n", err);
-               goto err_idr_alloc;
+               goto err_xa_alloc;
        }
        zone_rule->tupleid = tupleid;
 
@@ -541,8 +540,8 @@ mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv,
 err_rule:
        mlx5_modify_header_dealloc(esw->dev, attr->modify_hdr);
 err_mod_hdr:
-       idr_remove(&ct_priv->tuple_ids, zone_rule->tupleid);
-err_idr_alloc:
+       xa_erase(&ct_priv->tuple_ids, zone_rule->tupleid);
+err_xa_alloc:
        kfree(spec);
        return err;
 }
@@ -617,8 +616,6 @@ mlx5_tc_ct_block_flow_offload_add(struct mlx5_ct_ft *ft,
        if (err)
                goto err_insert;
 
-       list_add(&entry->list, &ft->ct_entries_list);
-
        return 0;
 
 err_insert:
@@ -646,7 +643,6 @@ mlx5_tc_ct_block_flow_offload_del(struct mlx5_ct_ft *ft,
        WARN_ON(rhashtable_remove_fast(&ft->ct_entries_ht,
                                       &entry->node,
                                       cts_ht_params));
-       list_del(&entry->list);
        kfree(entry);
 
        return 0;
@@ -818,7 +814,6 @@ mlx5_tc_ct_add_ft_cb(struct mlx5_tc_ct_priv *ct_priv, u16 zone,
        ft->zone = zone;
        ft->nf_ft = nf_ft;
        ft->ct_priv = ct_priv;
-       INIT_LIST_HEAD(&ft->ct_entries_list);
        refcount_set(&ft->refcount, 1);
 
        err = rhashtable_init(&ft->ct_entries_ht, &cts_ht_params);
@@ -847,12 +842,12 @@ err_init:
 }
 
 static void
-mlx5_tc_ct_flush_ft(struct mlx5_tc_ct_priv *ct_priv, struct mlx5_ct_ft *ft)
+mlx5_tc_ct_flush_ft_entry(void *ptr, void *arg)
 {
-       struct mlx5_ct_entry *entry;
+       struct mlx5_tc_ct_priv *ct_priv = arg;
+       struct mlx5_ct_entry *entry = ptr;
 
-       list_for_each_entry(entry, &ft->ct_entries_list, list)
-               mlx5_tc_ct_entry_del_rules(ft->ct_priv, entry);
+       mlx5_tc_ct_entry_del_rules(ct_priv, entry);
 }
 
 static void
@@ -863,9 +858,10 @@ mlx5_tc_ct_del_ft_cb(struct mlx5_tc_ct_priv *ct_priv, struct mlx5_ct_ft *ft)
 
        nf_flow_table_offload_del_cb(ft->nf_ft,
                                     mlx5_tc_ct_block_flow_offload, ft);
-       mlx5_tc_ct_flush_ft(ct_priv, ft);
        rhashtable_remove_fast(&ct_priv->zone_ht, &ft->node, zone_params);
-       rhashtable_destroy(&ft->ct_entries_ht);
+       rhashtable_free_and_destroy(&ft->ct_entries_ht,
+                                   mlx5_tc_ct_flush_ft_entry,
+                                   ct_priv);
        kfree(ft);
 }
 
@@ -1304,7 +1300,7 @@ mlx5_tc_ct_init(struct mlx5_rep_uplink_priv *uplink_priv)
        }
 
        idr_init(&ct_priv->fte_ids);
-       idr_init(&ct_priv->tuple_ids);
+       xa_init_flags(&ct_priv->tuple_ids, XA_FLAGS_ALLOC1);
        mutex_init(&ct_priv->control_lock);
        rhashtable_init(&ct_priv->zone_ht, &zone_params);
 
@@ -1339,7 +1335,7 @@ mlx5_tc_ct_clean(struct mlx5_rep_uplink_priv *uplink_priv)
 
        rhashtable_destroy(&ct_priv->zone_ht);
        mutex_destroy(&ct_priv->control_lock);
-       idr_destroy(&ct_priv->tuple_ids);
+       xa_destroy(&ct_priv->tuple_ids);
        idr_destroy(&ct_priv->fte_ids);
        kfree(ct_priv);
 
@@ -1357,7 +1353,7 @@ mlx5e_tc_ct_restore_flow(struct mlx5_rep_uplink_priv *uplink_priv,
        if (!ct_priv || !tupleid)
                return true;
 
-       zone_rule = idr_find(&ct_priv->tuple_ids, tupleid);
+       zone_rule = xa_load(&ct_priv->tuple_ids, tupleid);
        if (!zone_rule)
                return false;
 
index fe2d596cb361fa1ae03bfbfe28c2741965804f4b..3bcdb5b2fc2034f7819c2a0a86cdbe89b09d5564 100644 (file)
@@ -33,6 +33,9 @@ int mlx5e_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
                if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &c->xskicosq.state)))
                        return 0;
 
+               if (test_and_set_bit(MLX5E_SQ_STATE_PENDING_XSK_TX, &c->xskicosq.state))
+                       return 0;
+
                spin_lock(&c->xskicosq_lock);
                mlx5e_trigger_irq(&c->xskicosq);
                spin_unlock(&c->xskicosq_lock);
index dd7f338425eb1e87328fc6ef6a7d75151e11cb69..b314adf438da2d55c412e847a7ad149d415bcc65 100644 (file)
@@ -3583,7 +3583,12 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
        struct mlx5e_vport_stats *vstats = &priv->stats.vport;
        struct mlx5e_pport_stats *pstats = &priv->stats.pport;
 
-       if (!mlx5e_monitor_counter_supported(priv)) {
+       /* In switchdev mode, monitor counters doesn't monitor
+        * rx/tx stats of 802_3. The update stats mechanism
+        * should keep the 802_3 layout counters updated
+        */
+       if (!mlx5e_monitor_counter_supported(priv) ||
+           mlx5e_is_uplink_rep(priv)) {
                /* update HW stats in background for next time */
                mlx5e_queue_update_stats(priv);
        }
@@ -5526,8 +5531,8 @@ static void mlx5e_remove(struct mlx5_core_dev *mdev, void *vpriv)
 #ifdef CONFIG_MLX5_CORE_EN_DCB
        mlx5e_dcbnl_delete_app(priv);
 #endif
-       mlx5e_devlink_port_unregister(priv);
        unregister_netdev(priv->netdev);
+       mlx5e_devlink_port_unregister(priv);
        mlx5e_detach(mdev, vpriv);
        mlx5e_destroy_netdev(priv);
 }
index 2a0243e4af757ea59df77ea4386004827989b0d6..f372e94948fd64f0879b672ab5bfcba51b25ee98 100644 (file)
@@ -1773,19 +1773,14 @@ static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv)
 
 static int mlx5e_init_ul_rep_rx(struct mlx5e_priv *priv)
 {
-       int err = mlx5e_init_rep_rx(priv);
-
-       if (err)
-               return err;
-
        mlx5e_create_q_counters(priv);
-       return 0;
+       return mlx5e_init_rep_rx(priv);
 }
 
 static void mlx5e_cleanup_ul_rep_rx(struct mlx5e_priv *priv)
 {
-       mlx5e_destroy_q_counters(priv);
        mlx5e_cleanup_rep_rx(priv);
+       mlx5e_destroy_q_counters(priv);
 }
 
 static int mlx5e_init_uplink_rep_tx(struct mlx5e_rep_priv *rpriv)
@@ -2050,29 +2045,30 @@ static int register_devlink_port(struct mlx5_core_dev *dev,
        struct mlx5_eswitch_rep *rep = rpriv->rep;
        struct netdev_phys_item_id ppid = {};
        unsigned int dl_port_index = 0;
+       u16 pfnum;
 
        if (!is_devlink_port_supported(dev, rpriv))
                return 0;
 
        mlx5e_rep_get_port_parent_id(rpriv->netdev, &ppid);
+       pfnum = PCI_FUNC(dev->pdev->devfn);
 
        if (rep->vport == MLX5_VPORT_UPLINK) {
                devlink_port_attrs_set(&rpriv->dl_port,
                                       DEVLINK_PORT_FLAVOUR_PHYSICAL,
-                                      PCI_FUNC(dev->pdev->devfn), false, 0,
+                                      pfnum, false, 0,
                                       &ppid.id[0], ppid.id_len);
                dl_port_index = vport_to_devlink_port_index(dev, rep->vport);
        } else if (rep->vport == MLX5_VPORT_PF) {
                devlink_port_attrs_pci_pf_set(&rpriv->dl_port,
                                              &ppid.id[0], ppid.id_len,
-                                             dev->pdev->devfn);
+                                             pfnum);
                dl_port_index = rep->vport;
        } else if (mlx5_eswitch_is_vf_vport(dev->priv.eswitch,
                                            rpriv->rep->vport)) {
                devlink_port_attrs_pci_vf_set(&rpriv->dl_port,
                                              &ppid.id[0], ppid.id_len,
-                                             dev->pdev->devfn,
-                                             rep->vport - 1);
+                                             pfnum, rep->vport - 1);
                dl_port_index = vport_to_devlink_port_index(dev, rep->vport);
        }
 
index 6173faf542b06e4d65c5ac31dcb21bb536ff3ee2..e2beb89c1832fb443985fbd325c9893dced45128 100644 (file)
@@ -589,7 +589,7 @@ bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq)
        return !!err;
 }
 
-void mlx5e_poll_ico_cq(struct mlx5e_cq *cq)
+int mlx5e_poll_ico_cq(struct mlx5e_cq *cq)
 {
        struct mlx5e_icosq *sq = container_of(cq, struct mlx5e_icosq, cq);
        struct mlx5_cqe64 *cqe;
@@ -597,11 +597,11 @@ void mlx5e_poll_ico_cq(struct mlx5e_cq *cq)
        int i;
 
        if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &sq->state)))
-               return;
+               return 0;
 
        cqe = mlx5_cqwq_get_cqe(&cq->wq);
        if (likely(!cqe))
-               return;
+               return 0;
 
        /* sq->cc must be updated only after mlx5_cqwq_update_db_record(),
         * otherwise a cq overrun may occur
@@ -650,6 +650,8 @@ void mlx5e_poll_ico_cq(struct mlx5e_cq *cq)
        sq->cc = sqcc;
 
        mlx5_cqwq_update_db_record(&cq->wq);
+
+       return i;
 }
 
 bool mlx5e_post_rx_mpwqes(struct mlx5e_rq *rq)
index 438128dde187d7ec58892c2879c6037f807f576f..a574c588269a0f0110eb05c745351c9a8c0c761e 100644 (file)
@@ -1343,7 +1343,8 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
        if (err)
                return err;
 
-       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR &&
+           !(attr->ct_attr.ct_action & TCA_CT_ACT_CLEAR)) {
                err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
                dealloc_mod_hdr_actions(&parse_attr->mod_hdr_acts);
                if (err)
@@ -3558,12 +3559,13 @@ static int add_vlan_pop_action(struct mlx5e_priv *priv,
                               struct mlx5_esw_flow_attr *attr,
                               u32 *action)
 {
-       int nest_level = attr->parse_attr->filter_dev->lower_level;
        struct flow_action_entry vlan_act = {
                .id = FLOW_ACTION_VLAN_POP,
        };
-       int err = 0;
+       int nest_level, err = 0;
 
+       nest_level = attr->parse_attr->filter_dev->lower_level -
+                                               priv->netdev->lower_level;
        while (nest_level--) {
                err = parse_tc_vlan_action(priv, &vlan_act, attr, action);
                if (err)
index 87c49e7a164c84f6aa23b0f057d06a8b09a6168c..acb20215a33bb5c544b6b41cf0f60e975c155ab5 100644 (file)
@@ -152,7 +152,11 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
                                mlx5e_post_rx_wqes,
                                rq);
        if (xsk_open) {
-               mlx5e_poll_ico_cq(&c->xskicosq.cq);
+               if (mlx5e_poll_ico_cq(&c->xskicosq.cq))
+                       /* Don't clear the flag if nothing was polled to prevent
+                        * queueing more WQEs and overflowing XSKICOSQ.
+                        */
+                       clear_bit(MLX5E_SQ_STATE_PENDING_XSK_TX, &c->xskicosq.state);
                busy |= mlx5e_poll_xdpsq_cq(&xsksq->cq);
                busy_xsk |= mlx5e_napi_xsk_post(xsksq, xskrq);
        }
index 39f42f985fbd622d1592a5632615c40e49402bf3..c1848b57f61c8dc5c5822fdb1c453726f140fba2 100644 (file)
@@ -403,7 +403,6 @@ enum {
        MLX5_ESW_ATTR_FLAG_VLAN_HANDLED  = BIT(0),
        MLX5_ESW_ATTR_FLAG_SLOW_PATH     = BIT(1),
        MLX5_ESW_ATTR_FLAG_NO_IN_PORT    = BIT(2),
-       MLX5_ESW_ATTR_FLAG_HAIRPIN       = BIT(3),
 };
 
 struct mlx5_esw_flow_attr {
index f171eb2234b07e573ea49556582820d47ecf0ecd..5d9def18ae3a7b7496d8f4cc7c77f610c23b296f 100644 (file)
@@ -300,7 +300,6 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
        bool split = !!(attr->split_count);
        struct mlx5_flow_handle *rule;
        struct mlx5_flow_table *fdb;
-       bool hairpin = false;
        int j, i = 0;
 
        if (esw->mode != MLX5_ESWITCH_OFFLOADS)
@@ -398,21 +397,16 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
                goto err_esw_get;
        }
 
-       if (mlx5_eswitch_termtbl_required(esw, attr, &flow_act, spec)) {
+       if (mlx5_eswitch_termtbl_required(esw, attr, &flow_act, spec))
                rule = mlx5_eswitch_add_termtbl_rule(esw, fdb, spec, attr,
                                                     &flow_act, dest, i);
-               hairpin = true;
-       } else {
+       else
                rule = mlx5_add_flow_rules(fdb, spec, &flow_act, dest, i);
-       }
        if (IS_ERR(rule))
                goto err_add_rule;
        else
                atomic64_inc(&esw->offloads.num_flows);
 
-       if (hairpin)
-               attr->flags |= MLX5_ESW_ATTR_FLAG_HAIRPIN;
-
        return rule;
 
 err_add_rule:
@@ -501,7 +495,7 @@ __mlx5_eswitch_del_rule(struct mlx5_eswitch *esw,
 
        mlx5_del_flow_rules(rule);
 
-       if (attr->flags & MLX5_ESW_ATTR_FLAG_HAIRPIN) {
+       if (!(attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH)) {
                /* unref the term table */
                for (i = 0; i < MLX5_MAX_FLOW_FWD_VPORTS; i++) {
                        if (attr->dests[i].termtbl)
@@ -1556,9 +1550,9 @@ static int esw_create_restore_table(struct mlx5_eswitch *esw)
                                           MLX5_FLOW_NAMESPACE_KERNEL, 1,
                                           modact);
        if (IS_ERR(mod_hdr)) {
+               err = PTR_ERR(mod_hdr);
                esw_warn(dev, "Failed to create restore mod header, err: %d\n",
                         err);
-               err = PTR_ERR(mod_hdr);
                goto err_mod_hdr;
        }
 
@@ -2225,10 +2219,12 @@ static int esw_offloads_steering_init(struct mlx5_eswitch *esw)
                total_vports = num_vfs + MLX5_SPECIAL_VPORTS(esw->dev);
 
        memset(&esw->fdb_table.offloads, 0, sizeof(struct offloads_fdb));
+       mutex_init(&esw->fdb_table.offloads.vports.lock);
+       hash_init(esw->fdb_table.offloads.vports.table);
 
        err = esw_create_uplink_offloads_acl_tables(esw);
        if (err)
-               return err;
+               goto create_acl_err;
 
        err = esw_create_offloads_table(esw, total_vports);
        if (err)
@@ -2246,9 +2242,6 @@ static int esw_offloads_steering_init(struct mlx5_eswitch *esw)
        if (err)
                goto create_fg_err;
 
-       mutex_init(&esw->fdb_table.offloads.vports.lock);
-       hash_init(esw->fdb_table.offloads.vports.table);
-
        return 0;
 
 create_fg_err:
@@ -2259,18 +2252,19 @@ create_restore_err:
        esw_destroy_offloads_table(esw);
 create_offloads_err:
        esw_destroy_uplink_offloads_acl_tables(esw);
-
+create_acl_err:
+       mutex_destroy(&esw->fdb_table.offloads.vports.lock);
        return err;
 }
 
 static void esw_offloads_steering_cleanup(struct mlx5_eswitch *esw)
 {
-       mutex_destroy(&esw->fdb_table.offloads.vports.lock);
        esw_destroy_vport_rx_group(esw);
        esw_destroy_offloads_fdb_tables(esw);
        esw_destroy_restore_table(esw);
        esw_destroy_offloads_table(esw);
        esw_destroy_uplink_offloads_acl_tables(esw);
+       mutex_destroy(&esw->fdb_table.offloads.vports.lock);
 }
 
 static void
@@ -2383,9 +2377,9 @@ int esw_offloads_enable(struct mlx5_eswitch *esw)
 err_vports:
        esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK);
 err_uplink:
-       esw_set_passing_vport_metadata(esw, false);
-err_steering_init:
        esw_offloads_steering_cleanup(esw);
+err_steering_init:
+       esw_set_passing_vport_metadata(esw, false);
 err_vport_metadata:
        mlx5_rdma_disable_roce(esw->dev);
        mutex_destroy(&esw->offloads.termtbl_mutex);
index fa1665caac462c3aae87996a5ed6d8ff864124be..f99e1752d4e5c087fe4b814cc3aebdf8a5ff0a22 100644 (file)
@@ -243,7 +243,7 @@ recover_from_sw_reset:
                if (mlx5_get_nic_state(dev) == MLX5_NIC_IFC_DISABLED)
                        break;
 
-               cond_resched();
+               msleep(20);
        } while (!time_after(jiffies, end));
 
        if (mlx5_get_nic_state(dev) != MLX5_NIC_IFC_DISABLED) {
index c0ab9cf74929ca4346ff03490090c293baa5fb6b..18719acb7e547422a0c65faaad85eb2b07923fa8 100644 (file)
@@ -695,6 +695,12 @@ static void dr_cq_event(struct mlx5_core_cq *mcq,
        pr_info("CQ event %u on CQ #%u\n", event, mcq->cqn);
 }
 
+static void dr_cq_complete(struct mlx5_core_cq *mcq,
+                          struct mlx5_eqe *eqe)
+{
+       pr_err("CQ completion CQ: #%u\n", mcq->cqn);
+}
+
 static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
                                      struct mlx5_uars_page *uar,
                                      size_t ncqe)
@@ -756,6 +762,7 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
        mlx5_fill_page_frag_array(&cq->wq_ctrl.buf, pas);
 
        cq->mcq.event = dr_cq_event;
+       cq->mcq.comp  = dr_cq_complete;
 
        err = mlx5_core_create_cq(mdev, &cq->mcq, in, inlen, out, sizeof(out));
        kvfree(in);
@@ -767,7 +774,12 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
        cq->mcq.set_ci_db = cq->wq_ctrl.db.db;
        cq->mcq.arm_db = cq->wq_ctrl.db.db + 1;
        *cq->mcq.set_ci_db = 0;
-       *cq->mcq.arm_db = 0;
+
+       /* set no-zero value, in order to avoid the HW to run db-recovery on
+        * CQ that used in polling mode.
+        */
+       *cq->mcq.arm_db = cpu_to_be32(2 << 28);
+
        cq->mcq.vector = 0;
        cq->mcq.irqn = irqn;
        cq->mcq.uar = uar;
index 70a104e728f622656b1bd878b7a4994d2788502e..c3d04319ff44d6cf3b91af78578921349284ec4d 100644 (file)
@@ -380,7 +380,7 @@ struct mlxsw_afa_block *mlxsw_afa_block_create(struct mlxsw_afa *mlxsw_afa)
 
        block = kzalloc(sizeof(*block), GFP_KERNEL);
        if (!block)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        INIT_LIST_HEAD(&block->resource_list);
        block->afa = mlxsw_afa;
 
@@ -408,7 +408,7 @@ err_second_set_create:
        mlxsw_afa_set_destroy(block->first_set);
 err_first_set_create:
        kfree(block);
-       return NULL;
+       return ERR_PTR(-ENOMEM);
 }
 EXPORT_SYMBOL(mlxsw_afa_block_create);
 
index 6c66a0f1b79e38948af98b08bda300b55d5738e9..ad69913f19c10c7c645f574938f1c6f9e949384f 100644 (file)
@@ -88,8 +88,8 @@ static int mlxsw_sp2_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, void *priv,
         * to be written using PEFA register to all indexes for all regions.
         */
        afa_block = mlxsw_afa_block_create(mlxsw_sp->afa);
-       if (!afa_block) {
-               err = -ENOMEM;
+       if (IS_ERR(afa_block)) {
+               err = PTR_ERR(afa_block);
                goto err_afa_block;
        }
        err = mlxsw_afa_block_continue(afa_block);
index 67ee880a87279e8be04ed492133c403c93e5d416..01cff711bbd2e69ee401fe91736989f0f5823d8a 100644 (file)
@@ -464,7 +464,7 @@ mlxsw_sp_acl_rulei_create(struct mlxsw_sp_acl *acl,
 
        rulei = kzalloc(sizeof(*rulei), GFP_KERNEL);
        if (!rulei)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        if (afa_block) {
                rulei->act_block = afa_block;
index 430da69003d838f7978384c71d3205d40c4276ee..a6e30e020b5cf3de0b0915821130e50dbb11e0e5 100644 (file)
@@ -986,8 +986,9 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp,
                                unsigned int priority,
                                struct mlxsw_afk_element_usage *elusage)
 {
+       struct mlxsw_sp_acl_tcam_vchunk *vchunk, *vchunk2;
        struct mlxsw_sp_acl_tcam_vregion *vregion;
-       struct mlxsw_sp_acl_tcam_vchunk *vchunk;
+       struct list_head *pos;
        int err;
 
        if (priority == MLXSW_SP_ACL_TCAM_CATCHALL_PRIO)
@@ -1025,7 +1026,14 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp,
        }
 
        mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(vregion);
-       list_add_tail(&vchunk->list, &vregion->vchunk_list);
+
+       /* Position the vchunk inside the list according to priority */
+       list_for_each(pos, &vregion->vchunk_list) {
+               vchunk2 = list_entry(pos, typeof(*vchunk2), list);
+               if (vchunk2->priority > priority)
+                       break;
+       }
+       list_add_tail(&vchunk->list, pos);
        mutex_unlock(&vregion->lock);
 
        return vchunk;
index 51117a5a6bbf2764221c8707d854322e1327748a..890b078851c9f054b8e5ba11fbb18f0e92e920bb 100644 (file)
@@ -36,7 +36,8 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
                err = mlxsw_sp_acl_rulei_act_count(mlxsw_sp, rulei, extack);
                if (err)
                        return err;
-       } else if (act->hw_stats != FLOW_ACTION_HW_STATS_DISABLED) {
+       } else if (act->hw_stats != FLOW_ACTION_HW_STATS_DISABLED &&
+                  act->hw_stats != FLOW_ACTION_HW_STATS_DONT_CARE) {
                NL_SET_ERR_MSG_MOD(extack, "Unsupported action HW stats type");
                return -EOPNOTSUPP;
        }
index 346f4a5fe053bc186008ebbf789f5d8f0919e1fa..221aa6a474eb104ce5be1591e91d134dc4aeb68b 100644 (file)
@@ -199,8 +199,8 @@ mlxsw_sp_mr_tcam_afa_block_create(struct mlxsw_sp *mlxsw_sp,
        int err;
 
        afa_block = mlxsw_afa_block_create(mlxsw_sp->afa);
-       if (!afa_block)
-               return ERR_PTR(-ENOMEM);
+       if (IS_ERR(afa_block))
+               return afa_block;
 
        err = mlxsw_afa_block_append_allocated_counter(afa_block,
                                                       counter_index);
index e1651756bf9da181a089caccc7011c33fd9f4267..f70bb81e1ed652c44242ecd39e7bcf700dcfdb30 100644 (file)
@@ -564,7 +564,7 @@ static int moxart_remove(struct platform_device *pdev)
        struct net_device *ndev = platform_get_drvdata(pdev);
 
        unregister_netdev(ndev);
-       free_irq(ndev->irq, ndev);
+       devm_free_irq(&pdev->dev, ndev->irq, ndev);
        moxart_mac_free_memory(ndev);
        free_netdev(ndev);
 
index b4731df186f497a3b7a58e53ec6e0b7cd81e3761..02350c3d9d011a155c584b6e891d745f5f8aa7b5 100644 (file)
@@ -183,44 +183,47 @@ static void ocelot_vlan_mode(struct ocelot *ocelot, int port,
        ocelot_write(ocelot, val, ANA_VLANMASK);
 }
 
-void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
-                               bool vlan_aware)
+static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port,
+                                      u16 vid)
 {
        struct ocelot_port *ocelot_port = ocelot->ports[port];
-       u32 val;
+       u32 val = 0;
 
-       if (vlan_aware)
-               val = ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
-                     ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1);
-       else
-               val = 0;
-       ocelot_rmw_gix(ocelot, val,
-                      ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
-                      ANA_PORT_VLAN_CFG_VLAN_POP_CNT_M,
-                      ANA_PORT_VLAN_CFG, port);
+       if (ocelot_port->vid != vid) {
+               /* Always permit deleting the native VLAN (vid = 0) */
+               if (ocelot_port->vid && vid) {
+                       dev_err(ocelot->dev,
+                               "Port already has a native VLAN: %d\n",
+                               ocelot_port->vid);
+                       return -EBUSY;
+               }
+               ocelot_port->vid = vid;
+       }
 
-       if (vlan_aware && !ocelot_port->vid)
+       ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(vid),
+                      REW_PORT_VLAN_CFG_PORT_VID_M,
+                      REW_PORT_VLAN_CFG, port);
+
+       if (ocelot_port->vlan_aware && !ocelot_port->vid)
                /* If port is vlan-aware and tagged, drop untagged and priority
                 * tagged frames.
                 */
                val = ANA_PORT_DROP_CFG_DROP_UNTAGGED_ENA |
                      ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |
                      ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA;
-       else
-               val = 0;
        ocelot_rmw_gix(ocelot, val,
                       ANA_PORT_DROP_CFG_DROP_UNTAGGED_ENA |
                       ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |
                       ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA,
                       ANA_PORT_DROP_CFG, port);
 
-       if (vlan_aware) {
+       if (ocelot_port->vlan_aware) {
                if (ocelot_port->vid)
                        /* Tag all frames except when VID == DEFAULT_VLAN */
-                       val |= REW_TAG_CFG_TAG_CFG(1);
+                       val = REW_TAG_CFG_TAG_CFG(1);
                else
                        /* Tag all frames */
-                       val |= REW_TAG_CFG_TAG_CFG(3);
+                       val = REW_TAG_CFG_TAG_CFG(3);
        } else {
                /* Port tagging disabled. */
                val = REW_TAG_CFG_TAG_CFG(0);
@@ -228,31 +231,31 @@ void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
        ocelot_rmw_gix(ocelot, val,
                       REW_TAG_CFG_TAG_CFG_M,
                       REW_TAG_CFG, port);
+
+       return 0;
 }
-EXPORT_SYMBOL(ocelot_port_vlan_filtering);
 
-static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port,
-                                      u16 vid)
+void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
+                               bool vlan_aware)
 {
        struct ocelot_port *ocelot_port = ocelot->ports[port];
+       u32 val;
 
-       if (ocelot_port->vid != vid) {
-               /* Always permit deleting the native VLAN (vid = 0) */
-               if (ocelot_port->vid && vid) {
-                       dev_err(ocelot->dev,
-                               "Port already has a native VLAN: %d\n",
-                               ocelot_port->vid);
-                       return -EBUSY;
-               }
-               ocelot_port->vid = vid;
-       }
+       ocelot_port->vlan_aware = vlan_aware;
 
-       ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(vid),
-                      REW_PORT_VLAN_CFG_PORT_VID_M,
-                      REW_PORT_VLAN_CFG, port);
+       if (vlan_aware)
+               val = ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
+                     ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1);
+       else
+               val = 0;
+       ocelot_rmw_gix(ocelot, val,
+                      ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
+                      ANA_PORT_VLAN_CFG_VLAN_POP_CNT_M,
+                      ANA_PORT_VLAN_CFG, port);
 
-       return 0;
+       ocelot_port_set_native_vlan(ocelot, port, ocelot_port->vid);
 }
+EXPORT_SYMBOL(ocelot_port_vlan_filtering);
 
 /* Default vlan to clasify for untagged frames (may be zero) */
 static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, u16 pvid)
@@ -873,12 +876,12 @@ static void ocelot_get_stats64(struct net_device *dev,
 }
 
 int ocelot_fdb_add(struct ocelot *ocelot, int port,
-                  const unsigned char *addr, u16 vid, bool vlan_aware)
+                  const unsigned char *addr, u16 vid)
 {
        struct ocelot_port *ocelot_port = ocelot->ports[port];
 
        if (!vid) {
-               if (!vlan_aware)
+               if (!ocelot_port->vlan_aware)
                        /* If the bridge is not VLAN aware and no VID was
                         * provided, set it to pvid to ensure the MAC entry
                         * matches incoming untagged packets
@@ -905,7 +908,7 @@ static int ocelot_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
        struct ocelot *ocelot = priv->port.ocelot;
        int port = priv->chip_port;
 
-       return ocelot_fdb_add(ocelot, port, addr, vid, priv->vlan_aware);
+       return ocelot_fdb_add(ocelot, port, addr, vid);
 }
 
 int ocelot_fdb_del(struct ocelot *ocelot, int port,
@@ -1028,10 +1031,8 @@ int ocelot_fdb_dump(struct ocelot *ocelot, int port,
 {
        int i, j;
 
-       /* Loop through all the mac tables entries. There are 1024 rows of 4
-        * entries.
-        */
-       for (i = 0; i < 1024; i++) {
+       /* Loop through all the mac tables entries. */
+       for (i = 0; i < ocelot->num_mact_rows; i++) {
                for (j = 0; j < 4; j++) {
                        struct ocelot_mact_entry entry;
                        bool is_static;
@@ -1450,8 +1451,15 @@ static void ocelot_port_attr_stp_state_set(struct ocelot *ocelot, int port,
 
 void ocelot_set_ageing_time(struct ocelot *ocelot, unsigned int msecs)
 {
-       ocelot_write(ocelot, ANA_AUTOAGE_AGE_PERIOD(msecs / 2),
-                    ANA_AUTOAGE);
+       unsigned int age_period = ANA_AUTOAGE_AGE_PERIOD(msecs / 2000);
+
+       /* Setting AGE_PERIOD to zero effectively disables automatic aging,
+        * which is clearly not what our intention is. So avoid that.
+        */
+       if (!age_period)
+               age_period = 1;
+
+       ocelot_rmw(ocelot, age_period, ANA_AUTOAGE_AGE_PERIOD_M, ANA_AUTOAGE);
 }
 EXPORT_SYMBOL(ocelot_set_ageing_time);
 
@@ -1496,8 +1504,8 @@ static int ocelot_port_attr_set(struct net_device *dev,
                ocelot_port_attr_ageing_set(ocelot, port, attr->u.ageing_time);
                break;
        case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
-               priv->vlan_aware = attr->u.vlan_filtering;
-               ocelot_port_vlan_filtering(ocelot, port, priv->vlan_aware);
+               ocelot_port_vlan_filtering(ocelot, port,
+                                          attr->u.vlan_filtering);
                break;
        case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED:
                ocelot_port_attr_mc_set(ocelot, port, !attr->u.mc_disabled);
@@ -1868,7 +1876,6 @@ static int ocelot_netdevice_port_event(struct net_device *dev,
                        } else {
                                err = ocelot_port_bridge_leave(ocelot, port,
                                                               info->upper_dev);
-                               priv->vlan_aware = false;
                        }
                }
                if (netif_is_lag_master(info->upper_dev)) {
index e34ef8380eb326b8315a5203d6932fa046cd9e47..641af929497fd24a3d2941b5d423a85a4fd61169 100644 (file)
@@ -56,8 +56,6 @@ struct ocelot_port_private {
        struct phy_device *phy;
        u8 chip_port;
 
-       u8 vlan_aware;
-
        struct phy *serdes;
 
        struct ocelot_port_tc tc;
index b88b5899b22736fdc44f4dc7da04453282012d95..7d4fd1b6addaf2aba2e662614d275a1e38580c9f 100644 (file)
@@ -431,6 +431,7 @@ int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops)
        ocelot->stats_layout = ocelot_stats_layout;
        ocelot->num_stats = ARRAY_SIZE(ocelot_stats_layout);
        ocelot->shared_queue_sz = 224 * 1024;
+       ocelot->num_mact_rows = 1024;
        ocelot->ops = ops;
 
        ret = ocelot_regfields_init(ocelot, ocelot_regfields);
index bfa0c0d39600750b19e72c1915680737e38d744a..8b018ed37b1ba4c7a412431ce55fe0a0cf865e45 100644 (file)
@@ -208,11 +208,13 @@ static int jazz_sonic_probe(struct platform_device *pdev)
 
        err = register_netdev(dev);
        if (err)
-               goto out1;
+               goto undo_probe1;
 
        return 0;
 
-out1:
+undo_probe1:
+       dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+                         lp->descriptors, lp->descriptors_laddr);
        release_mem_region(dev->base_addr, SONIC_MEM_SIZE);
 out:
        free_netdev(dev);
index 0ec6b8e8b5494bb51e10a0a64e26476209c30fee..67e62603fe3bfbd498573f3530039d7fad0dc20c 100644 (file)
@@ -5155,7 +5155,7 @@ static int do_s2io_delete_unicast_mc(struct s2io_nic *sp, u64 addr)
 /* read mac entries from CAM */
 static u64 do_s2io_read_unicast_mc(struct s2io_nic *sp, int offset)
 {
-       u64 tmp64 = 0xffffffffffff0000ULL, val64;
+       u64 tmp64, val64;
        struct XENA_dev_config __iomem *bar0 = sp->bar0;
 
        /* read mac addr */
index 9183b3e85d217dec1328065f4594ce5e5895491d..354efffac0f9882f28c4fae9f87a9b9fc5094a0e 100644 (file)
@@ -283,6 +283,7 @@ nfp_abm_vnic_set_mac(struct nfp_pf *pf, struct nfp_abm *abm, struct nfp_net *nn,
        if (!nfp_nsp_has_hwinfo_lookup(nsp)) {
                nfp_warn(pf->cpp, "NSP doesn't support PF MAC generation\n");
                eth_hw_addr_random(nn->dp.netdev);
+               nfp_nsp_close(nsp);
                return;
        }
 
index 5f8fc58d42b3d31cd0c4e5318e8012e0e343f959..11621ccc1faf0837fdd9945e970309ce10f6d72b 100644 (file)
@@ -170,8 +170,7 @@ void ionic_debugfs_add_qcq(struct ionic_lif *lif, struct ionic_qcq *qcq)
        debugfs_create_x64("base_pa", 0400, cq_dentry, &cq->base_pa);
        debugfs_create_u32("num_descs", 0400, cq_dentry, &cq->num_descs);
        debugfs_create_u32("desc_size", 0400, cq_dentry, &cq->desc_size);
-       debugfs_create_u8("done_color", 0400, cq_dentry,
-                         (u8 *)&cq->done_color);
+       debugfs_create_bool("done_color", 0400, cq_dentry, &cq->done_color);
 
        debugfs_create_file("tail", 0400, cq_dentry, cq, &cq_tail_fops);
 
index 4b8a76098ca399d601150f8226aacc25b2de3096..d5293bfded292e1227f7a79d101d983437f9c0b9 100644 (file)
@@ -2101,6 +2101,7 @@ static void ionic_lif_handle_fw_down(struct ionic_lif *lif)
                ionic_txrx_free(lif);
        }
        ionic_lifs_deinit(ionic);
+       ionic_reset(ionic);
        ionic_qcqs_free(lif);
 
        dev_info(ionic->dev, "FW Down: LIFs stopped\n");
@@ -2116,6 +2117,7 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
 
        dev_info(ionic->dev, "FW Up: restarting LIFs\n");
 
+       ionic_init_devinfo(ionic);
        err = ionic_qcqs_alloc(lif);
        if (err)
                goto err_out;
@@ -2127,6 +2129,8 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
        if (lif->registered)
                ionic_lif_set_netdev_info(lif);
 
+       ionic_rx_filter_replay(lif);
+
        if (netif_running(lif->netdev)) {
                err = ionic_txrx_alloc(lif);
                if (err)
@@ -2206,9 +2210,9 @@ static void ionic_lif_deinit(struct ionic_lif *lif)
        if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state)) {
                cancel_work_sync(&lif->deferred.work);
                cancel_work_sync(&lif->tx_timeout_work);
+               ionic_rx_filters_deinit(lif);
        }
 
-       ionic_rx_filters_deinit(lif);
        if (lif->netdev->features & NETIF_F_RXHASH)
                ionic_lif_rss_deinit(lif);
 
@@ -2339,24 +2343,30 @@ static int ionic_station_set(struct ionic_lif *lif)
        err = ionic_adminq_post_wait(lif, &ctx);
        if (err)
                return err;
-
+       netdev_dbg(lif->netdev, "found initial MAC addr %pM\n",
+                  ctx.comp.lif_getattr.mac);
        if (is_zero_ether_addr(ctx.comp.lif_getattr.mac))
                return 0;
 
-       memcpy(addr.sa_data, ctx.comp.lif_getattr.mac, netdev->addr_len);
-       addr.sa_family = AF_INET;
-       err = eth_prepare_mac_addr_change(netdev, &addr);
-       if (err) {
-               netdev_warn(lif->netdev, "ignoring bad MAC addr from NIC %pM - err %d\n",
-                           addr.sa_data, err);
-               return 0;
-       }
+       if (!ether_addr_equal(ctx.comp.lif_getattr.mac, netdev->dev_addr)) {
+               memcpy(addr.sa_data, ctx.comp.lif_getattr.mac, netdev->addr_len);
+               addr.sa_family = AF_INET;
+               err = eth_prepare_mac_addr_change(netdev, &addr);
+               if (err) {
+                       netdev_warn(lif->netdev, "ignoring bad MAC addr from NIC %pM - err %d\n",
+                                   addr.sa_data, err);
+                       return 0;
+               }
 
-       netdev_dbg(lif->netdev, "deleting station MAC addr %pM\n",
-                  netdev->dev_addr);
-       ionic_lif_addr(lif, netdev->dev_addr, false);
+               if (!is_zero_ether_addr(netdev->dev_addr)) {
+                       netdev_dbg(lif->netdev, "deleting station MAC addr %pM\n",
+                                  netdev->dev_addr);
+                       ionic_lif_addr(lif, netdev->dev_addr, false);
+               }
+
+               eth_commit_mac_addr_change(netdev, &addr);
+       }
 
-       eth_commit_mac_addr_change(netdev, &addr);
        netdev_dbg(lif->netdev, "adding station MAC addr %pM\n",
                   netdev->dev_addr);
        ionic_lif_addr(lif, netdev->dev_addr, true);
@@ -2421,9 +2431,11 @@ static int ionic_lif_init(struct ionic_lif *lif)
        if (err)
                goto err_out_notifyq_deinit;
 
-       err = ionic_rx_filters_init(lif);
-       if (err)
-               goto err_out_notifyq_deinit;
+       if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state)) {
+               err = ionic_rx_filters_init(lif);
+               if (err)
+                       goto err_out_notifyq_deinit;
+       }
 
        err = ionic_station_set(lif);
        if (err)
@@ -2539,8 +2551,6 @@ int ionic_lifs_register(struct ionic *ionic)
                dev_err(ionic->dev, "Cannot register net device, aborting\n");
                return err;
        }
-
-       ionic_link_status_check_request(ionic->master_lif);
        ionic->master_lif->registered = true;
 
        return 0;
index 7a093f148ee58a5296ed50f9657f7e8f127c89cf..80eeb7696e0144768994509c26c1ed8e55e4e9c4 100644 (file)
@@ -2,6 +2,7 @@
 /* Copyright(c) 2017 - 2019 Pensando Systems, Inc */
 
 #include <linux/netdevice.h>
+#include <linux/dynamic_debug.h>
 #include <linux/etherdevice.h>
 
 #include "ionic.h"
@@ -17,17 +18,49 @@ void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *f)
        devm_kfree(dev, f);
 }
 
-int ionic_rx_filter_del(struct ionic_lif *lif, struct ionic_rx_filter *f)
+void ionic_rx_filter_replay(struct ionic_lif *lif)
 {
-       struct ionic_admin_ctx ctx = {
-               .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
-               .cmd.rx_filter_del = {
-                       .opcode = IONIC_CMD_RX_FILTER_DEL,
-                       .filter_id = cpu_to_le32(f->filter_id),
-               },
-       };
-
-       return ionic_adminq_post_wait(lif, &ctx);
+       struct ionic_rx_filter_add_cmd *ac;
+       struct ionic_admin_ctx ctx;
+       struct ionic_rx_filter *f;
+       struct hlist_head *head;
+       struct hlist_node *tmp;
+       unsigned int i;
+       int err;
+
+       ac = &ctx.cmd.rx_filter_add;
+
+       for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
+               head = &lif->rx_filters.by_id[i];
+               hlist_for_each_entry_safe(f, tmp, head, by_id) {
+                       ctx.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work);
+                       memcpy(ac, &f->cmd, sizeof(f->cmd));
+                       dev_dbg(&lif->netdev->dev, "replay filter command:\n");
+                       dynamic_hex_dump("cmd ", DUMP_PREFIX_OFFSET, 16, 1,
+                                        &ctx.cmd, sizeof(ctx.cmd), true);
+
+                       err = ionic_adminq_post_wait(lif, &ctx);
+                       if (err) {
+                               switch (le16_to_cpu(ac->match)) {
+                               case IONIC_RX_FILTER_MATCH_VLAN:
+                                       netdev_info(lif->netdev, "Replay failed - %d: vlan %d\n",
+                                                   err,
+                                                   le16_to_cpu(ac->vlan.vlan));
+                                       break;
+                               case IONIC_RX_FILTER_MATCH_MAC:
+                                       netdev_info(lif->netdev, "Replay failed - %d: mac %pM\n",
+                                                   err, ac->mac.addr);
+                                       break;
+                               case IONIC_RX_FILTER_MATCH_MAC_VLAN:
+                                       netdev_info(lif->netdev, "Replay failed - %d: vlan %d mac %pM\n",
+                                                   err,
+                                                   le16_to_cpu(ac->vlan.vlan),
+                                                   ac->mac.addr);
+                                       break;
+                               }
+                       }
+               }
+       }
 }
 
 int ionic_rx_filters_init(struct ionic_lif *lif)
index b6aec9c1991814e5dfb2758504dd3c26a1813f68..cf8f4c0a961c763201d7f99c13aa35352195b383 100644 (file)
@@ -24,7 +24,7 @@ struct ionic_rx_filters {
 };
 
 void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *f);
-int ionic_rx_filter_del(struct ionic_lif *lif, struct ionic_rx_filter *f);
+void ionic_rx_filter_replay(struct ionic_lif *lif);
 int ionic_rx_filters_init(struct ionic_lif *lif);
 void ionic_rx_filters_deinit(struct ionic_lif *lif);
 int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,
index 5b145c6bad60661877ecd1bc34780b291abb183a..2ba15c263e8b34a1014bc760bf1bb7159eceb6a2 100644 (file)
@@ -1,19 +1,3 @@
-
-/*
- * snull.h -- definitions for the network module
- *
- * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
- * Copyright (C) 2001 O'Reilly & Associates
- *
- * The source code in this file can be freely used, adapted,
- * and redistributed in source or binary form, so long as an
- * acknowledgment appears in derived source files.  The citation
- * should list that the code comes from the book "Linux Device
- * Drivers" by Alessandro Rubini and Jonathan Corbet, published
- * by O'Reilly & Associates.   No warranty is attached;
- * we cannot take responsibility for errors or fitness for use.
- */
-
 /* version dependencies have been confined to a separate file */
 
 /* Tunable parameters */
index 5419d4e478c0ed13d05c4c4ca7cfca3a36c5bfe4..2e4aaedb93f58098fa1e68fe364464d1e3eae325 100644 (file)
@@ -5,8 +5,13 @@
 #include <linux/clk-provider.h>
 #include <linux/pci.h>
 #include <linux/dmi.h>
+#include "dwmac-intel.h"
 #include "stmmac.h"
 
+struct intel_priv_data {
+       int mdio_adhoc_addr;    /* mdio address for serdes & etc */
+};
+
 /* This struct is used to associate PCI Function of MAC controller on a board,
  * discovered via DMI, with the address of PHY connected to the MAC. The
  * negative value of the address means that MAC controller is not connected
@@ -49,6 +54,172 @@ static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
        return -ENODEV;
 }
 
+static int serdes_status_poll(struct stmmac_priv *priv, int phyaddr,
+                             int phyreg, u32 mask, u32 val)
+{
+       unsigned int retries = 10;
+       int val_rd;
+
+       do {
+               val_rd = mdiobus_read(priv->mii, phyaddr, phyreg);
+               if ((val_rd & mask) == (val & mask))
+                       return 0;
+               udelay(POLL_DELAY_US);
+       } while (--retries);
+
+       return -ETIMEDOUT;
+}
+
+static int intel_serdes_powerup(struct net_device *ndev, void *priv_data)
+{
+       struct intel_priv_data *intel_priv = priv_data;
+       struct stmmac_priv *priv = netdev_priv(ndev);
+       int serdes_phy_addr = 0;
+       u32 data = 0;
+
+       if (!intel_priv->mdio_adhoc_addr)
+               return 0;
+
+       serdes_phy_addr = intel_priv->mdio_adhoc_addr;
+
+       /* assert clk_req */
+       data = mdiobus_read(priv->mii, serdes_phy_addr,
+                           SERDES_GCR0);
+
+       data |= SERDES_PLL_CLK;
+
+       mdiobus_write(priv->mii, serdes_phy_addr,
+                     SERDES_GCR0, data);
+
+       /* check for clk_ack assertion */
+       data = serdes_status_poll(priv, serdes_phy_addr,
+                                 SERDES_GSR0,
+                                 SERDES_PLL_CLK,
+                                 SERDES_PLL_CLK);
+
+       if (data) {
+               dev_err(priv->device, "Serdes PLL clk request timeout\n");
+               return data;
+       }
+
+       /* assert lane reset */
+       data = mdiobus_read(priv->mii, serdes_phy_addr,
+                           SERDES_GCR0);
+
+       data |= SERDES_RST;
+
+       mdiobus_write(priv->mii, serdes_phy_addr,
+                     SERDES_GCR0, data);
+
+       /* check for assert lane reset reflection */
+       data = serdes_status_poll(priv, serdes_phy_addr,
+                                 SERDES_GSR0,
+                                 SERDES_RST,
+                                 SERDES_RST);
+
+       if (data) {
+               dev_err(priv->device, "Serdes assert lane reset timeout\n");
+               return data;
+       }
+
+       /*  move power state to P0 */
+       data = mdiobus_read(priv->mii, serdes_phy_addr,
+                           SERDES_GCR0);
+
+       data &= ~SERDES_PWR_ST_MASK;
+       data |= SERDES_PWR_ST_P0 << SERDES_PWR_ST_SHIFT;
+
+       mdiobus_write(priv->mii, serdes_phy_addr,
+                     SERDES_GCR0, data);
+
+       /* Check for P0 state */
+       data = serdes_status_poll(priv, serdes_phy_addr,
+                                 SERDES_GSR0,
+                                 SERDES_PWR_ST_MASK,
+                                 SERDES_PWR_ST_P0 << SERDES_PWR_ST_SHIFT);
+
+       if (data) {
+               dev_err(priv->device, "Serdes power state P0 timeout.\n");
+               return data;
+       }
+
+       return 0;
+}
+
+static void intel_serdes_powerdown(struct net_device *ndev, void *intel_data)
+{
+       struct intel_priv_data *intel_priv = intel_data;
+       struct stmmac_priv *priv = netdev_priv(ndev);
+       int serdes_phy_addr = 0;
+       u32 data = 0;
+
+       if (!intel_priv->mdio_adhoc_addr)
+               return;
+
+       serdes_phy_addr = intel_priv->mdio_adhoc_addr;
+
+       /*  move power state to P3 */
+       data = mdiobus_read(priv->mii, serdes_phy_addr,
+                           SERDES_GCR0);
+
+       data &= ~SERDES_PWR_ST_MASK;
+       data |= SERDES_PWR_ST_P3 << SERDES_PWR_ST_SHIFT;
+
+       mdiobus_write(priv->mii, serdes_phy_addr,
+                     SERDES_GCR0, data);
+
+       /* Check for P3 state */
+       data = serdes_status_poll(priv, serdes_phy_addr,
+                                 SERDES_GSR0,
+                                 SERDES_PWR_ST_MASK,
+                                 SERDES_PWR_ST_P3 << SERDES_PWR_ST_SHIFT);
+
+       if (data) {
+               dev_err(priv->device, "Serdes power state P3 timeout\n");
+               return;
+       }
+
+       /* de-assert clk_req */
+       data = mdiobus_read(priv->mii, serdes_phy_addr,
+                           SERDES_GCR0);
+
+       data &= ~SERDES_PLL_CLK;
+
+       mdiobus_write(priv->mii, serdes_phy_addr,
+                     SERDES_GCR0, data);
+
+       /* check for clk_ack de-assert */
+       data = serdes_status_poll(priv, serdes_phy_addr,
+                                 SERDES_GSR0,
+                                 SERDES_PLL_CLK,
+                                 (u32)~SERDES_PLL_CLK);
+
+       if (data) {
+               dev_err(priv->device, "Serdes PLL clk de-assert timeout\n");
+               return;
+       }
+
+       /* de-assert lane reset */
+       data = mdiobus_read(priv->mii, serdes_phy_addr,
+                           SERDES_GCR0);
+
+       data &= ~SERDES_RST;
+
+       mdiobus_write(priv->mii, serdes_phy_addr,
+                     SERDES_GCR0, data);
+
+       /* check for de-assert lane reset reflection */
+       data = serdes_status_poll(priv, serdes_phy_addr,
+                                 SERDES_GSR0,
+                                 SERDES_RST,
+                                 (u32)~SERDES_RST);
+
+       if (data) {
+               dev_err(priv->device, "Serdes de-assert lane reset timeout\n");
+               return;
+       }
+}
+
 static void common_default_data(struct plat_stmmacenet_data *plat)
 {
        plat->clk_csr = 2;      /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
@@ -189,6 +360,9 @@ static int ehl_sgmii_data(struct pci_dev *pdev,
        plat->phy_addr = 0;
        plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
 
+       plat->serdes_powerup = intel_serdes_powerup;
+       plat->serdes_powerdown = intel_serdes_powerdown;
+
        return ehl_common_data(pdev, plat);
 }
 
@@ -233,6 +407,8 @@ static int ehl_pse0_sgmii1g_data(struct pci_dev *pdev,
                                 struct plat_stmmacenet_data *plat)
 {
        plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+       plat->serdes_powerup = intel_serdes_powerup;
+       plat->serdes_powerdown = intel_serdes_powerdown;
        return ehl_pse0_common_data(pdev, plat);
 }
 
@@ -263,6 +439,8 @@ static int ehl_pse1_sgmii1g_data(struct pci_dev *pdev,
                                 struct plat_stmmacenet_data *plat)
 {
        plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+       plat->serdes_powerup = intel_serdes_powerup;
+       plat->serdes_powerdown = intel_serdes_powerdown;
        return ehl_pse1_common_data(pdev, plat);
 }
 
@@ -291,6 +469,8 @@ static int tgl_sgmii_data(struct pci_dev *pdev,
        plat->bus_id = 1;
        plat->phy_addr = 0;
        plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+       plat->serdes_powerup = intel_serdes_powerup;
+       plat->serdes_powerdown = intel_serdes_powerdown;
        return tgl_common_data(pdev, plat);
 }
 
@@ -417,11 +597,17 @@ static int intel_eth_pci_probe(struct pci_dev *pdev,
                               const struct pci_device_id *id)
 {
        struct stmmac_pci_info *info = (struct stmmac_pci_info *)id->driver_data;
+       struct intel_priv_data *intel_priv;
        struct plat_stmmacenet_data *plat;
        struct stmmac_resources res;
        int i;
        int ret;
 
+       intel_priv = devm_kzalloc(&pdev->dev, sizeof(*intel_priv),
+                                 GFP_KERNEL);
+       if (!intel_priv)
+               return -ENOMEM;
+
        plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
        if (!plat)
                return -ENOMEM;
@@ -457,6 +643,9 @@ static int intel_eth_pci_probe(struct pci_dev *pdev,
 
        pci_set_master(pdev);
 
+       plat->bsp_priv = intel_priv;
+       intel_priv->mdio_adhoc_addr = 0x15;
+
        ret = info->setup(pdev, plat);
        if (ret)
                return ret;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.h b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.h
new file mode 100644 (file)
index 0000000..e723096
--- /dev/null
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2020, Intel Corporation
+ * DWMAC Intel header file
+ */
+
+#ifndef __DWMAC_INTEL_H__
+#define __DWMAC_INTEL_H__
+
+#define POLL_DELAY_US 8
+
+/* SERDES Register */
+#define SERDES_GSR0    0x5     /* Global Status Reg0 */
+#define SERDES_GCR0    0xb     /* Global Configuration Reg0 */
+
+/* SERDES defines */
+#define SERDES_PLL_CLK         BIT(0)          /* PLL clk valid signal */
+#define SERDES_RST             BIT(2)          /* Serdes Reset */
+#define SERDES_PWR_ST_MASK     GENMASK(6, 4)   /* Serdes Power state*/
+#define SERDES_PWR_ST_SHIFT    4
+#define SERDES_PWR_ST_P0       0x0
+#define SERDES_PWR_ST_P3       0x3
+
+#endif /* __DWMAC_INTEL_H__ */
index 0e2fa14f142377b0c47751d2eb99fa11cb4e445d..a3934ca6a043bb652e527ea03152653896929e2a 100644 (file)
@@ -119,6 +119,7 @@ static int meson8b_init_rgmii_tx_clk(struct meson8b_dwmac *dwmac)
                { .div = 5, .val = 5, },
                { .div = 6, .val = 6, },
                { .div = 7, .val = 7, },
+               { /* end of array */ }
        };
 
        clk_configs = devm_kzalloc(dev, sizeof(*clk_configs), GFP_KERNEL);
index e0212d2fc2a12c745d562b333b81688fe7227ecd..70d41783329dd4e9b8b25fcc2487c244ad44cc7a 100644 (file)
@@ -241,6 +241,8 @@ static int socfpga_set_phy_mode_common(int phymode, u32 *val)
        switch (phymode) {
        case PHY_INTERFACE_MODE_RGMII:
        case PHY_INTERFACE_MODE_RGMII_ID:
+       case PHY_INTERFACE_MODE_RGMII_RXID:
+       case PHY_INTERFACE_MODE_RGMII_TXID:
                *val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII;
                break;
        case PHY_INTERFACE_MODE_MII:
@@ -289,16 +291,19 @@ static int socfpga_gen5_set_phy_mode(struct socfpga_dwmac *dwmac)
            phymode == PHY_INTERFACE_MODE_MII ||
            phymode == PHY_INTERFACE_MODE_GMII ||
            phymode == PHY_INTERFACE_MODE_SGMII) {
-               ctrl |= SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2);
                regmap_read(sys_mgr_base_addr, SYSMGR_FPGAGRP_MODULE_REG,
                            &module);
                module |= (SYSMGR_FPGAGRP_MODULE_EMAC << (reg_shift / 2));
                regmap_write(sys_mgr_base_addr, SYSMGR_FPGAGRP_MODULE_REG,
                             module);
-       } else {
-               ctrl &= ~(SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2));
        }
 
+       if (dwmac->f2h_ptp_ref_clk)
+               ctrl |= SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2);
+       else
+               ctrl &= ~(SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK <<
+                         (reg_shift / 2));
+
        regmap_write(sys_mgr_base_addr, reg_offset, ctrl);
 
        /* Deassert reset for the phy configuration to be sampled by
index 7d40760e9ba887693e5b6b2a925eee73bd7ad92d..0e1ca2cba3c7c5220d8c24b62e835f64e5bdc2a2 100644 (file)
@@ -150,6 +150,8 @@ static int sun7i_gmac_probe(struct platform_device *pdev)
        plat_dat->init = sun7i_gmac_init;
        plat_dat->exit = sun7i_gmac_exit;
        plat_dat->fix_mac_speed = sun7i_fix_speed;
+       plat_dat->tx_fifo_size = 4096;
+       plat_dat->rx_fifo_size = 16384;
 
        ret = sun7i_gmac_init(pdev, plat_dat->bsp_priv);
        if (ret)
index 494c859b4ade8ab39a2939a3b21dd210e633dcfe..67ba67ed0cb99f9a1df76529a47fba1dee73f386 100644 (file)
@@ -624,7 +624,7 @@ int dwmac5_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg,
                total_offset += offset;
        }
 
-       total_ctr = cfg->ctr[0] + cfg->ctr[1] * 1000000000;
+       total_ctr = cfg->ctr[0] + cfg->ctr[1] * 1000000000ULL;
        total_ctr += total_offset;
 
        ctr_low = do_div(total_ctr, 1000000000);
index fcf080243a0fef578299e337b919eb39ebcee2a6..d291612eeafb96b753da3a6e6b42fc2b16bc0d1e 100644 (file)
@@ -27,12 +27,16 @@ static void config_sub_second_increment(void __iomem *ioaddr,
        unsigned long data;
        u32 reg_value;
 
-       /* For GMAC3.x, 4.x versions, convert the ptp_clock to nano second
-        *      formula = (1/ptp_clock) * 1000000000
-        * where ptp_clock is 50MHz if fine method is used to update system
+       /* For GMAC3.x, 4.x versions, in "fine adjustement mode" set sub-second
+        * increment to twice the number of nanoseconds of a clock cycle.
+        * The calculation of the default_addend value by the caller will set it
+        * to mid-range = 2^31 when the remainder of this division is zero,
+        * which will make the accumulator overflow once every 2 ptp_clock
+        * cycles, adding twice the number of nanoseconds of a clock cycle :
+        * 2000000000ULL / ptp_clock.
         */
        if (value & PTP_TCR_TSCFUPDT)
-               data = (1000000000ULL / 50000000);
+               data = (2000000000ULL / ptp_clock);
        else
                data = (1000000000ULL / ptp_clock);
 
index e6898fd5223f2987fe9611360c33ee63e6686497..a999d6b33a645ed565602b9d318284c229badfb1 100644 (file)
@@ -4060,7 +4060,7 @@ static int stmmac_set_features(struct net_device *netdev,
 /**
  *  stmmac_interrupt - main ISR
  *  @irq: interrupt number.
- *  @dev_id: to pass the net device pointer.
+ *  @dev_id: to pass the net device pointer (must be valid).
  *  Description: this is the main driver interrupt service routine.
  *  It can call:
  *  o DMA service routine (to manage incoming frame reception and transmission
@@ -4084,11 +4084,6 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
        if (priv->irq_wake)
                pm_wakeup_event(priv->device, 0);
 
-       if (unlikely(!dev)) {
-               netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__);
-               return IRQ_NONE;
-       }
-
        /* Check if adapter is up */
        if (test_bit(STMMAC_DOWN, &priv->state))
                return IRQ_HANDLED;
@@ -4986,12 +4981,22 @@ int stmmac_dvr_probe(struct device *device,
                goto error_netdev_register;
        }
 
+       if (priv->plat->serdes_powerup) {
+               ret = priv->plat->serdes_powerup(ndev,
+                                                priv->plat->bsp_priv);
+
+               if (ret < 0)
+                       goto error_serdes_powerup;
+       }
+
 #ifdef CONFIG_DEBUG_FS
        stmmac_init_fs(ndev);
 #endif
 
        return ret;
 
+error_serdes_powerup:
+       unregister_netdev(ndev);
 error_netdev_register:
        phylink_destroy(priv->phylink);
 error_phy_setup:
@@ -5029,6 +5034,9 @@ int stmmac_dvr_remove(struct device *dev)
 
        stmmac_stop_all_dma(priv);
 
+       if (priv->plat->serdes_powerdown)
+               priv->plat->serdes_powerdown(ndev, priv->plat->bsp_priv);
+
        stmmac_mac_set(priv, priv->ioaddr, false);
        netif_carrier_off(ndev);
        unregister_netdev(ndev);
@@ -5081,6 +5089,9 @@ int stmmac_suspend(struct device *dev)
        /* Stop TX/RX DMA */
        stmmac_stop_all_dma(priv);
 
+       if (priv->plat->serdes_powerdown)
+               priv->plat->serdes_powerdown(ndev, priv->plat->bsp_priv);
+
        /* Enable Power down mode by programming the PMT regs */
        if (device_may_wakeup(priv->device)) {
                stmmac_pmt(priv, priv->hw, priv->wolopts);
@@ -5143,6 +5154,7 @@ int stmmac_resume(struct device *dev)
 {
        struct net_device *ndev = dev_get_drvdata(dev);
        struct stmmac_priv *priv = netdev_priv(ndev);
+       int ret;
 
        if (!netif_running(ndev))
                return 0;
@@ -5170,6 +5182,14 @@ int stmmac_resume(struct device *dev)
                        stmmac_mdio_reset(priv->mii);
        }
 
+       if (priv->plat->serdes_powerup) {
+               ret = priv->plat->serdes_powerup(ndev,
+                                                priv->plat->bsp_priv);
+
+               if (ret < 0)
+                       return ret;
+       }
+
        netif_device_attach(ndev);
 
        mutex_lock(&priv->lock);
index 89cec778cf2d52176c63d9d474760422e1db180a..8e348780efb6fd3338ff3246caee2f683d47c04c 100644 (file)
@@ -90,9 +90,8 @@ config TI_CPTS
 config TI_CPTS_MOD
        tristate
        depends on TI_CPTS
+       depends on PTP_1588_CLOCK
        default y if TI_CPSW=y || TI_KEYSTONE_NETCP=y || TI_CPSW_SWITCHDEV=y
-       select NET_PTP_CLASSIFY
-       imply PTP_1588_CLOCK
        default m
 
 config TI_K3_AM65_CPSW_NUSS
index f71c15c394927efcaf3d0beb3de52c3ff91ee7c1..2517ffba81788e00a2c8732cd2138337b820a3d4 100644 (file)
@@ -1372,7 +1372,7 @@ static int am65_cpsw_nuss_init_tx_chns(struct am65_cpsw_common *common)
 err:
        i = devm_add_action(dev, am65_cpsw_nuss_free_tx_chns, common);
        if (i) {
-               dev_err(dev, "failed to add free_tx_chns action %d", i);
+               dev_err(dev, "Failed to add free_tx_chns action %d\n", i);
                return i;
        }
 
@@ -1481,7 +1481,7 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
 err:
        i = devm_add_action(dev, am65_cpsw_nuss_free_rx_chns, common);
        if (i) {
-               dev_err(dev, "failed to add free_rx_chns action %d", i);
+               dev_err(dev, "Failed to add free_rx_chns action %d\n", i);
                return i;
        }
 
@@ -1691,7 +1691,7 @@ static int am65_cpsw_nuss_init_ndev_2g(struct am65_cpsw_common *common)
        ret = devm_add_action_or_reset(dev, am65_cpsw_pcpu_stats_free,
                                       ndev_priv->stats);
        if (ret) {
-               dev_err(dev, "failed to add percpu stat free action %d", ret);
+               dev_err(dev, "Failed to add percpu stat free action %d\n", ret);
                return ret;
        }
 
@@ -1719,7 +1719,8 @@ static int am65_cpsw_nuss_ndev_add_napi_2g(struct am65_cpsw_common *common)
 
                ret = devm_request_irq(dev, tx_chn->irq,
                                       am65_cpsw_nuss_tx_irq,
-                                      0, tx_chn->tx_chn_name, tx_chn);
+                                      IRQF_TRIGGER_HIGH,
+                                      tx_chn->tx_chn_name, tx_chn);
                if (ret) {
                        dev_err(dev, "failure requesting tx%u irq %u, %d\n",
                                tx_chn->id, tx_chn->irq, ret);
@@ -1744,7 +1745,7 @@ static int am65_cpsw_nuss_ndev_reg_2g(struct am65_cpsw_common *common)
 
        ret = devm_request_irq(dev, common->rx_chns.irq,
                               am65_cpsw_nuss_rx_irq,
-                              0, dev_name(dev), common);
+                              IRQF_TRIGGER_HIGH, dev_name(dev), common);
        if (ret) {
                dev_err(dev, "failure requesting rx irq %u, %d\n",
                        common->rx_chns.irq, ret);
index b50c3ec3495bb152a73a2c8ab889b3305339b0f7..6bcda20ed7e72b5946fb7bc3a97eb1259e36a0cb 100644 (file)
@@ -643,7 +643,7 @@ static int tc_mii_probe(struct net_device *dev)
                linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, mask);
                linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, mask);
        }
-       linkmode_and(phydev->supported, phydev->supported, mask);
+       linkmode_andnot(phydev->supported, phydev->supported, mask);
        linkmode_copy(phydev->advertising, phydev->supported);
 
        lp->link = 0;
index 269596c15133d01008d699baf47ec6a8ecef8a5d..2e52029235104762b0ea4870433c2df7347addd9 100644 (file)
@@ -1387,6 +1387,8 @@ static int ixp4xx_eth_probe(struct platform_device *pdev)
                return -ENODEV;
        regs_phys = res->start;
        port->regs = devm_ioremap_resource(dev, res);
+       if (IS_ERR(port->regs))
+               return PTR_ERR(port->regs);
 
        switch (port->id) {
        case IXP4XX_ETH_NPEA:
index 09f279c0182be4c05144c5caca6548cacfebbd49..6b461be1820bb91899a406032f0dd4dcdb01857e 100644 (file)
@@ -1207,7 +1207,7 @@ static int geneve_validate(struct nlattr *tb[], struct nlattr *data[],
                enum ifla_geneve_df df = nla_get_u8(data[IFLA_GENEVE_DF]);
 
                if (df < 0 || df > GENEVE_DF_MAX) {
-                       NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_GENEVE_DF],
+                       NL_SET_ERR_MSG_ATTR(extack, data[IFLA_GENEVE_DF],
                                            "Invalid DF attribute");
                        return -EINVAL;
                }
index 672cd2caf2fbec6f1020f4dc30adfb8d96a8f917..21640a035d7df30de40da0b14a7e6abd309550ef 100644 (file)
@@ -1169,11 +1169,11 @@ out_unlock:
 static struct genl_family gtp_genl_family;
 
 static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq,
-                             u32 type, struct pdp_ctx *pctx)
+                             int flags, u32 type, struct pdp_ctx *pctx)
 {
        void *genlh;
 
-       genlh = genlmsg_put(skb, snd_portid, snd_seq, &gtp_genl_family, 0,
+       genlh = genlmsg_put(skb, snd_portid, snd_seq, &gtp_genl_family, flags,
                            type);
        if (genlh == NULL)
                goto nlmsg_failure;
@@ -1227,8 +1227,8 @@ static int gtp_genl_get_pdp(struct sk_buff *skb, struct genl_info *info)
                goto err_unlock;
        }
 
-       err = gtp_genl_fill_info(skb2, NETLINK_CB(skb).portid,
-                                info->snd_seq, info->nlhdr->nlmsg_type, pctx);
+       err = gtp_genl_fill_info(skb2, NETLINK_CB(skb).portid, info->snd_seq,
+                                0, info->nlhdr->nlmsg_type, pctx);
        if (err < 0)
                goto err_unlock_free;
 
@@ -1271,6 +1271,7 @@ static int gtp_genl_dump_pdp(struct sk_buff *skb,
                                    gtp_genl_fill_info(skb,
                                            NETLINK_CB(cb->skb).portid,
                                            cb->nlh->nlmsg_seq,
+                                           NLM_F_MULTI,
                                            cb->nlh->nlmsg_type, pctx)) {
                                        cb->args[0] = i;
                                        cb->args[1] = j;
index d8e86bdbfba1e68d861d7c5bf9b91dd947cc0a65..ebcfbae056900be8087fcbe03913d1a1e0dbb717 100644 (file)
@@ -707,7 +707,8 @@ no_memory:
        goto drop;
 }
 
-static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+static netdev_tx_t netvsc_start_xmit(struct sk_buff *skb,
+                                    struct net_device *ndev)
 {
        return netvsc_xmit(skb, ndev, false);
 }
index 845478a19a4f46b30fd448f8b852a5ae5bb2e8c2..b671bea0aa7c9549d752d4aaf2240e2259ce3060 100644 (file)
@@ -1041,6 +1041,7 @@ static void gsi_isr_gp_int1(struct gsi *gsi)
 
        complete(&gsi->completion);
 }
+
 /* Inter-EE interrupt handler */
 static void gsi_isr_glob_ee(struct gsi *gsi)
 {
@@ -1493,6 +1494,12 @@ static int gsi_generic_command(struct gsi *gsi, u32 channel_id,
        struct completion *completion = &gsi->completion;
        u32 val;
 
+       /* First zero the result code field */
+       val = ioread32(gsi->virt + GSI_CNTXT_SCRATCH_0_OFFSET);
+       val &= ~GENERIC_EE_RESULT_FMASK;
+       iowrite32(val, gsi->virt + GSI_CNTXT_SCRATCH_0_OFFSET);
+
+       /* Now issue the command */
        val = u32_encode_bits(opcode, GENERIC_OPCODE_FMASK);
        val |= u32_encode_bits(channel_id, GENERIC_CHID_FMASK);
        val |= u32_encode_bits(GSI_EE_MODEM, GENERIC_EE_FMASK);
@@ -1798,9 +1805,9 @@ static int gsi_channel_init_one(struct gsi *gsi,
 
        /* Worst case we need an event for every outstanding TRE */
        if (data->channel.tre_count > data->channel.event_count) {
-               dev_warn(gsi->dev, "channel %u limited to %u TREs\n",
-                       data->channel_id, data->channel.tre_count);
                tre_count = data->channel.event_count;
+               dev_warn(gsi->dev, "channel %u limited to %u TREs\n",
+                        data->channel_id, tre_count);
        } else {
                tre_count = data->channel.tre_count;
        }
index 7613b9cc7cf69f65acdcc04ee80e52a0d410f127..acc9e744c67d16ca0813bf435857f9b747eb7325 100644 (file)
 #define INTER_EE_RESULT_FMASK          GENMASK(2, 0)
 #define GENERIC_EE_RESULT_FMASK                GENMASK(7, 5)
 #define GENERIC_EE_SUCCESS_FVAL                        1
+#define GENERIC_EE_INCORRECT_DIRECTION_FVAL    3
+#define GENERIC_EE_INCORRECT_CHANNEL_FVAL      5
 #define GENERIC_EE_NO_RESOURCES_FVAL           7
 #define USB_MAX_PACKET_FMASK           GENMASK(15, 15) /* 0: HS; 1: SS */
 #define MHI_BASE_CHANNEL_FMASK         GENMASK(31, 24)
index 6de03be287848c0a2d7e4223bb76c4bd019a5dc6..a21534f1462fa5d81fb2f30ed969327d5881776e 100644 (file)
@@ -1283,7 +1283,7 @@ static int ipa_endpoint_stop_rx_dma(struct ipa *ipa)
  */
 int ipa_endpoint_stop(struct ipa_endpoint *endpoint)
 {
-       u32 retries = endpoint->toward_ipa ? 0 : IPA_ENDPOINT_STOP_RX_RETRIES;
+       u32 retries = IPA_ENDPOINT_STOP_RX_RETRIES;
        int ret;
 
        do {
@@ -1291,12 +1291,9 @@ int ipa_endpoint_stop(struct ipa_endpoint *endpoint)
                struct gsi *gsi = &ipa->gsi;
 
                ret = gsi_channel_stop(gsi, endpoint->channel_id);
-               if (ret != -EAGAIN)
+               if (ret != -EAGAIN || endpoint->toward_ipa)
                        break;
 
-               if (endpoint->toward_ipa)
-                       continue;
-
                /* For IPA v3.5.1, send a DMA read task and check again */
                if (ipa->version == IPA_VERSION_3_5_1) {
                        ret = ipa_endpoint_stop_rx_dma(ipa);
index 55c9329a4b1db62112bdbff6b3f841e567f4cfbc..ed10818dd99f2a6e5bcb56a662638fc39ce1305e 100644 (file)
@@ -297,14 +297,13 @@ static void ipa_modem_crashed(struct ipa *ipa)
 
        ret = ipa_endpoint_modem_exception_reset_all(ipa);
        if (ret)
-               dev_err(dev, "error %d resetting exception endpoint",
-                       ret);
+               dev_err(dev, "error %d resetting exception endpoint\n", ret);
 
        ipa_endpoint_modem_pause_all(ipa, false);
 
        ret = ipa_modem_stop(ipa);
        if (ret)
-               dev_err(dev, "error %d stopping modem", ret);
+               dev_err(dev, "error %d stopping modem\n", ret);
 
        /* Now prepare for the next modem boot */
        ret = ipa_mem_zero_modem(ipa);
index 0d580d81d910f0e8802684e163f89a286223a64a..d0d31cb991803daa2a18099605d35f1fbb406eb2 100644 (file)
@@ -1305,7 +1305,8 @@ static struct crypto_aead *macsec_alloc_tfm(char *key, int key_len, int icv_len)
        struct crypto_aead *tfm;
        int ret;
 
-       tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
+       /* Pick a sync gcm(aes) cipher to ensure order is preserved. */
+       tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
 
        if (IS_ERR(tfm))
                return tfm;
@@ -2640,11 +2641,12 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info)
        if (ret)
                goto rollback;
 
-       rtnl_unlock();
        /* Force features update, since they are different for SW MACSec and
         * HW offloading cases.
         */
        netdev_update_features(dev);
+
+       rtnl_unlock();
        return 0;
 
 rollback:
@@ -3809,7 +3811,7 @@ static int macsec_changelink(struct net_device *dev, struct nlattr *tb[],
                             struct netlink_ext_ack *extack)
 {
        struct macsec_dev *macsec = macsec_priv(dev);
-       struct macsec_tx_sa tx_sc;
+       struct macsec_tx_sc tx_sc;
        struct macsec_secy secy;
        int ret;
 
@@ -4002,11 +4004,11 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
                          struct netlink_ext_ack *extack)
 {
        struct macsec_dev *macsec = macsec_priv(dev);
+       rx_handler_func_t *rx_handler;
+       u8 icv_len = DEFAULT_ICV_LEN;
        struct net_device *real_dev;
-       int err;
+       int err, mtu;
        sci_t sci;
-       u8 icv_len = DEFAULT_ICV_LEN;
-       rx_handler_func_t *rx_handler;
 
        if (!tb[IFLA_LINK])
                return -EINVAL;
@@ -4033,7 +4035,11 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
 
        if (data && data[IFLA_MACSEC_ICV_LEN])
                icv_len = nla_get_u8(data[IFLA_MACSEC_ICV_LEN]);
-       dev->mtu = real_dev->mtu - icv_len - macsec_extra_len(true);
+       mtu = real_dev->mtu - icv_len - macsec_extra_len(true);
+       if (mtu < 0)
+               dev->mtu = 0;
+       else
+               dev->mtu = mtu;
 
        rx_handler = rtnl_dereference(real_dev->rx_handler);
        if (rx_handler && rx_handler != macsec_handle_frame)
index e7289d67268fc72caf8fe186a8065454270b2190..0482adc9916bffee47e6f73e7c2495271eee37b3 100644 (file)
@@ -1704,7 +1704,7 @@ static int macvlan_device_event(struct notifier_block *unused,
                                                struct macvlan_dev,
                                                list);
 
-               if (macvlan_sync_address(vlan->dev, dev->dev_addr))
+               if (vlan && macvlan_sync_address(vlan->dev, dev->dev_addr))
                        return NOTIFY_BAD;
 
                break;
index 3840d2adbbb9a4eea910c31224ba4c00f51f3b7b..9717a1626f3fa1c4a1daea0e96858afc13472d95 100644 (file)
@@ -155,9 +155,6 @@ static int bcm84881_read_status(struct phy_device *phydev)
        if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete)
                phydev->link = false;
 
-       if (!phydev->link)
-               return 0;
-
        linkmode_zero(phydev->lp_advertising);
        phydev->speed = SPEED_UNKNOWN;
        phydev->duplex = DUPLEX_UNKNOWN;
@@ -165,6 +162,9 @@ static int bcm84881_read_status(struct phy_device *phydev)
        phydev->asym_pause = 0;
        phydev->mdix = 0;
 
+       if (!phydev->link)
+               return 0;
+
        if (phydev->autoneg_complete) {
                val = genphy_c45_read_lpa(phydev);
                if (val < 0)
index 415c273109829959c28316a62b271ac3bfde83a3..ecbd5e0d685cf3cc3b3d46fbb2f1456c44ed0472 100644 (file)
@@ -1120,7 +1120,7 @@ static struct dp83640_clock *dp83640_clock_get_bus(struct mii_bus *bus)
                goto out;
        }
        dp83640_clock_init(clock, bus);
-       list_add_tail(&phyter_clocks, &clock->list);
+       list_add_tail(&clock->list, &phyter_clocks);
 out:
        mutex_unlock(&phyter_clocks_lock);
 
index fe9aa3ad52a71f8bbea3c26f1b08a1bb4a1e33c4..1dd19d0cb269f5a945b37e09cec3824f2f9e1eb1 100644 (file)
@@ -137,19 +137,18 @@ static int dp83822_set_wol(struct phy_device *phydev,
                        value &= ~DP83822_WOL_SECURE_ON;
                }
 
-               value |= (DP83822_WOL_EN | DP83822_WOL_INDICATION_SEL |
-                         DP83822_WOL_CLR_INDICATION);
-               phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG,
-                             value);
+               /* Clear any pending WoL interrupt */
+               phy_read(phydev, MII_DP83822_MISR2);
+
+               value |= DP83822_WOL_EN | DP83822_WOL_INDICATION_SEL |
+                        DP83822_WOL_CLR_INDICATION;
+
+               return phy_write_mmd(phydev, DP83822_DEVADDR,
+                                    MII_DP83822_WOL_CFG, value);
        } else {
-               value = phy_read_mmd(phydev, DP83822_DEVADDR,
-                                    MII_DP83822_WOL_CFG);
-               value &= ~DP83822_WOL_EN;
-               phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG,
-                             value);
+               return phy_clear_bits_mmd(phydev, DP83822_DEVADDR,
+                                         MII_DP83822_WOL_CFG, DP83822_WOL_EN);
        }
-
-       return 0;
 }
 
 static void dp83822_get_wol(struct phy_device *phydev,
@@ -258,12 +257,11 @@ static int dp83822_config_intr(struct phy_device *phydev)
 
 static int dp83822_config_init(struct phy_device *phydev)
 {
-       int value;
-
-       value = DP83822_WOL_MAGIC_EN | DP83822_WOL_SECURE_ON | DP83822_WOL_EN;
+       int value = DP83822_WOL_EN | DP83822_WOL_MAGIC_EN |
+                   DP83822_WOL_SECURE_ON;
 
-       return phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG,
-             value);
+       return phy_clear_bits_mmd(phydev, DP83822_DEVADDR,
+                                 MII_DP83822_WOL_CFG, value);
 }
 
 static int dp83822_phy_reset(struct phy_device *phydev)
index 06f08832ebcdea64413eb0fc49653d5ba82ab75c..d73725312c7c353e382417b341f5f241dbaf2dbf 100644 (file)
@@ -139,16 +139,19 @@ static int dp83811_set_wol(struct phy_device *phydev,
                        value &= ~DP83811_WOL_SECURE_ON;
                }
 
-               value |= (DP83811_WOL_EN | DP83811_WOL_INDICATION_SEL |
-                         DP83811_WOL_CLR_INDICATION);
-               phy_write_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG,
-                             value);
+               /* Clear any pending WoL interrupt */
+               phy_read(phydev, MII_DP83811_INT_STAT1);
+
+               value |= DP83811_WOL_EN | DP83811_WOL_INDICATION_SEL |
+                        DP83811_WOL_CLR_INDICATION;
+
+               return phy_write_mmd(phydev, DP83811_DEVADDR,
+                                    MII_DP83811_WOL_CFG, value);
        } else {
-               phy_clear_bits_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG,
-                                  DP83811_WOL_EN);
+               return phy_clear_bits_mmd(phydev, DP83811_DEVADDR,
+                                         MII_DP83811_WOL_CFG, DP83811_WOL_EN);
        }
 
-       return 0;
 }
 
 static void dp83811_get_wol(struct phy_device *phydev,
@@ -292,8 +295,8 @@ static int dp83811_config_init(struct phy_device *phydev)
 
        value = DP83811_WOL_MAGIC_EN | DP83811_WOL_SECURE_ON | DP83811_WOL_EN;
 
-       return phy_write_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG,
-             value);
+       return phy_clear_bits_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG,
+                                 value);
 }
 
 static int dp83811_phy_reset(struct phy_device *phydev)
index 4714ca0e0d4b215a958cbc534f5bc59e9744fd4f..7fc8e10c5f33729964f167b178bbf95618b2f43f 100644 (file)
@@ -1263,6 +1263,30 @@ static int marvell_read_status_page_an(struct phy_device *phydev,
        int lpa;
        int err;
 
+       if (!(status & MII_M1011_PHY_STATUS_RESOLVED)) {
+               phydev->link = 0;
+               return 0;
+       }
+
+       if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
+               phydev->duplex = DUPLEX_FULL;
+       else
+               phydev->duplex = DUPLEX_HALF;
+
+       switch (status & MII_M1011_PHY_STATUS_SPD_MASK) {
+       case MII_M1011_PHY_STATUS_1000:
+               phydev->speed = SPEED_1000;
+               break;
+
+       case MII_M1011_PHY_STATUS_100:
+               phydev->speed = SPEED_100;
+               break;
+
+       default:
+               phydev->speed = SPEED_10;
+               break;
+       }
+
        if (!fiber) {
                err = genphy_read_lpa(phydev);
                if (err < 0)
@@ -1291,28 +1315,6 @@ 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
-               phydev->duplex = DUPLEX_HALF;
-
-       switch (status & MII_M1011_PHY_STATUS_SPD_MASK) {
-       case MII_M1011_PHY_STATUS_1000:
-               phydev->speed = SPEED_1000;
-               break;
-
-       case MII_M1011_PHY_STATUS_100:
-               phydev->speed = SPEED_100;
-               break;
-
-       default:
-               phydev->speed = SPEED_10;
-               break;
-       }
-
        return 0;
 }
 
index 7621badae64d6d2599a76ef03f46cb817524d046..1f1a01c98e4406b6b959bd9fa6d4307342304b87 100644 (file)
@@ -33,6 +33,8 @@
 #define MV_PHY_ALASKA_NBT_QUIRK_REV    (MARVELL_PHY_ID_88X3310 | 0xa)
 
 enum {
+       MV_PMA_FW_VER0          = 0xc011,
+       MV_PMA_FW_VER1          = 0xc012,
        MV_PMA_BOOT             = 0xc050,
        MV_PMA_BOOT_FATAL       = BIT(0),
 
@@ -64,6 +66,9 @@ enum {
        MV_PCS_CSSR1_SPD2_2500  = 0x0004,
        MV_PCS_CSSR1_SPD2_10000 = 0x0000,
 
+       /* Temperature read register (88E2110 only) */
+       MV_PCS_TEMP             = 0x8042,
+
        /* These registers appear at 0x800X and 0xa00X - the 0xa00X control
         * registers appear to set themselves to the 0x800X when AN is
         * restarted, but status registers appear readable from either.
@@ -73,7 +78,9 @@ enum {
 
        /* Vendor2 MMD registers */
        MV_V2_PORT_CTRL         = 0xf001,
-       MV_V2_PORT_CTRL_PWRDOWN = 0x0800,
+       MV_V2_PORT_CTRL_SWRST   = BIT(15),
+       MV_V2_PORT_CTRL_PWRDOWN = BIT(11),
+       /* Temperature control/read registers (88X3310 only) */
        MV_V2_TEMP_CTRL         = 0xf08a,
        MV_V2_TEMP_CTRL_MASK    = 0xc000,
        MV_V2_TEMP_CTRL_SAMPLE  = 0x0000,
@@ -83,6 +90,8 @@ enum {
 };
 
 struct mv3310_priv {
+       u32 firmware_ver;
+
        struct device *hwmon_dev;
        char *hwmon_name;
 };
@@ -99,6 +108,24 @@ static umode_t mv3310_hwmon_is_visible(const void *data,
        return 0;
 }
 
+static int mv3310_hwmon_read_temp_reg(struct phy_device *phydev)
+{
+       return phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP);
+}
+
+static int mv2110_hwmon_read_temp_reg(struct phy_device *phydev)
+{
+       return phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_TEMP);
+}
+
+static int mv10g_hwmon_read_temp_reg(struct phy_device *phydev)
+{
+       if (phydev->drv->phy_id == MARVELL_PHY_ID_88X3310)
+               return mv3310_hwmon_read_temp_reg(phydev);
+       else /* MARVELL_PHY_ID_88E2110 */
+               return mv2110_hwmon_read_temp_reg(phydev);
+}
+
 static int mv3310_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
                             u32 attr, int channel, long *value)
 {
@@ -111,7 +138,7 @@ static int mv3310_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
        }
 
        if (type == hwmon_temp && attr == hwmon_temp_input) {
-               temp = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP);
+               temp = mv10g_hwmon_read_temp_reg(phydev);
                if (temp < 0)
                        return temp;
 
@@ -164,6 +191,9 @@ static int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
        u16 val;
        int ret;
 
+       if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310)
+               return 0;
+
        ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP,
                            MV_V2_TEMP_UNKNOWN);
        if (ret < 0)
@@ -235,8 +265,18 @@ static int mv3310_power_down(struct phy_device *phydev)
 
 static int mv3310_power_up(struct phy_device *phydev)
 {
-       return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
-                                 MV_V2_PORT_CTRL_PWRDOWN);
+       struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
+       int ret;
+
+       ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+                                MV_V2_PORT_CTRL_PWRDOWN);
+
+       if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310 ||
+           priv->firmware_ver < 0x00030000)
+               return ret;
+
+       return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+                               MV_V2_PORT_CTRL_SWRST);
 }
 
 static int mv3310_reset(struct phy_device *phydev, u32 unit)
@@ -355,6 +395,22 @@ static int mv3310_probe(struct phy_device *phydev)
 
        dev_set_drvdata(&phydev->mdio.dev, priv);
 
+       ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER0);
+       if (ret < 0)
+               return ret;
+
+       priv->firmware_ver = ret << 16;
+
+       ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER1);
+       if (ret < 0)
+               return ret;
+
+       priv->firmware_ver |= ret;
+
+       phydev_info(phydev, "Firmware version %u.%u.%u.%u\n",
+                   priv->firmware_ver >> 24, (priv->firmware_ver >> 16) & 255,
+                   (priv->firmware_ver >> 8) & 255, priv->firmware_ver & 255);
+
        /* Powering down the port when not in use saves about 600mW */
        ret = mv3310_power_down(phydev);
        if (ret)
index 522760c8bca6ec3d1b90b99c1b8315bb3e0ac23a..7a4eb3f2cb743a007903edaf8362eaee75602870 100644 (file)
@@ -464,7 +464,7 @@ static struct class mdio_bus_class = {
 
 /**
  * mdio_find_bus - Given the name of a mdiobus, find the mii_bus.
- * @mdio_bus_np: Pointer to the mii_bus.
+ * @mdio_name: The name of a mdiobus.
  *
  * Returns a reference to the mii_bus, or NULL if none found.  The
  * embedded struct device will have its reference count incremented,
index 05d20343b8161c722afb2d0f33bda1616fcdb32e..3a4d83fa52dca3c31245428dc0cba5171a641838 100644 (file)
@@ -1204,7 +1204,7 @@ static struct phy_driver ksphy_driver[] = {
        .driver_data    = &ksz9021_type,
        .probe          = kszphy_probe,
        .config_init    = ksz9131_config_init,
-       .read_status    = ksz9031_read_status,
+       .read_status    = genphy_read_status,
        .ack_interrupt  = kszphy_ack_interrupt,
        .config_intr    = kszphy_config_intr,
        .get_sset_count = kszphy_get_sset_count,
index 001def4509c29a79dd5ddee0a1f4b0532c99c43b..fed3e395f18e1c42bd81a5ef6537c18d8782f2ca 100644 (file)
@@ -3,9 +3,21 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/mii.h>
 #include <linux/phy.h>
 
+/* External Register Control Register */
+#define LAN87XX_EXT_REG_CTL                     (0x14)
+#define LAN87XX_EXT_REG_CTL_RD_CTL              (0x1000)
+#define LAN87XX_EXT_REG_CTL_WR_CTL              (0x0800)
+
+/* External Register Read Data Register */
+#define LAN87XX_EXT_REG_RD_DATA                 (0x15)
+
+/* External Register Write Data Register */
+#define LAN87XX_EXT_REG_WR_DATA                 (0x16)
+
 /* Interrupt Source Register */
 #define LAN87XX_INTERRUPT_SOURCE                (0x18)
 
 #define LAN87XX_MASK_LINK_UP                    (0x0004)
 #define LAN87XX_MASK_LINK_DOWN                  (0x0002)
 
+/* phyaccess nested types */
+#define        PHYACC_ATTR_MODE_READ           0
+#define        PHYACC_ATTR_MODE_WRITE          1
+#define        PHYACC_ATTR_MODE_MODIFY         2
+
+#define        PHYACC_ATTR_BANK_SMI            0
+#define        PHYACC_ATTR_BANK_MISC           1
+#define        PHYACC_ATTR_BANK_PCS            2
+#define        PHYACC_ATTR_BANK_AFE            3
+#define        PHYACC_ATTR_BANK_MAX            7
+
 #define DRIVER_AUTHOR  "Nisar Sayed <nisar.sayed@microchip.com>"
 #define DRIVER_DESC    "Microchip LAN87XX T1 PHY driver"
 
+struct access_ereg_val {
+       u8  mode;
+       u8  bank;
+       u8  offset;
+       u16 val;
+       u16 mask;
+};
+
+static int access_ereg(struct phy_device *phydev, u8 mode, u8 bank,
+                      u8 offset, u16 val)
+{
+       u16 ereg = 0;
+       int rc = 0;
+
+       if (mode > PHYACC_ATTR_MODE_WRITE || bank > PHYACC_ATTR_BANK_MAX)
+               return -EINVAL;
+
+       if (bank == PHYACC_ATTR_BANK_SMI) {
+               if (mode == PHYACC_ATTR_MODE_WRITE)
+                       rc = phy_write(phydev, offset, val);
+               else
+                       rc = phy_read(phydev, offset);
+               return rc;
+       }
+
+       if (mode == PHYACC_ATTR_MODE_WRITE) {
+               ereg = LAN87XX_EXT_REG_CTL_WR_CTL;
+               rc = phy_write(phydev, LAN87XX_EXT_REG_WR_DATA, val);
+               if (rc < 0)
+                       return rc;
+       } else {
+               ereg = LAN87XX_EXT_REG_CTL_RD_CTL;
+       }
+
+       ereg |= (bank << 8) | offset;
+
+       rc = phy_write(phydev, LAN87XX_EXT_REG_CTL, ereg);
+       if (rc < 0)
+               return rc;
+
+       if (mode == PHYACC_ATTR_MODE_READ)
+               rc = phy_read(phydev, LAN87XX_EXT_REG_RD_DATA);
+
+       return rc;
+}
+
+static int access_ereg_modify_changed(struct phy_device *phydev,
+                                     u8 bank, u8 offset, u16 val, u16 mask)
+{
+       int new = 0, rc = 0;
+
+       if (bank > PHYACC_ATTR_BANK_MAX)
+               return -EINVAL;
+
+       rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, bank, offset, val);
+       if (rc < 0)
+               return rc;
+
+       new = val | (rc & (mask ^ 0xFFFF));
+       rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE, bank, offset, new);
+
+       return rc;
+}
+
+static int lan87xx_phy_init(struct phy_device *phydev)
+{
+       static const struct access_ereg_val init[] = {
+               /* TX Amplitude = 5 */
+               {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_AFE, 0x0B,
+                0x000A, 0x001E},
+               /* Clear SMI interrupts */
+               {PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI, 0x18,
+                0, 0},
+               /* Clear MISC interrupts */
+               {PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_MISC, 0x08,
+                0, 0},
+               /* Turn on TC10 Ring Oscillator (ROSC) */
+               {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_MISC, 0x20,
+                0x0020, 0x0020},
+               /* WUR Detect Length to 1.2uS, LPC Detect Length to 1.09uS */
+               {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_PCS, 0x20,
+                0x283C, 0},
+               /* Wake_In Debounce Length to 39uS, Wake_Out Length to 79uS */
+               {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_MISC, 0x21,
+                0x274F, 0},
+               /* Enable Auto Wake Forward to Wake_Out, ROSC on, Sleep,
+                * and Wake_In to wake PHY
+                */
+               {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_MISC, 0x20,
+                0x80A7, 0},
+               /* Enable WUP Auto Fwd, Enable Wake on MDI, Wakeup Debouncer
+                * to 128 uS
+                */
+               {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_MISC, 0x24,
+                0xF110, 0},
+               /* Enable HW Init */
+               {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_SMI, 0x1A,
+                0x0100, 0x0100},
+       };
+       int rc, i;
+
+       /* Start manual initialization procedures in Managed Mode */
+       rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI,
+                                       0x1a, 0x0000, 0x0100);
+       if (rc < 0)
+               return rc;
+
+       /* Soft Reset the SMI block */
+       rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI,
+                                       0x00, 0x8000, 0x8000);
+       if (rc < 0)
+               return rc;
+
+       /* Check to see if the self-clearing bit is cleared */
+       usleep_range(1000, 2000);
+       rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
+                        PHYACC_ATTR_BANK_SMI, 0x00, 0);
+       if (rc < 0)
+               return rc;
+       if ((rc & 0x8000) != 0)
+               return -ETIMEDOUT;
+
+       /* PHY Initialization */
+       for (i = 0; i < ARRAY_SIZE(init); i++) {
+               if (init[i].mode == PHYACC_ATTR_MODE_MODIFY) {
+                       rc = access_ereg_modify_changed(phydev, init[i].bank,
+                                                       init[i].offset,
+                                                       init[i].val,
+                                                       init[i].mask);
+               } else {
+                       rc = access_ereg(phydev, init[i].mode, init[i].bank,
+                                        init[i].offset, init[i].val);
+               }
+               if (rc < 0)
+                       return rc;
+       }
+
+       return 0;
+}
+
 static int lan87xx_phy_config_intr(struct phy_device *phydev)
 {
        int rc, val = 0;
@@ -40,6 +203,13 @@ static int lan87xx_phy_ack_interrupt(struct phy_device *phydev)
        return rc < 0 ? rc : 0;
 }
 
+static int lan87xx_config_init(struct phy_device *phydev)
+{
+       int rc = lan87xx_phy_init(phydev);
+
+       return rc < 0 ? rc : 0;
+}
+
 static struct phy_driver microchip_t1_phy_driver[] = {
        {
                .phy_id         = 0x0007c150,
@@ -48,6 +218,7 @@ static struct phy_driver microchip_t1_phy_driver[] = {
 
                .features       = PHY_BASIC_T1_FEATURES,
 
+               .config_init    = lan87xx_config_init,
                .config_aneg    = genphy_config_aneg,
 
                .ack_interrupt  = lan87xx_phy_ack_interrupt,
index 4004f98e50d9fc58a8d8d6449448840d3c9da748..04845a4017f935f3cdff0fbbbc41d281ab641672 100644 (file)
@@ -468,6 +468,9 @@ static const struct team_mode *team_mode_get(const char *kind)
        struct team_mode_item *mitem;
        const struct team_mode *mode = NULL;
 
+       if (!try_module_get(THIS_MODULE))
+               return NULL;
+
        spin_lock(&mode_list_lock);
        mitem = __find_mode(kind);
        if (!mitem) {
@@ -483,6 +486,7 @@ static const struct team_mode *team_mode_get(const char *kind)
        }
 
        spin_unlock(&mode_list_lock);
+       module_put(THIS_MODULE);
        return mode;
 }
 
index 07476c6510f2f50f8185b2be401a5894e37350c8..44889eba1dbc73bdf2f9e5f77e39919be4a43b14 100644 (file)
@@ -1888,6 +1888,7 @@ drop:
 
        skb_reset_network_header(skb);
        skb_probe_transport_header(skb);
+       skb_record_rx_queue(skb, tfile->queue_index);
 
        if (skb_xdp) {
                struct bpf_prog *xdp_prog;
@@ -2459,6 +2460,7 @@ build:
        skb->protocol = eth_type_trans(skb, tun->dev);
        skb_reset_network_header(skb);
        skb_probe_transport_header(skb);
+       skb_record_rx_queue(skb, tfile->queue_index);
 
        if (skb_xdp) {
                err = do_xdp_generic(xdp_prog, skb);
@@ -2470,7 +2472,6 @@ build:
            !tfile->detached)
                rxhash = __skb_get_hash_symmetric(skb);
 
-       skb_record_rx_queue(skb, tfile->queue_index);
        netif_receive_skb(skb);
 
        /* No need for get_cpu_ptr() here since this function is
index 6c738a271257d4f180774e91b10494b0d96fa5c0..4bb8552a00d3de951a49edbaff0d7b309f992703 100644 (file)
@@ -1359,6 +1359,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x413c, 0x81b3, 8)},    /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */
        {QMI_FIXED_INTF(0x413c, 0x81b6, 8)},    /* Dell Wireless 5811e */
        {QMI_FIXED_INTF(0x413c, 0x81b6, 10)},   /* Dell Wireless 5811e */
+       {QMI_FIXED_INTF(0x413c, 0x81cc, 8)},    /* Dell Wireless 5816e */
        {QMI_FIXED_INTF(0x413c, 0x81d7, 0)},    /* Dell Wireless 5821e */
        {QMI_FIXED_INTF(0x413c, 0x81d7, 1)},    /* Dell Wireless 5821e preproduction config */
        {QMI_FIXED_INTF(0x413c, 0x81e0, 0)},    /* Dell Wireless 5821e with eSIM support*/
index 66e00ddc0d421009be4ed5a61d510408e45aabbf..56f8aab46f89ba03ba28f7919b877260659f46e8 100644 (file)
@@ -188,8 +188,8 @@ static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb,
        fl6.flowi6_proto = iph->nexthdr;
        fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;
 
-       dst = ip6_route_output(net, NULL, &fl6);
-       if (dst == dst_null)
+       dst = ip6_dst_lookup_flow(net, NULL, &fl6, NULL);
+       if (IS_ERR(dst) || dst == dst_null)
                goto err;
 
        skb_dst_drop(skb);
@@ -474,7 +474,8 @@ static struct sk_buff *vrf_ip6_out(struct net_device *vrf_dev,
        if (rt6_need_strict(&ipv6_hdr(skb)->daddr))
                return skb;
 
-       if (qdisc_tx_is_default(vrf_dev))
+       if (qdisc_tx_is_default(vrf_dev) ||
+           IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
                return vrf_ip6_out_direct(vrf_dev, sk, skb);
 
        return vrf_ip6_out_redirect(vrf_dev, skb);
@@ -686,7 +687,8 @@ static struct sk_buff *vrf_ip_out(struct net_device *vrf_dev,
            ipv4_is_lbcast(ip_hdr(skb)->daddr))
                return skb;
 
-       if (qdisc_tx_is_default(vrf_dev))
+       if (qdisc_tx_is_default(vrf_dev) ||
+           IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
                return vrf_ip_out_direct(vrf_dev, sk, skb);
 
        return vrf_ip_out_redirect(vrf_dev, skb);
index 45308b3350cf5f4934a9a6cfc7548a7b4175fc15..a5b415fed11efb8c6e2dcd30554ea6c10835d0ab 100644 (file)
@@ -3144,7 +3144,7 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[],
                u32 id = nla_get_u32(data[IFLA_VXLAN_ID]);
 
                if (id >= VXLAN_N_VID) {
-                       NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_ID],
+                       NL_SET_ERR_MSG_ATTR(extack, data[IFLA_VXLAN_ID],
                                            "VXLAN ID must be lower than 16777216");
                        return -ERANGE;
                }
@@ -3155,7 +3155,7 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[],
                        = nla_data(data[IFLA_VXLAN_PORT_RANGE]);
 
                if (ntohs(p->high) < ntohs(p->low)) {
-                       NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_PORT_RANGE],
+                       NL_SET_ERR_MSG_ATTR(extack, data[IFLA_VXLAN_PORT_RANGE],
                                            "Invalid source port range");
                        return -EINVAL;
                }
@@ -3165,7 +3165,7 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[],
                enum ifla_vxlan_df df = nla_get_u8(data[IFLA_VXLAN_DF]);
 
                if (df < 0 || df > VXLAN_DF_MAX) {
-                       NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_DF],
+                       NL_SET_ERR_MSG_ATTR(extack, data[IFLA_VXLAN_DF],
                                            "Invalid DF attribute");
                        return -EINVAL;
                }
index 529ebca1e9e13eb94d4574a29172ec311e614e58..1f7709d24f3526a1498a9f5a2f85e79c71ab811f 100644 (file)
@@ -354,6 +354,7 @@ out:
                usb_autopm_put_interface(i2400mu->usb_iface);
        d_fnend(8, dev, "(i2400m %p ack %p size %zu) = %ld\n",
                i2400m, ack, ack_size, (long) result);
+       usb_put_urb(&notif_urb);
        return result;
 
 error_exceeded:
index 5c964fcb994ec5f44e69d5fa987369af99afe40f..71b8e80b58e121d2cb46882bac905522c205146f 100644 (file)
@@ -35,8 +35,10 @@ int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function,
                if (multicore) {
                        queue->worker = wg_packet_percpu_multicore_worker_alloc(
                                function, queue);
-                       if (!queue->worker)
+                       if (!queue->worker) {
+                               ptr_ring_cleanup(&queue->ring, NULL);
                                return -ENOMEM;
+                       }
                } else {
                        INIT_WORK(&queue->work, function);
                }
index da3b782ab7d31df11e381529b144bcc494234a38..3bb5b9ae7cd15634df6f4700f223618e8f4b456b 100644 (file)
@@ -226,21 +226,20 @@ void wg_packet_handshake_receive_worker(struct work_struct *work)
 static void keep_key_fresh(struct wg_peer *peer)
 {
        struct noise_keypair *keypair;
-       bool send = false;
+       bool send;
 
        if (peer->sent_lastminute_handshake)
                return;
 
        rcu_read_lock_bh();
        keypair = rcu_dereference_bh(peer->keypairs.current_keypair);
-       if (likely(keypair && READ_ONCE(keypair->sending.is_valid)) &&
-           keypair->i_am_the_initiator &&
-           unlikely(wg_birthdate_has_expired(keypair->sending.birthdate,
-                       REJECT_AFTER_TIME - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT)))
-               send = true;
+       send = keypair && READ_ONCE(keypair->sending.is_valid) &&
+              keypair->i_am_the_initiator &&
+              wg_birthdate_has_expired(keypair->sending.birthdate,
+                       REJECT_AFTER_TIME - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT);
        rcu_read_unlock_bh();
 
-       if (send) {
+       if (unlikely(send)) {
                peer->sent_lastminute_handshake = true;
                wg_packet_send_queued_handshake_initiation(peer, false);
        }
@@ -393,13 +392,11 @@ static void wg_packet_consume_data_done(struct wg_peer *peer,
                len = ntohs(ip_hdr(skb)->tot_len);
                if (unlikely(len < sizeof(struct iphdr)))
                        goto dishonest_packet_size;
-               if (INET_ECN_is_ce(PACKET_CB(skb)->ds))
-                       IP_ECN_set_ce(ip_hdr(skb));
+               INET_ECN_decapsulate(skb, PACKET_CB(skb)->ds, ip_hdr(skb)->tos);
        } else if (skb->protocol == htons(ETH_P_IPV6)) {
                len = ntohs(ipv6_hdr(skb)->payload_len) +
                      sizeof(struct ipv6hdr);
-               if (INET_ECN_is_ce(PACKET_CB(skb)->ds))
-                       IP6_ECN_set_ce(skb, ipv6_hdr(skb));
+               INET_ECN_decapsulate(skb, PACKET_CB(skb)->ds, ipv6_get_dsfield(ipv6_hdr(skb)));
        } else {
                goto dishonest_packet_type;
        }
@@ -518,6 +515,8 @@ void wg_packet_decrypt_worker(struct work_struct *work)
                                &PACKET_CB(skb)->keypair->receiving)) ?
                                PACKET_STATE_CRYPTED : PACKET_STATE_DEAD;
                wg_queue_enqueue_per_peer_napi(skb, state);
+               if (need_resched())
+                       cond_resched();
        }
 }
 
index bcd6462e454017841bf86a1973869e83097a2826..007cd4457c5f67be970866335908b4b8c020d67f 100644 (file)
@@ -120,9 +120,9 @@ bool __init wg_ratelimiter_selftest(void)
        enum { TRIALS_BEFORE_GIVING_UP = 5000 };
        bool success = false;
        int test = 0, trials;
-       struct sk_buff *skb4, *skb6;
+       struct sk_buff *skb4, *skb6 = NULL;
        struct iphdr *hdr4;
-       struct ipv6hdr *hdr6;
+       struct ipv6hdr *hdr6 = NULL;
 
        if (IS_ENABLED(CONFIG_KASAN) || IS_ENABLED(CONFIG_UBSAN))
                return true;
index 7348c10cbae3db54bfcb31f23c2753185735f876..6687db69980351c6ba68bb5757626a7dbdbd0e56 100644 (file)
@@ -124,20 +124,17 @@ void wg_packet_send_handshake_cookie(struct wg_device *wg,
 static void keep_key_fresh(struct wg_peer *peer)
 {
        struct noise_keypair *keypair;
-       bool send = false;
+       bool send;
 
        rcu_read_lock_bh();
        keypair = rcu_dereference_bh(peer->keypairs.current_keypair);
-       if (likely(keypair && READ_ONCE(keypair->sending.is_valid)) &&
-           (unlikely(atomic64_read(&keypair->sending.counter.counter) >
-                     REKEY_AFTER_MESSAGES) ||
-            (keypair->i_am_the_initiator &&
-             unlikely(wg_birthdate_has_expired(keypair->sending.birthdate,
-                                               REKEY_AFTER_TIME)))))
-               send = true;
+       send = keypair && READ_ONCE(keypair->sending.is_valid) &&
+              (atomic64_read(&keypair->sending.counter.counter) > REKEY_AFTER_MESSAGES ||
+               (keypair->i_am_the_initiator &&
+                wg_birthdate_has_expired(keypair->sending.birthdate, REKEY_AFTER_TIME)));
        rcu_read_unlock_bh();
 
-       if (send)
+       if (unlikely(send))
                wg_packet_send_queued_handshake_initiation(peer, false);
 }
 
@@ -281,6 +278,8 @@ void wg_packet_tx_worker(struct work_struct *work)
 
                wg_noise_keypair_put(keypair, false);
                wg_peer_put(peer);
+               if (need_resched())
+                       cond_resched();
        }
 }
 
@@ -304,7 +303,8 @@ void wg_packet_encrypt_worker(struct work_struct *work)
                }
                wg_queue_enqueue_per_peer(&PACKET_PEER(first)->tx_queue, first,
                                          state);
-
+               if (need_resched())
+                       cond_resched();
        }
 }
 
index b0d6541582d312eeed1a5a25123cb27380cd038f..f9018027fc133db48e7d20972690c7e52f4942f5 100644 (file)
@@ -76,12 +76,6 @@ static int send4(struct wg_device *wg, struct sk_buff *skb,
                        net_dbg_ratelimited("%s: No route to %pISpfsc, error %d\n",
                                            wg->dev->name, &endpoint->addr, ret);
                        goto err;
-               } else if (unlikely(rt->dst.dev == skb->dev)) {
-                       ip_rt_put(rt);
-                       ret = -ELOOP;
-                       net_dbg_ratelimited("%s: Avoiding routing loop to %pISpfsc\n",
-                                           wg->dev->name, &endpoint->addr);
-                       goto err;
                }
                if (cache)
                        dst_cache_set_ip4(cache, &rt->dst, fl.saddr);
@@ -149,12 +143,6 @@ static int send6(struct wg_device *wg, struct sk_buff *skb,
                        net_dbg_ratelimited("%s: No route to %pISpfsc, error %d\n",
                                            wg->dev->name, &endpoint->addr, ret);
                        goto err;
-               } else if (unlikely(dst->dev == skb->dev)) {
-                       dst_release(dst);
-                       ret = -ELOOP;
-                       net_dbg_ratelimited("%s: Avoiding routing loop to %pISpfsc\n",
-                                           wg->dev->name, &endpoint->addr);
-                       goto err;
                }
                if (cache)
                        dst_cache_set_ip6(cache, dst, &fl.saddr);
index 459b8d49c184220ec0d82cbcc548d571f8d94102..f9af55f3682def093b461eb33530bda4719d3f3f 100644 (file)
@@ -36,12 +36,13 @@ static inline int ath11k_thermal_register(struct ath11k_base *sc)
        return 0;
 }
 
-static inline void ath11k_thermal_unregister(struct ath11k *ar)
+static inline void ath11k_thermal_unregister(struct ath11k_base *sc)
 {
 }
 
 static inline int ath11k_thermal_set_throttling(struct ath11k *ar, u32 throttle_state)
 {
+       return 0;
 }
 
 static inline void ath11k_thermal_event_temperature(struct ath11k *ar,
index 23627c953a5ebd440ac126d931a6ed7b6edd3f2c..436f501be937aef441592ceee86049e1e3ea043e 100644 (file)
@@ -729,9 +729,18 @@ static int brcmf_net_mon_stop(struct net_device *ndev)
        return err;
 }
 
+static netdev_tx_t brcmf_net_mon_start_xmit(struct sk_buff *skb,
+                                           struct net_device *ndev)
+{
+       dev_kfree_skb_any(skb);
+
+       return NETDEV_TX_OK;
+}
+
 static const struct net_device_ops brcmf_netdev_ops_mon = {
        .ndo_open = brcmf_net_mon_open,
        .ndo_stop = brcmf_net_mon_stop,
+       .ndo_start_xmit = brcmf_net_mon_start_xmit,
 };
 
 int brcmf_net_mon_attach(struct brcmf_if *ifp)
index 6209f85a71ddb3438ed68a310a2de71e7280a778..0af9e997c9f6766e21ccf7b8d1b72a37a6622577 100644 (file)
@@ -374,7 +374,7 @@ out:
 }
 
 static void *
-il3945_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+il3945_rs_alloc(struct ieee80211_hw *hw)
 {
        return hw->priv;
 }
index 7c6e2c8634974dee2df38b8530d157ae4bbbffa2..0a02d8aca320619c0186a9d5e407faf1fcfa9064 100644 (file)
@@ -2474,7 +2474,7 @@ il4965_rs_fill_link_cmd(struct il_priv *il, struct il_lq_sta *lq_sta,
 }
 
 static void *
-il4965_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+il4965_rs_alloc(struct ieee80211_hw *hw)
 {
        return hw->priv;
 }
index 226165db7dfd5bfc46007192512993c0864f75be..dac809df7f1dd05e9db77c8bc2634f44761b9e7d 100644 (file)
@@ -3019,7 +3019,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
                        cpu_to_le16(priv->lib->bt_params->agg_time_limit);
 }
 
-static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+static void *rs_alloc(struct ieee80211_hw *hw)
 {
        return hw->priv;
 }
index ba2aff3af0fe9218ed1311e0e56a0c1d95f0a283..e3a33388be701464949af1c0d8e08518247233b9 100644 (file)
@@ -296,9 +296,14 @@ int iwl_sar_select_profile(struct iwl_fw_runtime *fwrt,
                if (!prof->enabled) {
                        IWL_DEBUG_RADIO(fwrt, "SAR profile %d is disabled.\n",
                                        profs[i]);
-                       /* if one of the profiles is disabled, we fail all */
-                       return -ENOENT;
+                       /*
+                        * if one of the profiles is disabled, we
+                        * ignore all of them and return 1 to
+                        * differentiate disabled from other failures.
+                        */
+                       return 1;
                }
+
                IWL_DEBUG_INFO(fwrt,
                               "SAR EWRD: chain %d profile index %d\n",
                               i, profs[i]);
index 73196cbc7fbefd8bb1511adda2ddbd7474664e2c..75d958bab0e380317192f22c339abd909456e63f 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2019 Intel Corporation
+ * Copyright(c) 2019 - 2020 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
  * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2019 Intel Corporation
+ * Copyright(c) 2019 - 2020 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -99,7 +99,7 @@ enum iwl_mvm_dqa_txq {
        IWL_MVM_DQA_MAX_MGMT_QUEUE = 8,
        IWL_MVM_DQA_AP_PROBE_RESP_QUEUE = 9,
        IWL_MVM_DQA_MIN_DATA_QUEUE = 10,
-       IWL_MVM_DQA_MAX_DATA_QUEUE = 31,
+       IWL_MVM_DQA_MAX_DATA_QUEUE = 30,
 };
 
 enum iwl_mvm_tx_fifo {
index ff52e69c1c80a7664ace9470554a56b0c954f1b3..eeb750bdbda130400fe1d0052059880e253aa6e4 100644 (file)
@@ -1467,7 +1467,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
                                kmemdup(pieces->dbg_conf_tlv[i],
                                        pieces->dbg_conf_tlv_len[i],
                                        GFP_KERNEL);
-                       if (!pieces->dbg_conf_tlv[i])
+                       if (!drv->fw.dbg.conf_tlv[i])
                                goto out_free_fw;
                }
        }
index 9e9810d2b26221650b6f958a329d8bdc2f7706ed..ccf0bc16465d20c08948b5ea3c97e850c59ee84f 100644 (file)
@@ -532,8 +532,7 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = {
                                        IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US |
                                        IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8,
                                .mac_cap_info[2] =
-                                       IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP |
-                                       IEEE80211_HE_MAC_CAP2_ACK_EN,
+                                       IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP,
                                .mac_cap_info[3] =
                                        IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
                                        IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_2,
@@ -617,8 +616,7 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = {
                                        IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US |
                                        IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8,
                                .mac_cap_info[2] =
-                                       IEEE80211_HE_MAC_CAP2_BSR |
-                                       IEEE80211_HE_MAC_CAP2_ACK_EN,
+                                       IEEE80211_HE_MAC_CAP2_BSR,
                                .mac_cap_info[3] =
                                        IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
                                        IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_2,
index a4038f289ab31244c1681e37044724a814104ca1..e67c452fa92cff0b09d75f03fcfc3c984ea0246a 100644 (file)
@@ -727,6 +727,7 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
                struct iwl_dev_tx_power_cmd_v4 v4;
        } cmd;
 
+       int ret;
        u16 len = 0;
 
        cmd.v5.v3.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS);
@@ -741,9 +742,14 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
                len = sizeof(cmd.v4.v3);
 
 
-       if (iwl_sar_select_profile(&mvm->fwrt, cmd.v5.v3.per_chain_restriction,
-                                  prof_a, prof_b))
-               return -ENOENT;
+       ret = iwl_sar_select_profile(&mvm->fwrt,
+                                    cmd.v5.v3.per_chain_restriction,
+                                    prof_a, prof_b);
+
+       /* return on error or if the profile is disabled (positive number) */
+       if (ret)
+               return ret;
+
        IWL_DEBUG_RADIO(mvm, "Sending REDUCE_TX_POWER_CMD per chain\n");
        return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
 }
@@ -1034,16 +1040,7 @@ static int iwl_mvm_sar_init(struct iwl_mvm *mvm)
                                "EWRD SAR BIOS table invalid or unavailable. (%d)\n",
                                ret);
 
-       ret = iwl_mvm_sar_select_profile(mvm, 1, 1);
-       /*
-        * If we don't have profile 0 from BIOS, just skip it.  This
-        * means that SAR Geo will not be enabled either, even if we
-        * have other valid profiles.
-        */
-       if (ret == -ENOENT)
-               return 1;
-
-       return ret;
+       return iwl_mvm_sar_select_profile(mvm, 1, 1);
 }
 
 static int iwl_mvm_load_rt_fw(struct iwl_mvm *mvm)
@@ -1272,7 +1269,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
        ret = iwl_mvm_sar_init(mvm);
        if (ret == 0) {
                ret = iwl_mvm_sar_geo_init(mvm);
-       } else if (ret > 0 && !iwl_sar_get_wgds_table(&mvm->fwrt)) {
+       } else if (ret == -ENOENT && !iwl_sar_get_wgds_table(&mvm->fwrt)) {
                /*
                 * If basic SAR is not available, we check for WGDS,
                 * which should *not* be available either.  If it is
index c1aba2bf73cff4b0732d76f21b05fa8c79ee22ad..00e7fdbaeb7fd8104a536bfa45d75610860ea131 100644 (file)
@@ -3665,7 +3665,7 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
                        cpu_to_le16(iwl_mvm_coex_agg_time_limit(mvm, sta));
 }
 
-static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+static void *rs_alloc(struct ieee80211_hw *hw)
 {
        return hw->priv;
 }
index 5ee33c8ae9d24cd55b38be4cf745a92fd19e85f3..77b8def26edb225130670a05c8ad204880bd7641 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -566,6 +566,7 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
 
 struct iwl_mvm_stat_data {
        struct iwl_mvm *mvm;
+       __le32 flags;
        __le32 mac_id;
        u8 beacon_filter_average_energy;
        void *general;
@@ -606,6 +607,13 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
                        -general->beacon_average_energy[vif_id];
        }
 
+       /* make sure that beacon statistics don't go backwards with TCM
+        * request to clear statistics
+        */
+       if (le32_to_cpu(data->flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
+               mvmvif->beacon_stats.accu_num_beacons +=
+                       mvmvif->beacon_stats.num_beacons;
+
        if (mvmvif->id != id)
                return;
 
@@ -763,6 +771,7 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
 
                flags = stats->flag;
        }
+       data.flags = flags;
 
        iwl_mvm_rx_stats_check_trigger(mvm, pkt);
 
index 64ef3f3ba23b7d229afaf0ea7f144858abfc398c..56ae72debb96a0e510da48d0a127b473f1aaab4b 100644 (file)
@@ -722,6 +722,11 @@ static int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id,
 
        lockdep_assert_held(&mvm->mutex);
 
+       if (WARN(maxq >= mvm->trans->trans_cfg->base_params->num_of_queues,
+                "max queue %d >= num_of_queues (%d)", maxq,
+                mvm->trans->trans_cfg->base_params->num_of_queues))
+               maxq = mvm->trans->trans_cfg->base_params->num_of_queues - 1;
+
        /* This should not be hit with new TX path */
        if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
                return -ENOSPC;
@@ -1164,9 +1169,9 @@ static int iwl_mvm_inactivity_check(struct iwl_mvm *mvm, u8 alloc_for_sta)
                                                   inactive_tid_bitmap,
                                                   &unshare_queues,
                                                   &changetid_queues);
-               if (ret >= 0 && free_queue < 0) {
+               if (ret && free_queue < 0) {
                        queue_owner = sta;
-                       free_queue = ret;
+                       free_queue = i;
                }
                /* only unlock sta lock - we still need the queue info lock */
                spin_unlock_bh(&mvmsta->lock);
index 01f248ba8fecfd6ead64945fc62ef35943f95e9d..9d5b1e51b50d7385afa6a4d3efd5f14952d4541a 100644 (file)
@@ -129,6 +129,18 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
        int cmdq_size = max_t(u32, IWL_CMD_QUEUE_SIZE,
                              trans->cfg->min_txq_size);
 
+       switch (trans_pcie->rx_buf_size) {
+       case IWL_AMSDU_DEF:
+               return -EINVAL;
+       case IWL_AMSDU_2K:
+               break;
+       case IWL_AMSDU_4K:
+       case IWL_AMSDU_8K:
+       case IWL_AMSDU_12K:
+               control_flags |= IWL_PRPH_SCRATCH_RB_SIZE_4K;
+               break;
+       }
+
        /* Allocate prph scratch */
        prph_scratch = dma_alloc_coherent(trans->dev, sizeof(*prph_scratch),
                                          &trans_pcie->prph_scratch_dma_addr,
@@ -143,10 +155,8 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
                cpu_to_le16((u16)iwl_read32(trans, CSR_HW_REV));
        prph_sc_ctrl->version.size = cpu_to_le16(sizeof(*prph_scratch) / 4);
 
-       control_flags = IWL_PRPH_SCRATCH_RB_SIZE_4K |
-                       IWL_PRPH_SCRATCH_MTR_MODE |
-                       (IWL_PRPH_MTR_FORMAT_256B &
-                        IWL_PRPH_SCRATCH_MTR_FORMAT);
+       control_flags |= IWL_PRPH_SCRATCH_MTR_MODE;
+       control_flags |= IWL_PRPH_MTR_FORMAT_256B & IWL_PRPH_SCRATCH_MTR_FORMAT;
 
        /* initialize RX default queue */
        prph_sc_ctrl->rbd_cfg.free_rbd_addr =
index 86fc001678174cd278af0c29eb93218ea4ed8159..9664dbc70ef1cfcd0ae30eff58a5562ab9ce06c3 100644 (file)
@@ -1418,6 +1418,9 @@ void iwl_trans_pcie_dyn_txq_free(struct iwl_trans *trans, int queue)
 
        iwl_pcie_gen2_txq_unmap(trans, queue);
 
+       iwl_pcie_gen2_txq_free_memory(trans, trans_pcie->txq[queue]);
+       trans_pcie->txq[queue] = NULL;
+
        IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", queue);
 }
 
index 7fe8207db6ae9d7dd1c99c302116e7293fe36426..0528d4cb4d37478bbed6008b20dde478e5390f87 100644 (file)
@@ -3669,9 +3669,9 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
        }
 
        if (info->attrs[HWSIM_ATTR_RADIO_NAME]) {
-               hwname = kasprintf(GFP_KERNEL, "%.*s",
-                                  nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]),
-                                  (char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]));
+               hwname = kstrndup((char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]),
+                                 nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]),
+                                 GFP_KERNEL);
                if (!hwname)
                        return -ENOMEM;
                param.hwname = hwname;
@@ -3691,9 +3691,9 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)
        if (info->attrs[HWSIM_ATTR_RADIO_ID]) {
                idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]);
        } else if (info->attrs[HWSIM_ATTR_RADIO_NAME]) {
-               hwname = kasprintf(GFP_KERNEL, "%.*s",
-                                  nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]),
-                                  (char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]));
+               hwname = kstrndup((char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]),
+                                 nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]),
+                                 GFP_KERNEL);
                if (!hwname)
                        return -ENOMEM;
        } else
@@ -4068,7 +4068,7 @@ static void hwsim_virtio_rx_work(struct work_struct *work)
        }
        vq = hwsim_vqs[HWSIM_VQ_RX];
        sg_init_one(sg, skb->head, skb_end_offset(skb));
-       err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL);
+       err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_ATOMIC);
        if (WARN(err, "virtqueue_add_inbuf returned %d\n", err))
                nlmsg_free(skb);
        else
index 0c7d74902d33b7dd361d7ba31924b3809f476e12..4b5ea0ec9109362e97833a5f32b904fe6e6e4184 100644 (file)
@@ -261,7 +261,7 @@ static void rtl_rate_update(void *ppriv,
 {
 }
 
-static void *rtl_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+static void *rtl_rate_alloc(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        return rtlpriv;
index e37c71495c0d31907f9fee039f394115cf108c87..1af87eb2e53ac90a0a9d30dd54cd1d9464528b82 100644 (file)
@@ -1338,22 +1338,17 @@ static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev)
        rtw_pci_link_cfg(rtwdev);
 }
 
-#ifdef CONFIG_PM
-static int rtw_pci_suspend(struct device *dev)
+static int __maybe_unused rtw_pci_suspend(struct device *dev)
 {
        return 0;
 }
 
-static int rtw_pci_resume(struct device *dev)
+static int __maybe_unused rtw_pci_resume(struct device *dev)
 {
        return 0;
 }
 
 static SIMPLE_DEV_PM_OPS(rtw_pm_ops, rtw_pci_suspend, rtw_pci_resume);
-#define RTW_PM_OPS (&rtw_pm_ops)
-#else
-#define RTW_PM_OPS NULL
-#endif
 
 static int rtw_pci_claim(struct rtw_dev *rtwdev, struct pci_dev *pdev)
 {
@@ -1582,7 +1577,7 @@ static struct pci_driver rtw_pci_driver = {
        .id_table = rtw_pci_id_table,
        .probe = rtw_pci_probe,
        .remove = rtw_pci_remove,
-       .driver.pm = RTW_PM_OPS,
+       .driver.pm = &rtw_pm_ops,
 };
 module_pci_driver(rtw_pci_driver);
 
index 91c1bd659947eb259292f01c4f3b86e2ec70cb7f..f3c037f5a9ba058f2f811fee80b6c41bb3b7fdf1 100644 (file)
@@ -1110,7 +1110,7 @@ static int nvme_identify_ns_descs(struct nvme_ctrl *ctrl, unsigned nsid,
                  * Don't treat an error as fatal, as we potentially already
                  * have a NGUID or EUI-64.
                  */
-               if (status > 0)
+               if (status > 0 && !(status & NVME_SC_DNR))
                        status = 0;
                goto free_data;
        }
@@ -3642,6 +3642,8 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
 
        return;
  out_put_disk:
+       /* prevent double queue cleanup */
+       ns->disk->queue = NULL;
        put_disk(ns->disk);
  out_unlink_ns:
        mutex_lock(&ctrl->subsys->lock);
index 4e79e412b276c2140b5bca6f9f118e7621f1295e..e13c370de830473972250ab683eec8a82a03564e 100644 (file)
@@ -973,9 +973,13 @@ static inline void nvme_handle_cqe(struct nvme_queue *nvmeq, u16 idx)
 
 static inline void nvme_update_cq_head(struct nvme_queue *nvmeq)
 {
-       if (++nvmeq->cq_head == nvmeq->q_depth) {
+       u16 tmp = nvmeq->cq_head + 1;
+
+       if (tmp == nvmeq->q_depth) {
                nvmeq->cq_head = 0;
                nvmeq->cq_phase ^= 1;
+       } else {
+               nvmeq->cq_head = tmp;
        }
 }
 
index c9219fddf44bea12fe7f8e14dfc3b224631c7bbb..50bbe0edf538022c2f9f2f13546499fe4addf643 100644 (file)
@@ -261,6 +261,8 @@ static struct property *dup_and_fixup_symbol_prop(
 
        of_property_set_flag(new_prop, OF_DYNAMIC);
 
+       kfree(target_path);
+
        return new_prop;
 
 err_free_new_prop:
index c190da54f1754f77cfdee751126e57842e91312f..6327d1ffb9636589857d6c92f011c23c2854dde1 100644 (file)
@@ -3,22 +3,37 @@
 /plugin/;
 
 /*
- * &electric_1/motor-1 and &spin_ctrl_1 are the same node:
- *   /testcase-data-2/substation@100/motor-1
+ * &electric_1/motor-1/electric and &spin_ctrl_1/electric are the same node:
+ *   /testcase-data-2/substation@100/motor-1/electric
  *
  * Thus the property "rpm_avail" in each fragment will
  * result in an attempt to update the same property twice.
  * This will result in an error and the overlay apply
  * will fail.
+ *
+ * The previous version of this test did not include the extra
+ * level of node 'electric'.  That resulted in the 'rpm_avail'
+ * property being located in the pre-existing node 'motor-1'.
+ * Modifying a property results in a WARNING that a memory leak
+ * will occur if the overlay is removed.  Since the overlay apply
+ * fails, the memory leak does actually occur, and kmemleak will
+ * further report the memory leak if CONFIG_DEBUG_KMEMLEAK is
+ * enabled.  Adding the overlay node 'electric' avoids the
+ * memory leak and thus people who use kmemleak will not
+ * have to debug this non-problem again.
  */
 
 &electric_1 {
 
        motor-1 {
-               rpm_avail = < 100 >;
+               electric {
+                       rpm_avail = < 100 >;
+               };
        };
 };
 
 &spin_ctrl_1 {
-               rpm_avail = < 100 200 >;
+               electric {
+                       rpm_avail = < 100 200 >;
+               };
 };
index 7e27670c36163f0c0e82ed254806b11d843b8a9b..398de04fd19c943e40ec0adb6d5bca92302c1979 100644 (file)
@@ -861,6 +861,10 @@ static void __init of_unittest_changeset(void)
        unittest(!of_changeset_revert(&chgset), "revert failed\n");
 
        of_changeset_destroy(&chgset);
+
+       of_node_put(n1);
+       of_node_put(n2);
+       of_node_put(n21);
 #endif
 }
 
@@ -1243,10 +1247,13 @@ static void __init of_unittest_platform_populate(void)
 
        of_platform_populate(np, match, NULL, &test_bus->dev);
        for_each_child_of_node(np, child) {
-               for_each_child_of_node(child, grandchild)
-                       unittest(of_find_device_by_node(grandchild),
+               for_each_child_of_node(child, grandchild) {
+                       pdev = of_find_device_by_node(grandchild);
+                       unittest(pdev,
                                 "Could not create device for node '%pOFn'\n",
                                 grandchild);
+                       of_dev_put(pdev);
+               }
        }
 
        of_platform_depopulate(&test_bus->dev);
@@ -3087,8 +3094,11 @@ static __init void of_unittest_overlay_high_level(void)
                                goto err_unlock;
                        }
                        if (__of_add_property(of_symbols, new_prop)) {
+                               kfree(new_prop->name);
+                               kfree(new_prop->value);
+                               kfree(new_prop);
                                /* "name" auto-generated by unflatten */
-                               if (!strcmp(new_prop->name, "name"))
+                               if (!strcmp(prop->name, "name"))
                                        continue;
                                unittest(0, "duplicate property '%s' in overlay_base node __symbols__",
                                         prop->name);
@@ -3171,21 +3181,21 @@ static __init void of_unittest_overlay_high_level(void)
                   "OF: overlay: ERROR: multiple fragments add and/or delete node /testcase-data-2/substation@100/motor-1/controller");
 
        EXPECT_BEGIN(KERN_ERR,
-                    "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/motor-1/rpm_avail");
+                    "OF: overlay: ERROR: multiple fragments add and/or delete node /testcase-data-2/substation@100/motor-1/electric");
        EXPECT_BEGIN(KERN_ERR,
-                    "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/motor-1/rpm_avail");
+                    "OF: overlay: ERROR: multiple fragments add, update, and/or delete property /testcase-data-2/substation@100/motor-1/electric/rpm_avail");
        EXPECT_BEGIN(KERN_ERR,
-                    "OF: overlay: ERROR: multiple fragments add, update, and/or delete property /testcase-data-2/substation@100/motor-1/rpm_avail");
+                    "OF: overlay: ERROR: multiple fragments add, update, and/or delete property /testcase-data-2/substation@100/motor-1/electric/name");
 
        unittest(overlay_data_apply("overlay_bad_add_dup_prop", NULL),
                 "Adding overlay 'overlay_bad_add_dup_prop' failed\n");
 
        EXPECT_END(KERN_ERR,
-                  "OF: overlay: ERROR: multiple fragments add, update, and/or delete property /testcase-data-2/substation@100/motor-1/rpm_avail");
+                    "OF: overlay: ERROR: multiple fragments add, update, and/or delete property /testcase-data-2/substation@100/motor-1/electric/name");
        EXPECT_END(KERN_ERR,
-                  "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/motor-1/rpm_avail");
+                    "OF: overlay: ERROR: multiple fragments add, update, and/or delete property /testcase-data-2/substation@100/motor-1/electric/rpm_avail");
        EXPECT_END(KERN_ERR,
-                  "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/motor-1/rpm_avail");
+                    "OF: overlay: ERROR: multiple fragments add and/or delete node /testcase-data-2/substation@100/motor-1/electric");
 
        unittest(overlay_data_apply("overlay_bad_phandle", NULL),
                 "Adding overlay 'overlay_bad_phandle' failed\n");
index ba43e6a3dc0aeeddab9409fd0adc6339815c841e..e4f01e7771a223d6915a5f231339b1fd5d0a3a4a 100644 (file)
@@ -819,6 +819,8 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
        if (unlikely(!target_freq)) {
                if (opp_table->required_opp_tables) {
                        ret = _set_required_opps(dev, opp_table, NULL);
+               } else if (!_get_opp_count(opp_table)) {
+                       return 0;
                } else {
                        dev_err(dev, "target frequency can't be 0\n");
                        ret = -EINVAL;
@@ -849,6 +851,18 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
                goto put_opp_table;
        }
 
+       /*
+        * For IO devices which require an OPP on some platforms/SoCs
+        * while just needing to scale the clock on some others
+        * we look for empty OPP tables with just a clock handle and
+        * scale only the clk. This makes dev_pm_opp_set_rate()
+        * equivalent to a clk_set_rate()
+        */
+       if (!_get_opp_count(opp_table)) {
+               ret = _generic_set_opp_clk_only(dev, clk, freq);
+               goto put_opp_table;
+       }
+
        temp_freq = old_freq;
        old_opp = _find_freq_ceil(opp_table, &temp_freq);
        if (IS_ERR(old_opp)) {
index 28c9a2409c50eceb3bc9c9722ee417421151ecc0..ca9ed5774eb1bfefb372fc87a9635788ea5b24f5 100644 (file)
@@ -5567,3 +5567,10 @@ static void pci_fixup_no_d0_pme(struct pci_dev *dev)
        dev->pme_support &= ~(PCI_PM_CAP_PME_D0 >> PCI_PM_CAP_PME_SHIFT);
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x2142, pci_fixup_no_d0_pme);
+
+static void apex_pci_fixup_class(struct pci_dev *pdev)
+{
+       pdev->class = (PCI_CLASS_SYSTEM_OTHER << 8) | pdev->class;
+}
+DECLARE_PCI_FIXUP_CLASS_HEADER(0x1ac1, 0x089a,
+                              PCI_CLASS_NOT_DEFINED, 8, apex_pci_fixup_class);
index 3708d43b75085a29d1809e352a6bbda6b484e702..393011a05b48a640da7f70fdef3394b5026a552d 100644 (file)
@@ -815,6 +815,13 @@ static const struct of_device_id qusb2_phy_of_match_table[] = {
        }, {
                .compatible     = "qcom,msm8998-qusb2-phy",
                .data           = &msm8998_phy_cfg,
+       }, {
+               /*
+                * Deprecated. Only here to support legacy device
+                * trees that didn't include "qcom,qusb2-v2-phy"
+                */
+               .compatible     = "qcom,sdm845-qusb2-phy",
+               .data           = &qusb2_v2_phy_cfg,
        }, {
                .compatible     = "qcom,qusb2-v2-phy",
                .data           = &qusb2_v2_phy_cfg,
index d998e65c89c800e12ebf9c0dae8b3735ade4b8fe..a52a9bf13b758d99c95786a8e9e8d1cbe2fe15bf 100644 (file)
@@ -160,18 +160,11 @@ static int qcom_snps_hsphy_power_on(struct phy *phy)
        ret = regulator_bulk_enable(VREG_NUM, priv->vregs);
        if (ret)
                return ret;
-       ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
-       if (ret)
-               goto err_disable_regulator;
+
        qcom_snps_hsphy_disable_hv_interrupts(priv);
        qcom_snps_hsphy_exit_retention(priv);
 
        return 0;
-
-err_disable_regulator:
-       regulator_bulk_disable(VREG_NUM, priv->vregs);
-
-       return ret;
 }
 
 static int qcom_snps_hsphy_power_off(struct phy *phy)
@@ -180,7 +173,6 @@ static int qcom_snps_hsphy_power_off(struct phy *phy)
 
        qcom_snps_hsphy_enter_retention(priv);
        qcom_snps_hsphy_enable_hv_interrupts(priv);
-       clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
        regulator_bulk_disable(VREG_NUM, priv->vregs);
 
        return 0;
@@ -266,21 +258,39 @@ static int qcom_snps_hsphy_init(struct phy *phy)
        struct hsphy_priv *priv = phy_get_drvdata(phy);
        int ret;
 
-       ret = qcom_snps_hsphy_reset(priv);
+       ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
        if (ret)
                return ret;
 
+       ret = qcom_snps_hsphy_reset(priv);
+       if (ret)
+               goto disable_clocks;
+
        qcom_snps_hsphy_init_sequence(priv);
 
        ret = qcom_snps_hsphy_por_reset(priv);
        if (ret)
-               return ret;
+               goto disable_clocks;
+
+       return 0;
+
+disable_clocks:
+       clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
+       return ret;
+}
+
+static int qcom_snps_hsphy_exit(struct phy *phy)
+{
+       struct hsphy_priv *priv = phy_get_drvdata(phy);
+
+       clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
 
        return 0;
 }
 
 static const struct phy_ops qcom_snps_hsphy_ops = {
        .init = qcom_snps_hsphy_init,
+       .exit = qcom_snps_hsphy_exit,
        .power_on = qcom_snps_hsphy_power_on,
        .power_off = qcom_snps_hsphy_power_off,
        .set_mode = qcom_snps_hsphy_set_mode,
index a208aca4ba7b376bfc350bc8f082dca93b21ac3b..c591c958f1ebc56ec33dd9c01f51a656f9866e7a 100644 (file)
@@ -1,7 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config PHY_TEGRA_XUSB
        tristate "NVIDIA Tegra XUSB pad controller driver"
-       depends on ARCH_TEGRA
+       depends on ARCH_TEGRA && USB_SUPPORT
+       select USB_COMMON
        select USB_CONN_GPIO
        select USB_PHY
        help
index b7f2c00db5e1e423f7ed4d3d7927da0685c29f18..9c4af76a9956ed567752f6920ec8db3671b2ab35 100644 (file)
@@ -52,28 +52,15 @@ static int cros_ec_sensorhub_register(struct device *dev,
        int sensor_type[MOTIONSENSE_TYPE_MAX] = { 0 };
        struct cros_ec_command *msg = sensorhub->msg;
        struct cros_ec_dev *ec = sensorhub->ec;
-       int ret, i, sensor_num;
+       int ret, i;
        char *name;
 
-       sensor_num = cros_ec_get_sensor_count(ec);
-       if (sensor_num < 0) {
-               dev_err(dev,
-                       "Unable to retrieve sensor information (err:%d)\n",
-                       sensor_num);
-               return sensor_num;
-       }
-
-       sensorhub->sensor_num = sensor_num;
-       if (sensor_num == 0) {
-               dev_err(dev, "Zero sensors reported.\n");
-               return -EINVAL;
-       }
 
        msg->version = 1;
        msg->insize = sizeof(struct ec_response_motion_sense);
        msg->outsize = sizeof(struct ec_params_motion_sense);
 
-       for (i = 0; i < sensor_num; i++) {
+       for (i = 0; i < sensorhub->sensor_num; i++) {
                sensorhub->params->cmd = MOTIONSENSE_CMD_INFO;
                sensorhub->params->info.sensor_num = i;
 
@@ -140,8 +127,7 @@ static int cros_ec_sensorhub_probe(struct platform_device *pdev)
        struct cros_ec_dev *ec = dev_get_drvdata(dev->parent);
        struct cros_ec_sensorhub *data;
        struct cros_ec_command *msg;
-       int ret;
-       int i;
+       int ret, i, sensor_num;
 
        msg = devm_kzalloc(dev, sizeof(struct cros_ec_command) +
                           max((u16)sizeof(struct ec_params_motion_sense),
@@ -166,10 +152,52 @@ static int cros_ec_sensorhub_probe(struct platform_device *pdev)
        dev_set_drvdata(dev, data);
 
        /* Check whether this EC is a sensor hub. */
-       if (cros_ec_check_features(data->ec, EC_FEATURE_MOTION_SENSE)) {
+       if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE)) {
+               sensor_num = cros_ec_get_sensor_count(ec);
+               if (sensor_num < 0) {
+                       dev_err(dev,
+                               "Unable to retrieve sensor information (err:%d)\n",
+                               sensor_num);
+                       return sensor_num;
+               }
+               if (sensor_num == 0) {
+                       dev_err(dev, "Zero sensors reported.\n");
+                       return -EINVAL;
+               }
+               data->sensor_num = sensor_num;
+
+               /*
+                * Prepare the ring handler before enumering the
+                * sensors.
+                */
+               if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
+                       ret = cros_ec_sensorhub_ring_allocate(data);
+                       if (ret)
+                               return ret;
+               }
+
+               /* Enumerate the sensors.*/
                ret = cros_ec_sensorhub_register(dev, data);
                if (ret)
                        return ret;
+
+               /*
+                * When the EC does not have a FIFO, the sensors will query
+                * their data themselves via sysfs or a software trigger.
+                */
+               if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
+                       ret = cros_ec_sensorhub_ring_add(data);
+                       if (ret)
+                               return ret;
+                       /*
+                        * The msg and its data is not under the control of the
+                        * ring handler.
+                        */
+                       return devm_add_action_or_reset(dev,
+                                       cros_ec_sensorhub_ring_remove,
+                                       data);
+               }
+
        } else {
                /*
                 * If the device has sensors but does not claim to
@@ -184,22 +212,6 @@ static int cros_ec_sensorhub_probe(struct platform_device *pdev)
                }
        }
 
-       /*
-        * If the EC does not have a FIFO, the sensors will query their data
-        * themselves via sysfs or a software trigger.
-        */
-       if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
-               ret = cros_ec_sensorhub_ring_add(data);
-               if (ret)
-                       return ret;
-               /*
-                * The msg and its data is not under the control of the ring
-                * handler.
-                */
-               return devm_add_action_or_reset(dev,
-                                               cros_ec_sensorhub_ring_remove,
-                                               data);
-       }
 
        return 0;
 }
index 230e6cf3da2f71773cde303e0fe97c6e67009d93..24e48d96ed7663f3f8fda74b7ace2b71c93181f1 100644 (file)
@@ -40,7 +40,7 @@ cros_sensorhub_send_sample(struct cros_ec_sensorhub *sensorhub,
        int id = sample->sensor_id;
        struct iio_dev *indio_dev;
 
-       if (id > sensorhub->sensor_num)
+       if (id >= sensorhub->sensor_num)
                return -EINVAL;
 
        cb = sensorhub->push_data[id].push_data_cb;
@@ -820,7 +820,7 @@ static void cros_ec_sensorhub_ring_handler(struct cros_ec_sensorhub *sensorhub)
        if (fifo_info->count > sensorhub->fifo_size ||
            fifo_info->size != sensorhub->fifo_size) {
                dev_warn(sensorhub->dev,
-                        "Mismatch EC data: count %d, size %d - expected %d",
+                        "Mismatch EC data: count %d, size %d - expected %d\n",
                         fifo_info->count, fifo_info->size,
                         sensorhub->fifo_size);
                goto error;
@@ -851,14 +851,14 @@ static void cros_ec_sensorhub_ring_handler(struct cros_ec_sensorhub *sensorhub)
                }
                if (number_data > fifo_info->count - i) {
                        dev_warn(sensorhub->dev,
-                                "Invalid EC data: too many entry received: %d, expected %d",
+                                "Invalid EC data: too many entry received: %d, expected %d\n",
                                 number_data, fifo_info->count - i);
                        break;
                }
                if (out + number_data >
                    sensorhub->ring + fifo_info->count) {
                        dev_warn(sensorhub->dev,
-                                "Too many samples: %d (%zd data) to %d entries for expected %d entries",
+                                "Too many samples: %d (%zd data) to %d entries for expected %d entries\n",
                                 i, out - sensorhub->ring, i + number_data,
                                 fifo_info->count);
                        break;
@@ -957,17 +957,15 @@ static int cros_ec_sensorhub_event(struct notifier_block *nb,
 }
 
 /**
- * cros_ec_sensorhub_ring_add() - Add the FIFO functionality if the EC
- *                               supports it.
+ * cros_ec_sensorhub_ring_allocate() - Prepare the FIFO functionality if the EC
+ *                                    supports it.
  *
  * @sensorhub : Sensor Hub object.
  *
  * Return: 0 on success.
  */
-int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub)
+int cros_ec_sensorhub_ring_allocate(struct cros_ec_sensorhub *sensorhub)
 {
-       struct cros_ec_dev *ec = sensorhub->ec;
-       int ret;
        int fifo_info_length =
                sizeof(struct ec_response_motion_sense_fifo_info) +
                sizeof(u16) * sensorhub->sensor_num;
@@ -978,6 +976,49 @@ int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub)
        if (!sensorhub->fifo_info)
                return -ENOMEM;
 
+       /*
+        * Allocate the callback area based on the number of sensors.
+        * Add one for the sensor ring.
+        */
+       sensorhub->push_data = devm_kcalloc(sensorhub->dev,
+                       sensorhub->sensor_num,
+                       sizeof(*sensorhub->push_data),
+                       GFP_KERNEL);
+       if (!sensorhub->push_data)
+               return -ENOMEM;
+
+       sensorhub->tight_timestamps = cros_ec_check_features(
+                       sensorhub->ec,
+                       EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS);
+
+       if (sensorhub->tight_timestamps) {
+               sensorhub->batch_state = devm_kcalloc(sensorhub->dev,
+                               sensorhub->sensor_num,
+                               sizeof(*sensorhub->batch_state),
+                               GFP_KERNEL);
+               if (!sensorhub->batch_state)
+                       return -ENOMEM;
+       }
+
+       return 0;
+}
+
+/**
+ * cros_ec_sensorhub_ring_add() - Add the FIFO functionality if the EC
+ *                               supports it.
+ *
+ * @sensorhub : Sensor Hub object.
+ *
+ * Return: 0 on success.
+ */
+int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub)
+{
+       struct cros_ec_dev *ec = sensorhub->ec;
+       int ret;
+       int fifo_info_length =
+               sizeof(struct ec_response_motion_sense_fifo_info) +
+               sizeof(u16) * sensorhub->sensor_num;
+
        /* Retrieve FIFO information */
        sensorhub->msg->version = 2;
        sensorhub->params->cmd = MOTIONSENSE_CMD_FIFO_INFO;
@@ -998,31 +1039,9 @@ int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub)
        if (!sensorhub->ring)
                return -ENOMEM;
 
-       /*
-        * Allocate the callback area based on the number of sensors.
-        */
-       sensorhub->push_data = devm_kcalloc(
-                       sensorhub->dev, sensorhub->sensor_num,
-                       sizeof(*sensorhub->push_data),
-                       GFP_KERNEL);
-       if (!sensorhub->push_data)
-               return -ENOMEM;
-
        sensorhub->fifo_timestamp[CROS_EC_SENSOR_LAST_TS] =
                cros_ec_get_time_ns();
 
-       sensorhub->tight_timestamps = cros_ec_check_features(
-                       ec, EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS);
-
-       if (sensorhub->tight_timestamps) {
-               sensorhub->batch_state = devm_kcalloc(sensorhub->dev,
-                               sensorhub->sensor_num,
-                               sizeof(*sensorhub->batch_state),
-                               GFP_KERNEL);
-               if (!sensorhub->batch_state)
-                       return -ENOMEM;
-       }
-
        /* Register the notifier that will act as a top half interrupt. */
        sensorhub->notifier.notifier_call = cros_ec_sensorhub_event;
        ret = blocking_notifier_chain_register(&ec->ec_dev->event_notifier,
index 6f12747a359a286a8a5fcfd33440264e75e17de9..c4404d9c1de4ff3fd1eac24991de546a04f09778 100644 (file)
@@ -515,9 +515,33 @@ static struct asus_wmi_driver asus_nb_wmi_driver = {
        .detect_quirks = asus_nb_wmi_quirks,
 };
 
+static const struct dmi_system_id asus_nb_wmi_blacklist[] __initconst = {
+       {
+               /*
+                * asus-nb-wm adds no functionality. The T100TA has a detachable
+                * USB kbd, so no hotkeys and it has no WMI rfkill; and loading
+                * asus-nb-wm causes the camera LED to turn and _stay_ on.
+                */
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
+               },
+       },
+       {
+               /* The Asus T200TA has the same issue as the T100TA */
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T200TA"),
+               },
+       },
+       {} /* Terminating entry */
+};
 
 static int __init asus_nb_wmi_init(void)
 {
+       if (dmi_check_system(asus_nb_wmi_blacklist))
+               return -ENODEV;
+
        return asus_wmi_register_driver(&asus_nb_wmi_driver);
 }
 
index b96d172eb2c15e04471cbbe80cd3da17b1c01061..12d5ab7e1f5d8eb3cfdf2c97ea87a003715e6e5a 100644 (file)
@@ -53,7 +53,7 @@ static int uncore_max_entries __read_mostly;
 /* Storage for uncore data for all instances */
 static struct uncore_data *uncore_instances;
 /* Root of the all uncore sysfs kobjs */
-struct kobject *uncore_root_kobj;
+static struct kobject *uncore_root_kobj;
 /* Stores the CPU mask of the target CPUs to use during uncore read/write */
 static cpumask_t uncore_cpu_mask;
 /* CPU online callback register instance */
index d2a5d4c367152553799a3b152f4c7e334bc8f179..7c8bdab078cf5e56ed330055f984e96242475f7f 100644 (file)
@@ -255,7 +255,7 @@ static const struct pmc_bit_map *ext_cnp_pfear_map[] = {
 };
 
 static const struct pmc_bit_map icl_pfear_map[] = {
-       /* Ice Lake generation onwards only */
+       /* Ice Lake and Jasper Lake generation onwards only */
        {"RES_65",              BIT(0)},
        {"RES_66",              BIT(1)},
        {"RES_67",              BIT(2)},
@@ -274,7 +274,7 @@ static const struct pmc_bit_map *ext_icl_pfear_map[] = {
 };
 
 static const struct pmc_bit_map tgl_pfear_map[] = {
-       /* Tiger Lake, Elkhart Lake and Jasper Lake generation onwards only */
+       /* Tiger Lake and Elkhart Lake generation onwards only */
        {"PSF9",                BIT(0)},
        {"RES_66",              BIT(1)},
        {"RES_67",              BIT(2)},
@@ -692,7 +692,6 @@ static void pmc_core_lpm_display(struct pmc_dev *pmcdev, struct device *dev,
        kfree(lpm_regs);
 }
 
-#if IS_ENABLED(CONFIG_DEBUG_FS)
 static bool slps0_dbg_latch;
 
 static inline u8 pmc_core_reg_read_byte(struct pmc_dev *pmcdev, int offset)
@@ -1133,15 +1132,6 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
                                    &pmc_core_substate_l_sts_regs_fops);
        }
 }
-#else
-static inline void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
-{
-}
-
-static inline void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev)
-{
-}
-#endif /* CONFIG_DEBUG_FS */
 
 static const struct x86_cpu_id intel_pmc_core_ids[] = {
        X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L,           &spt_reg_map),
@@ -1156,7 +1146,7 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = {
        X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L,         &tgl_reg_map),
        X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE,           &tgl_reg_map),
        X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT,        &tgl_reg_map),
-       X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L,      &tgl_reg_map),
+       X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L,      &icl_reg_map),
        {}
 };
 
@@ -1260,13 +1250,11 @@ static int pmc_core_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-
 static bool warn_on_s0ix_failures;
 module_param(warn_on_s0ix_failures, bool, 0644);
 MODULE_PARM_DESC(warn_on_s0ix_failures, "Check and warn for S0ix failures");
 
-static int pmc_core_suspend(struct device *dev)
+static __maybe_unused int pmc_core_suspend(struct device *dev)
 {
        struct pmc_dev *pmcdev = dev_get_drvdata(dev);
 
@@ -1318,7 +1306,7 @@ static inline bool pmc_core_is_s0ix_failed(struct pmc_dev *pmcdev)
        return false;
 }
 
-static int pmc_core_resume(struct device *dev)
+static __maybe_unused int pmc_core_resume(struct device *dev)
 {
        struct pmc_dev *pmcdev = dev_get_drvdata(dev);
        const struct pmc_bit_map **maps = pmcdev->map->lpm_sts;
@@ -1348,8 +1336,6 @@ static int pmc_core_resume(struct device *dev)
        return 0;
 }
 
-#endif
-
 static const struct dev_pm_ops pmc_core_pm_ops = {
        SET_LATE_SYSTEM_SLEEP_PM_OPS(pmc_core_suspend, pmc_core_resume)
 };
index 0d50b2402abe5c5d81402b75b4fd2ba16d7be421..5eae55d8022665960ab96ff0fec8e83c680b1a00 100644 (file)
@@ -282,9 +282,7 @@ struct pmc_dev {
        u32 base_addr;
        void __iomem *regbase;
        const struct pmc_reg_map *map;
-#if IS_ENABLED(CONFIG_DEBUG_FS)
        struct dentry *dbgfs_dir;
-#endif /* CONFIG_DEBUG_FS */
        int pmc_xram_read_bit;
        struct mutex lock; /* generic mutex lock for PMC Core */
 
index 946ac2dc08ae7c3e2691b47d5f09594368440144..cc4f9cba68563c137c1c71785e8d6c26479ef2c6 100644 (file)
@@ -522,8 +522,8 @@ static int mshw0011_probe(struct i2c_client *client)
        strlcpy(board_info.type, "MSHW0011-bat0", I2C_NAME_SIZE);
 
        bat0 = i2c_acpi_new_device(dev, 1, &board_info);
-       if (!bat0)
-               return -ENOMEM;
+       if (IS_ERR(bat0))
+               return PTR_ERR(bat0);
 
        data->bat0 = bat0;
        i2c_set_clientdata(bat0, data);
index 8eaadbaf8ffa5281d6db62f9f9152c783e0c69c8..0f704484ae1d6b7a4d6fc7abb08fb3f268d1dce1 100644 (file)
@@ -9548,7 +9548,7 @@ static ssize_t tpacpi_battery_store(int what,
                if (!battery_info.batteries[battery].start_support)
                        return -ENODEV;
                /* valid values are [0, 99] */
-               if (value < 0 || value > 99)
+               if (value > 99)
                        return -EINVAL;
                if (value > battery_info.batteries[battery].charge_stop)
                        return -EINVAL;
index 601cbb282f54317e823096adcaec309b891dbed1..54a2546bb93bf847b06ea5377053076306fab47b 100644 (file)
@@ -23,7 +23,7 @@ struct xiaomi_wmi {
        unsigned int key_code;
 };
 
-int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context)
+static int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context)
 {
        struct xiaomi_wmi *data;
 
@@ -48,7 +48,7 @@ int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context)
        return input_register_device(data->input_dev);
 }
 
-void xiaomi_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy)
+static void xiaomi_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy)
 {
        struct xiaomi_wmi *data;
 
index dfda54cbd86638b18c229b0ea1dcde3bc4b7cda6..52d77db39829295c614434b4a6d64934905c7aa0 100644 (file)
@@ -400,8 +400,8 @@ static int ines_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
        ines_write32(port, ts_stat_rx, ts_stat_rx);
        ines_write32(port, ts_stat_tx, ts_stat_tx);
 
-       port->rxts_enabled = ts_stat_rx == TS_ENABLE ? true : false;
-       port->txts_enabled = ts_stat_tx == TS_ENABLE ? true : false;
+       port->rxts_enabled = ts_stat_rx == TS_ENABLE;
+       port->txts_enabled = ts_stat_tx == TS_ENABLE;
 
        spin_unlock_irqrestore(&port->lock, flags);
 
index c340505150b685a4048bb2a62da5c717e4abbfe3..7486f6e4e613ce15e2df9bdd05503dc47ab0dd93 100644 (file)
@@ -5754,10 +5754,6 @@ static DECLARE_DELAYED_WORK(regulator_init_complete_work,
 
 static int __init regulator_init_complete(void)
 {
-       int delay = driver_deferred_probe_timeout;
-
-       if (delay < 0)
-               delay = 0;
        /*
         * Since DT doesn't provide an idiomatic mechanism for
         * enabling full constraints and since it's much more natural
@@ -5768,17 +5764,18 @@ static int __init regulator_init_complete(void)
                has_full_constraints = true;
 
        /*
-        * If driver_deferred_probe_timeout is set, we punt
-        * completion for that many seconds since systems like
-        * distros will load many drivers from userspace so consumers
-        * might not always be ready yet, this is particularly an
-        * issue with laptops where this might bounce the display off
-        * then on.  Ideally we'd get a notification from userspace
-        * when this happens but we don't so just wait a bit and hope
-        * we waited long enough.  It'd be better if we'd only do
-        * this on systems that need it.
+        * We punt completion for an arbitrary amount of time since
+        * systems like distros will load many drivers from userspace
+        * so consumers might not always be ready yet, this is
+        * particularly an issue with laptops where this might bounce
+        * the display off then on.  Ideally we'd get a notification
+        * from userspace when this happens but we don't so just wait
+        * a bit and hope we waited long enough.  It'd be better if
+        * we'd only do this on systems that need it, and a kernel
+        * command line option might be useful.
         */
-       schedule_delayed_work(&regulator_init_complete_work, delay * HZ);
+       schedule_delayed_work(&regulator_init_complete_work,
+                             msecs_to_jiffies(30000));
 
        return 0;
 }
index deb20096146a44b25b14e333327d5a0e5cb747e8..0066c83636d08bbcf9f60da7cfe511268f5cc430 100644 (file)
@@ -68,7 +68,7 @@ struct mtk_scp {
        wait_queue_head_t ack_wq;
 
        void __iomem *cpu_addr;
-       phys_addr_t phys_addr;
+       dma_addr_t dma_addr;
        size_t dram_size;
 
        struct rproc_subdev *rpmsg_subdev;
index ea3743e7e794f04797f3b3183abb7fadc4f0007b..2bead57c9cf9b1dfa0220c56c8231ab33ea91fb9 100644 (file)
@@ -330,7 +330,7 @@ static void *scp_da_to_va(struct rproc *rproc, u64 da, size_t len)
                if (offset >= 0 && (offset + len) < scp->sram_size)
                        return (void __force *)scp->sram_base + offset;
        } else {
-               offset = da - scp->phys_addr;
+               offset = da - scp->dma_addr;
                if (offset >= 0 && (offset + len) < scp->dram_size)
                        return (void __force *)scp->cpu_addr + offset;
        }
@@ -451,7 +451,7 @@ static int scp_map_memory_region(struct mtk_scp *scp)
        /* Reserved SCP code size */
        scp->dram_size = MAX_CODE_SIZE;
        scp->cpu_addr = dma_alloc_coherent(scp->dev, scp->dram_size,
-                                          &scp->phys_addr, GFP_KERNEL);
+                                          &scp->dma_addr, GFP_KERNEL);
        if (!scp->cpu_addr)
                return -ENOMEM;
 
@@ -461,7 +461,7 @@ static int scp_map_memory_region(struct mtk_scp *scp)
 static void scp_unmap_memory_region(struct mtk_scp *scp)
 {
        dma_free_coherent(scp->dev, scp->dram_size, scp->cpu_addr,
-                         scp->phys_addr);
+                         scp->dma_addr);
        of_reserved_mem_device_release(scp->dev);
 }
 
index ce49c3236ff7c83e00cbb7491c9db320c92cef44..5475d4f808a8e3b3e4945a5255050ff0da5611b5 100644 (file)
@@ -367,7 +367,7 @@ unroll_pd_votes:
        }
 
        return ret;
-};
+}
 
 static void q6v5_pds_disable(struct q6v5 *qproc, struct device **pds,
                             size_t pd_count)
@@ -1527,7 +1527,7 @@ unroll_attach:
                dev_pm_domain_detach(devs[i], false);
 
        return ret;
-};
+}
 
 static void q6v5_pds_detach(struct q6v5 *qproc, struct device **pds,
                            size_t pd_count)
@@ -1675,7 +1675,7 @@ static int q6v5_probe(struct platform_device *pdev)
        ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name",
                                            1, &qproc->hexagon_mdt_image);
        if (ret < 0 && ret != -EINVAL)
-               return ret;
+               goto free_rproc;
 
        platform_set_drvdata(pdev, qproc);
 
@@ -1766,17 +1766,23 @@ static int q6v5_probe(struct platform_device *pdev)
        qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
        if (IS_ERR(qproc->sysmon)) {
                ret = PTR_ERR(qproc->sysmon);
-               goto detach_proxy_pds;
+               goto remove_subdevs;
        }
 
        ret = rproc_add(rproc);
        if (ret)
-               goto detach_proxy_pds;
+               goto remove_sysmon_subdev;
 
        return 0;
 
-detach_proxy_pds:
+remove_sysmon_subdev:
+       qcom_remove_sysmon_subdev(qproc->sysmon);
+remove_subdevs:
        qcom_remove_ipa_notify_subdev(qproc->rproc, &qproc->ipa_notify_subdev);
+       qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
+       qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+       qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+detach_proxy_pds:
        q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
 detach_active_pds:
        q6v5_pds_detach(qproc, qproc->active_pds, qproc->active_pd_count);
@@ -1789,19 +1795,20 @@ free_rproc:
 static int q6v5_remove(struct platform_device *pdev)
 {
        struct q6v5 *qproc = platform_get_drvdata(pdev);
+       struct rproc *rproc = qproc->rproc;
 
-       rproc_del(qproc->rproc);
+       rproc_del(rproc);
 
        qcom_remove_sysmon_subdev(qproc->sysmon);
-       qcom_remove_ipa_notify_subdev(qproc->rproc, &qproc->ipa_notify_subdev);
-       qcom_remove_glink_subdev(qproc->rproc, &qproc->glink_subdev);
-       qcom_remove_smd_subdev(qproc->rproc, &qproc->smd_subdev);
-       qcom_remove_ssr_subdev(qproc->rproc, &qproc->ssr_subdev);
+       qcom_remove_ipa_notify_subdev(rproc, &qproc->ipa_notify_subdev);
+       qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
+       qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+       qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
 
-       q6v5_pds_detach(qproc, qproc->active_pds, qproc->active_pd_count);
        q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
+       q6v5_pds_detach(qproc, qproc->active_pds, qproc->active_pd_count);
 
-       rproc_free(qproc->rproc);
+       rproc_free(rproc);
 
        return 0;
 }
index 7f8536b73295d50d85dae7203e7fea8443a6941b..52b871327b55351baabd81c03a3f5d45580bd7b9 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/remoteproc.h>
+#include <linux/slab.h>
 
 #include "remoteproc_internal.h"
 
index 6a66dbf2df407db0371649d219b5a55247f32a86..0bdd56f02f1834a372b18ee76317fa85f6530cb2 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/regmap.h>
 #include <linux/remoteproc.h>
 #include <linux/reset.h>
+#include <linux/slab.h>
 #include <linux/workqueue.h>
 
 #include "remoteproc_internal.h"
index 232aa4e4013362124ba828c9a08a0fa93c210fb0..83f2b8804ee989df521372b879e709cb9d129cf5 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/platform_device.h>
 #include <linux/remoteproc.h>
 #include <linux/rpmsg/mtk_rpmsg.h>
+#include <linux/slab.h>
 #include <linux/workqueue.h>
 
 #include "rpmsg_internal.h"
index a8682f69effc4d39f39c9f9db297717550db07c5..376f1efbbb86046660d0bcf19a8d97a44f0311f4 100644 (file)
@@ -26,7 +26,6 @@ config DASD
        def_tristate y
        prompt "Support for DASD devices"
        depends on CCW && BLOCK
-       select IOSCHED_DEADLINE
        help
          Enable this option if you want to access DASDs directly utilizing
          S/390s channel subsystem commands. This is necessary for running
index f7689461c242cf3f75c99380fe15e92fb9b30c0f..569966bdc5138eef07d6bfcc90fe2c8d94b352c5 100644 (file)
@@ -6717,17 +6717,17 @@ int qeth_stop(struct net_device *dev)
                unsigned int i;
 
                /* Quiesce the NAPI instances: */
-               qeth_for_each_output_queue(card, queue, i) {
+               qeth_for_each_output_queue(card, queue, i)
                        napi_disable(&queue->napi);
-                       del_timer_sync(&queue->timer);
-               }
 
                /* Stop .ndo_start_xmit, might still access queue->napi. */
                netif_tx_disable(dev);
 
-               /* Queues may get re-allocated, so remove the NAPIs here. */
-               qeth_for_each_output_queue(card, queue, i)
+               qeth_for_each_output_queue(card, queue, i) {
+                       del_timer_sync(&queue->timer);
+                       /* Queues may get re-allocated, so remove the NAPIs. */
                        netif_napi_del(&queue->napi);
+               }
        } else {
                netif_tx_disable(dev);
        }
index 17feff174f574930a096d0101b0cc5affdd981d8..2017c43dac1bcacad82c3b836ae1f97bf67aee34 100644 (file)
@@ -127,7 +127,7 @@ config CHR_DEV_SG
 
          For scanners, look at SANE (<http://www.sane-project.org/>). For CD
          writer software look at Cdrtools
-         (<http://cdrecord.berlios.de/private/cdrecord.html>)
+         (<http://cdrtools.sourceforge.net/>)
          and for burning a "disk at once": CDRDAO
          (<http://cdrdao.sourceforge.net/>). Cdparanoia is a high
          quality digital reader of audio CDs (<http://www.xiph.org/paranoia/>).
index 90a17452a50dc3beabf87ce2334e9c1f2c39a06f..13ed9073fc72fab3cdcb677924609cccc0c30056 100644 (file)
@@ -6,6 +6,7 @@ config SCSI_HISI_SAS
        select SCSI_SAS_LIBSAS
        select BLK_DEV_INTEGRITY
        depends on ATA
+       select SATA_HOST
        help
                This driver supports HiSilicon's SAS HBA, including support based
                on platform device
index 7da9e060b27063b0948b05e9ad836b0581a43c4a..635f6f9cffc4029173af9c2a07a3021cfb1521d3 100644 (file)
@@ -3640,6 +3640,11 @@ static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *tgt)
        struct ibmvfc_host *vhost = tgt->vhost;
        struct ibmvfc_event *evt;
 
+       if (!vhost->logged_in) {
+               ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+               return;
+       }
+
        if (vhost->discovery_threads >= disc_threads)
                return;
 
index 7f66a778320994908bbc101e344b9840895c5e35..59f0f1030c54aaf244c287932a5d29f082e449bd 100644 (file)
@@ -2320,16 +2320,12 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
 static int ibmvscsi_remove(struct vio_dev *vdev)
 {
        struct ibmvscsi_host_data *hostdata = dev_get_drvdata(&vdev->dev);
-       unsigned long flags;
 
        srp_remove_host(hostdata->host);
        scsi_remove_host(hostdata->host);
 
        purge_requests(hostdata, DID_ERROR);
-
-       spin_lock_irqsave(hostdata->host->host_lock, flags);
        release_event_pool(&hostdata->pool, hostdata);
-       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 
        ibmvscsi_release_crq_queue(&hostdata->queue, hostdata,
                                        max_events);
index 97cabd7e001480092fe650acce5e53483cfe0f37..33255968f03a43438d8c511ef04bffa8ace1642d 100644 (file)
@@ -3031,11 +3031,11 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
            test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags))
                msleep(1000);
 
-       qla_nvme_delete(vha);
 
        qla24xx_disable_vp(vha);
        qla2x00_wait_for_sess_deletion(vha);
 
+       qla_nvme_delete(vha);
        vha->flags.delete_progress = 1;
 
        qlt_remove_target(ha, vha);
index f301a8048b2fe2af60ba2af85554aaa564c842be..bf1e98f11990198b4a6a41f28e6fc9f1c30817c4 100644 (file)
@@ -2539,7 +2539,6 @@ ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...)
 {
        va_list va;
        struct va_format vaf;
-       char pbuf[64];
 
        va_start(va, fmt);
 
@@ -2547,6 +2546,8 @@ ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...)
        vaf.va = &va;
 
        if (!ql_mask_match(level)) {
+               char pbuf[64];
+
                if (vha != NULL) {
                        const struct pci_dev *pdev = vha->hw->pdev;
                        /* <module-name> <msg-id>:<host> Message */
index 5b2deaa730bfd6adc344d144eeea4794ce53f619..caa6b840e459463a6cfa2e61745986f224bf7e6c 100644 (file)
@@ -3611,8 +3611,6 @@ qla24xx_detect_sfp(scsi_qla_host_t *vha)
                        ha->lr_distance = LR_DISTANCE_5K;
        }
 
-       if (!vha->flags.init_done)
-               rc = QLA_SUCCESS;
 out:
        ql_dbg(ql_dbg_async, vha, 0x507b,
            "SFP detect: %s-Range SFP %s (nvr=%x ll=%x lr=%x lrd=%x).\n",
index 8d7a905f624713bf576f9b31f67c91c4b7cd341b..8a78d395bbc8f92eeaa33ac8d41bdf3f10373a8a 100644 (file)
@@ -87,7 +87,6 @@ qla24xx_process_abts(struct scsi_qla_host *vha, void *pkt)
        }
 
        /* terminate exchange */
-       memset(rsp_els, 0, sizeof(*rsp_els));
        rsp_els->entry_type = ELS_IOCB_TYPE;
        rsp_els->entry_count = 1;
        rsp_els->nport_handle = ~0;
index 9fd83d1bffe02d1e5d87c0e0d0a66d20f7717025..d6c991bd1bde9bc024c4c907589b756b2b5c7ad5 100644 (file)
@@ -3153,7 +3153,7 @@ qla24xx_abort_command(srb_t *sp)
        ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108c,
            "Entered %s.\n", __func__);
 
-       if (vha->flags.qpairs_available && sp->qpair)
+       if (sp->qpair)
                req = sp->qpair->req;
        else
                return QLA_FUNCTION_FAILED;
@@ -4894,8 +4894,6 @@ qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
                return QLA_MEMORY_ALLOC_FAILED;
        }
 
-       memset(els_cmd_map, 0, ELS_CMD_MAP_SIZE);
-
        els_cmd_map[index] |= 1 << bit;
 
        mcp->mb[0] = MBC_SET_RNID_PARAMS;
index d190db5ea7d9e33eae1ef649982fa49ad26b1aaa..1d9a4866f9a74259381d924b62f52dd91540e738 100644 (file)
@@ -3732,6 +3732,13 @@ qla2x00_remove_one(struct pci_dev *pdev)
        }
        qla2x00_wait_for_hba_ready(base_vha);
 
+       /*
+        * if UNLOADING flag is already set, then continue unload,
+        * where it was set first.
+        */
+       if (test_and_set_bit(UNLOADING, &base_vha->dpc_flags))
+               return;
+
        if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) ||
            IS_QLA28XX(ha)) {
                if (ha->flags.fw_started)
@@ -3750,15 +3757,6 @@ qla2x00_remove_one(struct pci_dev *pdev)
 
        qla2x00_wait_for_sess_deletion(base_vha);
 
-       /*
-        * if UNLOAD flag is already set, then continue unload,
-        * where it was set first.
-        */
-       if (test_bit(UNLOADING, &base_vha->dpc_flags))
-               return;
-
-       set_bit(UNLOADING, &base_vha->dpc_flags);
-
        qla_nvme_delete(base_vha);
 
        dma_free_coherent(&ha->pdev->dev,
@@ -4864,6 +4862,9 @@ qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
        struct qla_work_evt *e;
        uint8_t bail;
 
+       if (test_bit(UNLOADING, &vha->dpc_flags))
+               return NULL;
+
        QLA_VHA_MARK_BUSY(vha, bail);
        if (bail)
                return NULL;
@@ -6628,13 +6629,6 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
        struct pci_dev *pdev = ha->pdev;
        scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
 
-       /*
-        * if UNLOAD flag is already set, then continue unload,
-        * where it was set first.
-        */
-       if (test_bit(UNLOADING, &base_vha->dpc_flags))
-               return;
-
        ql_log(ql_log_warn, base_vha, 0x015b,
            "Disabling adapter.\n");
 
@@ -6645,9 +6639,14 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
                return;
        }
 
-       qla2x00_wait_for_sess_deletion(base_vha);
+       /*
+        * if UNLOADING flag is already set, then continue unload,
+        * where it was set first.
+        */
+       if (test_and_set_bit(UNLOADING, &base_vha->dpc_flags))
+               return;
 
-       set_bit(UNLOADING, &base_vha->dpc_flags);
+       qla2x00_wait_for_sess_deletion(base_vha);
 
        qla2x00_delete_all_vps(ha, base_vha);
 
index 47835c4b4ee05016420f07f0bf63c015879e5009..06c260f6cdae3f43fc8de4ced5d5b98a0d36bac9 100644 (file)
@@ -2284,6 +2284,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
                switch (oldstate) {
                case SDEV_RUNNING:
                case SDEV_CREATED_BLOCK:
+               case SDEV_QUIESCE:
                case SDEV_OFFLINE:
                        break;
                default:
index 4e6af592f018e77b54c81624b8860de3826b594a..20472aaaf630a4627abaa4287dbfe2a384474b49 100644 (file)
@@ -685,8 +685,10 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
        hp->flags = input_size; /* structure abuse ... */
        hp->pack_id = old_hdr.pack_id;
        hp->usr_ptr = NULL;
-       if (copy_from_user(cmnd, buf, cmd_size))
+       if (copy_from_user(cmnd, buf, cmd_size)) {
+               sg_remove_request(sfp, srp);
                return -EFAULT;
+       }
        /*
         * SG_DXFER_TO_FROM_DEV is functionally equivalent to SG_DXFER_FROM_DEV,
         * but is is possible that the app intended SG_DXFER_TO_DEV, because there
@@ -793,8 +795,10 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
                        "sg_common_write:  scsi opcode=0x%02x, cmd_size=%d\n",
                        (int) cmnd[0], (int) hp->cmd_len));
 
-       if (hp->dxfer_len >= SZ_256M)
+       if (hp->dxfer_len >= SZ_256M) {
+               sg_remove_request(sfp, srp);
                return -EINVAL;
+       }
 
        k = sg_start_req(srp, cmnd);
        if (k) {
index cd4f6410e8c2f89cdf94c3f2c1ab356449f7a205..bcdcd3e7d7f12571f68ef453eeb12ca438c0c4f2 100644 (file)
@@ -478,12 +478,18 @@ int dpaa2_io_service_enqueue_multiple_desc_fq(struct dpaa2_io *d,
                                const struct dpaa2_fd *fd,
                                int nb)
 {
-       int i;
-       struct qbman_eq_desc ed[32];
+       struct qbman_eq_desc *ed;
+       int i, ret;
+
+       ed = kcalloc(sizeof(struct qbman_eq_desc), 32, GFP_KERNEL);
+       if (!ed)
+               return -ENOMEM;
 
        d = service_select(d);
-       if (!d)
-               return -ENODEV;
+       if (!d) {
+               ret = -ENODEV;
+               goto out;
+       }
 
        for (i = 0; i < nb; i++) {
                qbman_eq_desc_clear(&ed[i]);
@@ -491,7 +497,10 @@ int dpaa2_io_service_enqueue_multiple_desc_fq(struct dpaa2_io *d,
                qbman_eq_desc_set_fq(&ed[i], fqid[i]);
        }
 
-       return qbman_swp_enqueue_multiple_desc(d->swp, &ed[0], fd, nb);
+       ret = qbman_swp_enqueue_multiple_desc(d->swp, &ed[0], fd, nb);
+out:
+       kfree(ed);
+       return ret;
 }
 EXPORT_SYMBOL(dpaa2_io_service_enqueue_multiple_desc_fq);
 
index d1f49caa5b13779e9e9106f5fa4841f83c5e9be6..804b8ba9bf5c949e9df56aab130e53e2a99f8e94 100644 (file)
@@ -753,7 +753,7 @@ int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s,
        if (!s->eqcr.available) {
                eqcr_ci = s->eqcr.ci;
                p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI_MEMBACK;
-               s->eqcr.ci = __raw_readl(p) & full_mask;
+               s->eqcr.ci = *p & full_mask;
                s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
                                        eqcr_ci, s->eqcr.ci);
                if (!s->eqcr.available) {
@@ -823,7 +823,6 @@ int qbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s,
        const uint32_t *cl;
        uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
        int i, num_enqueued = 0;
-       uint64_t addr_cena;
 
        half_mask = (s->eqcr.pi_ci_mask>>1);
        full_mask = s->eqcr.pi_ci_mask;
@@ -867,7 +866,6 @@ int qbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s,
 
        /* Flush all the cacheline without load/store in between */
        eqcr_pi = s->eqcr.pi;
-       addr_cena = (uint64_t)s->addr_cena;
        for (i = 0; i < num_enqueued; i++)
                eqcr_pi++;
        s->eqcr.pi = eqcr_pi & full_mask;
@@ -901,7 +899,7 @@ int qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s,
        if (!s->eqcr.available) {
                eqcr_ci = s->eqcr.ci;
                p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI_MEMBACK;
-               s->eqcr.ci = __raw_readl(p) & full_mask;
+               s->eqcr.ci = *p & full_mask;
                s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
                                        eqcr_ci, s->eqcr.ci);
                if (!s->eqcr.available)
index 67aa94b2481b273f8c8c31127605f60dfebd162d..d515d2cc20ed13d1afb90b99a4151654909da702 100644 (file)
@@ -21,6 +21,7 @@ config SOC_IMX8M
        bool "i.MX8M SoC family support"
        depends on ARCH_MXC || COMPILE_TEST
        default ARCH_MXC && ARM64
+       select SOC_BUS
        help
          If you say yes here you get support for the NXP i.MX8M family
          support, it will provide the SoC info like SoC family,
index 223f1f9d0922ff281c8ae1b1203a39b7d9f9bb15..646512d7276f4237b9e2b17f822be695f8265aa2 100644 (file)
@@ -19,7 +19,7 @@ config XILINX_VCU
 
 config ZYNQMP_POWER
        bool "Enable Xilinx Zynq MPSoC Power Management driver"
-       depends on PM && ARCH_ZYNQMP
+       depends on PM && ZYNQMP_FIRMWARE
        default y
        select MAILBOX
        select ZYNQMP_IPI_MBOX
@@ -35,7 +35,7 @@ config ZYNQMP_POWER
 config ZYNQMP_PM_DOMAINS
        bool "Enable Zynq MPSoC generic PM domains"
        default y
-       depends on PM && ARCH_ZYNQMP && ZYNQMP_FIRMWARE
+       depends on PM && ZYNQMP_FIRMWARE
        select PM_GENERIC_DOMAINS
        help
          Say yes to enable device power management through PM domains
index 08d1bbbebf2d7b59edc87b8dac466421a171b29f..e84b4fb493d627d5a17f183d99978ce2029fe376 100644 (file)
@@ -2725,8 +2725,10 @@ static int comedi_open(struct inode *inode, struct file *file)
        }
 
        cfp = kzalloc(sizeof(*cfp), GFP_KERNEL);
-       if (!cfp)
+       if (!cfp) {
+               comedi_dev_put(dev);
                return -ENOMEM;
+       }
 
        cfp->dev = dev;
 
index 83026ba63d1cc57a5fb0c727b72c22b2791e4f08..78a7c1b3448ab1088cf959bff6d4df4d85af0417 100644 (file)
@@ -92,6 +92,7 @@ static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
        int ret;
 
        for (i = 0; i < insn->n; i++) {
+               /* FIXME: lo bit 0 chooses voltage output or current output */
                lo = ((data[i] & 0x0f) << 4) | (chan << 1) | 0x01;
                hi = (data[i] & 0xff0) >> 4;
 
@@ -105,6 +106,8 @@ static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
                if (ret)
                        return ret;
 
+               outb(hi, dev->iobase + DT2815_DATA);
+
                devpriv->ao_readback[chan] = data[i];
        }
        return i;
index 46199c8ca441b6579d0330e133cfb9b90ea01f3a..f12f81c8dd2fb68bfd50ea16d79aa6bc84c2f6f6 100644 (file)
@@ -570,13 +570,6 @@ static const struct pci_device_id apex_pci_ids[] = {
        { PCI_DEVICE(APEX_PCI_VENDOR_ID, APEX_PCI_DEVICE_ID) }, { 0 }
 };
 
-static void apex_pci_fixup_class(struct pci_dev *pdev)
-{
-       pdev->class = (PCI_CLASS_SYSTEM_OTHER << 8) | pdev->class;
-}
-DECLARE_PCI_FIXUP_CLASS_HEADER(APEX_PCI_VENDOR_ID, APEX_PCI_DEVICE_ID,
-                              PCI_CLASS_NOT_DEFINED, 8, apex_pci_fixup_class);
-
 static int apex_pci_probe(struct pci_dev *pci_dev,
                          const struct pci_device_id *id)
 {
index 8e0575fcb4c8c72c2efad3bcfe79e880816a94df..67325fbaf7605af34a8fc7a28991e402f73df0a9 100644 (file)
@@ -925,6 +925,10 @@ do_map_region(const struct gasket_dev *gasket_dev, struct vm_area_struct *vma,
                gasket_get_bar_index(gasket_dev,
                                     (vma->vm_pgoff << PAGE_SHIFT) +
                                     driver_desc->legacy_mmap_address_offset);
+
+       if (bar_index < 0)
+               return DO_MAP_REGION_INVALID;
+
        phys_base = gasket_dev->bar_data[bar_index].phys_base + phys_offset;
        while (mapped_bytes < map_length) {
                /*
index a2d67c28f530c8991887a4ea64de2254613b2e79..5f0e089573a29fa972a9a8a9633ad039fc628757 100644 (file)
@@ -228,8 +228,7 @@ int gasket_sysfs_create_entries(struct device *device,
        }
 
        mutex_lock(&mapping->mutex);
-       for (i = 0; strcmp(attrs[i].attr.attr.name, GASKET_ARRAY_END_MARKER);
-               i++) {
+       for (i = 0; attrs[i].attr.attr.name != NULL; i++) {
                if (mapping->attribute_count == GASKET_SYSFS_MAX_NODES) {
                        dev_err(device,
                                "Maximum number of sysfs nodes reached for device\n");
index 1d0eed66a7f49fe2bf6088564cf53e549cd3b3fe..ab5aa351d55500bcbd7b9dfa167e7cad015c660a 100644 (file)
  */
 #define GASKET_SYSFS_MAX_NODES 196
 
-/* End markers for sysfs struct arrays. */
-#define GASKET_ARRAY_END_TOKEN GASKET_RESERVED_ARRAY_END
-#define GASKET_ARRAY_END_MARKER __stringify(GASKET_ARRAY_END_TOKEN)
-
 /*
  * Terminator struct for a gasket_sysfs_attr array. Must be at the end of
  * all gasket_sysfs_attribute arrays.
index 87a6dac4890dc4ffe79d31e222379bfa7846fd35..ab6f39175d992ab07cfb46572e5f2f76f319b5ac 100644 (file)
@@ -30,5 +30,4 @@ Now the TODOs:
 
 Please send any patches to:
 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Wolfram Sang <wsa@the-dreams.de>
 Linux Driver Project Developer List <driverdev-devel@linuxdriverproject.org>
index 41b73f9670e2c82021df995cd5fbbbb609fe1d1b..ac3b188984d0f57db8d6e6a3fe23381bb5077a5f 100644 (file)
@@ -83,9 +83,6 @@ static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr,
        case  VNT_KEY_PAIRWISE:
                key_mode |= mode;
                key_inx = 4;
-               /* Don't save entry for pairwise key for station mode */
-               if (priv->op_mode == NL80211_IFTYPE_STATION)
-                       clear_bit(entry, &priv->key_entry_inuse);
                break;
        default:
                return -EINVAL;
@@ -109,7 +106,6 @@ static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr,
 int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
                 struct ieee80211_vif *vif, struct ieee80211_key_conf *key)
 {
-       struct ieee80211_bss_conf *conf = &vif->bss_conf;
        struct vnt_private *priv = hw->priv;
        u8 *mac_addr = NULL;
        u8 key_dec_mode = 0;
@@ -154,16 +150,12 @@ int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
                return -EOPNOTSUPP;
        }
 
-       if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
+       if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
                vnt_set_keymode(hw, mac_addr, key, VNT_KEY_PAIRWISE,
                                key_dec_mode, true);
-       } else {
-               vnt_set_keymode(hw, mac_addr, key, VNT_KEY_DEFAULTKEY,
+       else
+               vnt_set_keymode(hw, mac_addr, key, VNT_KEY_GROUP_ADDRESS,
                                key_dec_mode, true);
 
-               vnt_set_keymode(hw, (u8 *)conf->bssid, key,
-                               VNT_KEY_GROUP_ADDRESS, key_dec_mode, true);
-       }
-
        return 0;
 }
index 8e7269c87ea96b8a4c073ada02f44ac7b5b2b647..5f78cad3b6476541ba42d7c89ef5fb2f3eff6108 100644 (file)
@@ -625,8 +625,6 @@ static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 
        priv->op_mode = vif->type;
 
-       vnt_set_bss_mode(priv);
-
        /* LED blink on TX */
        vnt_mac_set_led(priv, LEDSTS_STS, LEDSTS_INTER);
 
@@ -713,7 +711,6 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw,
                priv->basic_rates = conf->basic_rates;
 
                vnt_update_top_rates(priv);
-               vnt_set_bss_mode(priv);
 
                dev_dbg(&priv->usb->dev, "basic rates %x\n", conf->basic_rates);
        }
@@ -742,11 +739,14 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw,
                        priv->short_slot_time = false;
 
                vnt_set_short_slot_time(priv);
-               vnt_update_ifs(priv);
                vnt_set_vga_gain_offset(priv, priv->bb_vga[0]);
                vnt_update_pre_ed_threshold(priv, false);
        }
 
+       if (changed & (BSS_CHANGED_BASIC_RATES | BSS_CHANGED_ERP_PREAMBLE |
+                      BSS_CHANGED_ERP_SLOT))
+               vnt_set_bss_mode(priv);
+
        if (changed & BSS_CHANGED_TXPOWER)
                vnt_rf_setpower(priv, priv->current_rate,
                                conf->chandef.chan->hw_value);
@@ -770,12 +770,15 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw,
                        vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL,
                                            TFTCTL_TSFCNTREN);
 
-                       vnt_adjust_tsf(priv, conf->beacon_rate->hw_value,
-                                      conf->sync_tsf, priv->current_tsf);
-
                        vnt_mac_set_beacon_interval(priv, conf->beacon_int);
 
                        vnt_reset_next_tbtt(priv, conf->beacon_int);
+
+                       vnt_adjust_tsf(priv, conf->beacon_rate->hw_value,
+                                      conf->sync_tsf, priv->current_tsf);
+
+                       vnt_update_next_tbtt(priv,
+                                            conf->sync_tsf, conf->beacon_int);
                } else {
                        vnt_clear_current_tsf(priv);
 
@@ -809,15 +812,11 @@ static void vnt_configure(struct ieee80211_hw *hw,
 {
        struct vnt_private *priv = hw->priv;
        u8 rx_mode = 0;
-       int rc;
 
        *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC;
 
-       rc = vnt_control_in(priv, MESSAGE_TYPE_READ, MAC_REG_RCR,
-                           MESSAGE_REQUEST_MACREG, sizeof(u8), &rx_mode);
-
-       if (!rc)
-               rx_mode = RCR_MULTICAST | RCR_BROADCAST;
+       vnt_control_in(priv, MESSAGE_TYPE_READ, MAC_REG_RCR,
+                      MESSAGE_REQUEST_MACREG, sizeof(u8), &rx_mode);
 
        dev_dbg(&priv->usb->dev, "rx mode in = %x\n", rx_mode);
 
@@ -856,8 +855,12 @@ static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        case SET_KEY:
                return vnt_set_keys(hw, sta, vif, key);
        case DISABLE_KEY:
-               if (test_bit(key->hw_key_idx, &priv->key_entry_inuse))
+               if (test_bit(key->hw_key_idx, &priv->key_entry_inuse)) {
                        clear_bit(key->hw_key_idx, &priv->key_entry_inuse);
+
+                       vnt_mac_disable_keyentry(priv, key->hw_key_idx);
+               }
+
        default:
                break;
        }
index eae211e5860f1e16e673224c5f557cca912750c3..91b62c3dff7b8cda86fca34c6dde783106231f36 100644 (file)
@@ -207,7 +207,8 @@ static void vnt_int_process_data(struct vnt_private *priv)
                                priv->wake_up_count =
                                        priv->hw->conf.listen_interval;
 
-                       --priv->wake_up_count;
+                       if (priv->wake_up_count)
+                               --priv->wake_up_count;
 
                        /* Turn on wake up to listen next beacon */
                        if (priv->wake_up_count == 1)
index 6b4b354c88aa09d100b77bc6b1f4cf2dfb0929be..1e031d81e59e871dc96025e9963f3abe9723199d 100644 (file)
@@ -63,7 +63,7 @@ static int fc_get_pr_transport_id(
         * encoded TransportID.
         */
        ptr = &se_nacl->initiatorname[0];
-       for (i = 0; i < 24; ) {
+       for (i = 0; i < 23; ) {
                if (!strncmp(&ptr[i], ":", 1)) {
                        i++;
                        continue;
@@ -341,7 +341,8 @@ static char *iscsi_parse_pr_out_transport_id(
                        *p = tolower(*p);
                        p++;
                }
-       }
+       } else
+               *port_nexus_ptr = NULL;
 
        return &buf[4];
 }
index 51ffd5c002dee2da58281ce0e1c2032dac1ad9e2..1c181d31f4c872d0d18290668842654382c6a593 100644 (file)
@@ -432,7 +432,7 @@ iblock_execute_zero_out(struct block_device *bdev, struct se_cmd *cmd)
                                target_to_linux_sector(dev, cmd->t_task_lba),
                                target_to_linux_sector(dev,
                                        sbc_get_write_same_sectors(cmd)),
-                               GFP_KERNEL, false);
+                               GFP_KERNEL, BLKDEV_ZERO_NOUNMAP);
        if (ret)
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
index 0b9dfa6b17bc70c3302c90776cd220d0bf85dc81..f769bb1e373568e53a4290003876a545922bfced 100644 (file)
@@ -2073,6 +2073,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level)
        mb->cmd_tail = 0;
        mb->cmd_head = 0;
        tcmu_flush_dcache_range(mb, sizeof(*mb));
+       clear_bit(TCMU_DEV_BIT_BROKEN, &udev->flags);
 
        del_timer(&udev->cmd_timer);
 
index 3d084cec136f552a1048df38be78b6c0e6dfb573..50c7534ba31e9ac65b03d55d7c42de93dcec1341 100644 (file)
@@ -182,6 +182,9 @@ static int usb4_switch_op(struct tb_switch *sw, u16 opcode, u8 *status)
                return ret;
 
        ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_26, 1);
+       if (ret)
+               return ret;
+
        if (val & ROUTER_CS_26_ONS)
                return -EOPNOTSUPP;
 
index 31b7e1b0374916744f3ec867c49d07b0d0dc00dd..d1b27b0522a3cde22e9ecb1ebc943a5a743c102f 100644 (file)
@@ -88,7 +88,7 @@ config HVC_DCC
 
 config HVC_RISCV_SBI
        bool "RISC-V SBI console support"
-       depends on RISCV_SBI
+       depends on RISCV_SBI_V01
        select HVC_DRIVER
        help
          This enables support for console output via RISC-V SBI calls, which
index 27284a2dcd2b62395c5b140900ccca85a68ab683..436cc51c92c39765f9e9ba782fabecf62dda4830 100644 (file)
@@ -302,10 +302,6 @@ int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops)
        vtermnos[index] = vtermno;
        cons_ops[index] = ops;
 
-       /* reserve all indices up to and including this index */
-       if (last_hvc < index)
-               last_hvc = index;
-
        /* check if we need to re-register the kernel console */
        hvc_check_console(index);
 
@@ -960,13 +956,22 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
                    cons_ops[i] == hp->ops)
                        break;
 
-       /* no matching slot, just use a counter */
-       if (i >= MAX_NR_HVC_CONSOLES)
-               i = ++last_hvc;
+       if (i >= MAX_NR_HVC_CONSOLES) {
+
+               /* find 'empty' slot for console */
+               for (i = 0; i < MAX_NR_HVC_CONSOLES && vtermnos[i] != -1; i++) {
+               }
+
+               /* no matching slot, just use a counter */
+               if (i == MAX_NR_HVC_CONSOLES)
+                       i = ++last_hvc + MAX_NR_HVC_CONSOLES;
+       }
 
        hp->index = i;
-       cons_ops[i] = ops;
-       vtermnos[i] = vtermno;
+       if (i < MAX_NR_HVC_CONSOLES) {
+               cons_ops[i] = ops;
+               vtermnos[i] = vtermno;
+       }
 
        list_add_tail(&(hp->next), &hvc_structs);
        mutex_unlock(&hvc_structs_mutex);
index fbaa4ec85560e661e22cd25a67169a00f4225ea2..e2138e7d5dc64b8c01deb1d77a9c744edeaffb52 100644 (file)
@@ -632,18 +632,21 @@ init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
        tty_port_init(&info->port);
        info->port.ops = &rocket_port_ops;
        info->flags &= ~ROCKET_MODE_MASK;
-       switch (pc104[board][line]) {
-       case 422:
-               info->flags |= ROCKET_MODE_RS422;
-               break;
-       case 485:
-               info->flags |= ROCKET_MODE_RS485;
-               break;
-       case 232:
-       default:
+       if (board < ARRAY_SIZE(pc104) && line < ARRAY_SIZE(pc104_1))
+               switch (pc104[board][line]) {
+               case 422:
+                       info->flags |= ROCKET_MODE_RS422;
+                       break;
+               case 485:
+                       info->flags |= ROCKET_MODE_RS485;
+                       break;
+               case 232:
+               default:
+                       info->flags |= ROCKET_MODE_RS232;
+                       break;
+               }
+       else
                info->flags |= ROCKET_MODE_RS232;
-               break;
-       }
 
        info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR;
        if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) {
index 0aea76cd67ff2e72aaea9d339180badaa2f39d4b..adf9e80e7dc9e45fa956fe8940f2f5c20709c530 100644 (file)
@@ -86,7 +86,7 @@ config SERIAL_EARLYCON_ARM_SEMIHOST
 
 config SERIAL_EARLYCON_RISCV_SBI
        bool "Early console using RISC-V SBI"
-       depends on RISCV_SBI
+       depends on RISCV_SBI_V01
        select SERIAL_CORE
        select SERIAL_CORE_CONSOLE
        select SERIAL_EARLYCON
index 42c8cc93b603b43aa4a206099dc696889008941d..c149f8c300074b0188f2c24ab047a437007a43f0 100644 (file)
@@ -680,6 +680,12 @@ static int owl_uart_probe(struct platform_device *pdev)
                return PTR_ERR(owl_port->clk);
        }
 
+       ret = clk_prepare_enable(owl_port->clk);
+       if (ret) {
+               dev_err(&pdev->dev, "could not enable clk\n");
+               return ret;
+       }
+
        owl_port->port.dev = &pdev->dev;
        owl_port->port.line = pdev->id;
        owl_port->port.type = PORT_OWL;
@@ -712,6 +718,7 @@ static int owl_uart_remove(struct platform_device *pdev)
 
        uart_remove_one_port(&owl_uart_driver, &owl_port->port);
        owl_uart_ports[pdev->id] = NULL;
+       clk_disable_unprepare(owl_port->clk);
 
        return 0;
 }
index c073aa7001c4fe716a7d4caa7b92c76e7d8c7454..e1179e74a2b89d892f4c8e0edceb3378c6755e5a 100644 (file)
@@ -870,9 +870,16 @@ static void sci_receive_chars(struct uart_port *port)
                                tty_insert_flip_char(tport, c, TTY_NORMAL);
                } else {
                        for (i = 0; i < count; i++) {
-                               char c = serial_port_in(port, SCxRDR);
-
-                               status = serial_port_in(port, SCxSR);
+                               char c;
+
+                               if (port->type == PORT_SCIF ||
+                                   port->type == PORT_HSCIF) {
+                                       status = serial_port_in(port, SCxSR);
+                                       c = serial_port_in(port, SCxRDR);
+                               } else {
+                                       c = serial_port_in(port, SCxRDR);
+                                       status = serial_port_in(port, SCxSR);
+                               }
                                if (uart_handle_sysrq_char(port, c)) {
                                        count--; i--;
                                        continue;
index eafada8fb6fad8755104ffa4fdc7cb40c8cc1d6e..e35073e93a5b4710a56039a3e36ed15a00dc9b90 100644 (file)
@@ -567,6 +567,9 @@ static int hv_probe(struct platform_device *op)
        sunserial_console_match(&sunhv_console, op->dev.of_node,
                                &sunhv_reg, port->line, false);
 
+       /* We need to initialize lock even for non-registered console */
+       spin_lock_init(&port->lock);
+
        err = uart_add_one_port(&sunhv_reg, port);
        if (err)
                goto out_unregister_driver;
index 6b26f767768ebb82c83e04cc436d944e029b8b68..35e9e8faf8de90f927dfc23851e8387337103b9f 100644 (file)
 
 #define CDNS_UART_TTY_NAME     "ttyPS"
 #define CDNS_UART_NAME         "xuartps"
+#define CDNS_UART_MAJOR                0       /* use dynamic node allocation */
+#define CDNS_UART_MINOR                0       /* works best with devtmpfs */
+#define CDNS_UART_NR_PORTS     16
 #define CDNS_UART_FIFO_SIZE    64      /* FIFO size */
 #define CDNS_UART_REGISTER_SPACE       0x1000
 #define TX_TIMEOUT             500000
 
 /* Rx Trigger level */
 static int rx_trigger_level = 56;
-static int uartps_major;
 module_param(rx_trigger_level, uint, 0444);
 MODULE_PARM_DESC(rx_trigger_level, "Rx trigger level, 1-63 bytes");
 
@@ -188,7 +190,6 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255");
  * @pclk:              APB clock
  * @cdns_uart_driver:  Pointer to UART driver
  * @baud:              Current baud rate
- * @id:                        Port ID
  * @clk_rate_change_nb:        Notifier block for clock changes
  * @quirks:            Flags for RXBS support.
  */
@@ -198,7 +199,6 @@ struct cdns_uart {
        struct clk              *pclk;
        struct uart_driver      *cdns_uart_driver;
        unsigned int            baud;
-       int                     id;
        struct notifier_block   clk_rate_change_nb;
        u32                     quirks;
        bool cts_override;
@@ -1133,6 +1133,8 @@ static const struct uart_ops cdns_uart_ops = {
 #endif
 };
 
+static struct uart_driver cdns_uart_uart_driver;
+
 #ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE
 /**
  * cdns_uart_console_putchar - write the character to the FIFO buffer
@@ -1272,6 +1274,16 @@ static int cdns_uart_console_setup(struct console *co, char *options)
 
        return uart_set_options(port, co, baud, parity, bits, flow);
 }
+
+static struct console cdns_uart_console = {
+       .name   = CDNS_UART_TTY_NAME,
+       .write  = cdns_uart_console_write,
+       .device = uart_console_device,
+       .setup  = cdns_uart_console_setup,
+       .flags  = CON_PRINTBUFFER,
+       .index  = -1, /* Specified on the cmdline (e.g. console=ttyPS ) */
+       .data   = &cdns_uart_uart_driver,
+};
 #endif /* CONFIG_SERIAL_XILINX_PS_UART_CONSOLE */
 
 #ifdef CONFIG_PM_SLEEP
@@ -1403,89 +1415,8 @@ static const struct of_device_id cdns_uart_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, cdns_uart_of_match);
 
-/*
- * Maximum number of instances without alias IDs but if there is alias
- * which target "< MAX_UART_INSTANCES" range this ID can't be used.
- */
-#define MAX_UART_INSTANCES     32
-
-/* Stores static aliases list */
-static DECLARE_BITMAP(alias_bitmap, MAX_UART_INSTANCES);
-static int alias_bitmap_initialized;
-
-/* Stores actual bitmap of allocated IDs with alias IDs together */
-static DECLARE_BITMAP(bitmap, MAX_UART_INSTANCES);
-/* Protect bitmap operations to have unique IDs */
-static DEFINE_MUTEX(bitmap_lock);
-
-static int cdns_get_id(struct platform_device *pdev)
-{
-       int id, ret;
-
-       mutex_lock(&bitmap_lock);
-
-       /* Alias list is stable that's why get alias bitmap only once */
-       if (!alias_bitmap_initialized) {
-               ret = of_alias_get_alias_list(cdns_uart_of_match, "serial",
-                                             alias_bitmap, MAX_UART_INSTANCES);
-               if (ret && ret != -EOVERFLOW) {
-                       mutex_unlock(&bitmap_lock);
-                       return ret;
-               }
-
-               alias_bitmap_initialized++;
-       }
-
-       /* Make sure that alias ID is not taken by instance without alias */
-       bitmap_or(bitmap, bitmap, alias_bitmap, MAX_UART_INSTANCES);
-
-       dev_dbg(&pdev->dev, "Alias bitmap: %*pb\n",
-               MAX_UART_INSTANCES, bitmap);
-
-       /* Look for a serialN alias */
-       id = of_alias_get_id(pdev->dev.of_node, "serial");
-       if (id < 0) {
-               dev_warn(&pdev->dev,
-                        "No serial alias passed. Using the first free id\n");
-
-               /*
-                * Start with id 0 and check if there is no serial0 alias
-                * which points to device which is compatible with this driver.
-                * If alias exists then try next free position.
-                */
-               id = 0;
-
-               for (;;) {
-                       dev_info(&pdev->dev, "Checking id %d\n", id);
-                       id = find_next_zero_bit(bitmap, MAX_UART_INSTANCES, id);
-
-                       /* No free empty instance */
-                       if (id == MAX_UART_INSTANCES) {
-                               dev_err(&pdev->dev, "No free ID\n");
-                               mutex_unlock(&bitmap_lock);
-                               return -EINVAL;
-                       }
-
-                       dev_dbg(&pdev->dev, "The empty id is %d\n", id);
-                       /* Check if ID is empty */
-                       if (!test_and_set_bit(id, bitmap)) {
-                               /* Break the loop if bit is taken */
-                               dev_dbg(&pdev->dev,
-                                       "Selected ID %d allocation passed\n",
-                                       id);
-                               break;
-                       }
-                       dev_dbg(&pdev->dev,
-                               "Selected ID %d allocation failed\n", id);
-                       /* if taking bit fails then try next one */
-                       id++;
-               }
-       }
-
-       mutex_unlock(&bitmap_lock);
-
-       return id;
-}
+/* Temporary variable for storing number of instances */
+static int instances;
 
 /**
  * cdns_uart_probe - Platform driver probe
@@ -1495,16 +1426,11 @@ static int cdns_get_id(struct platform_device *pdev)
  */
 static int cdns_uart_probe(struct platform_device *pdev)
 {
-       int rc, irq;
+       int rc, id, irq;
        struct uart_port *port;
        struct resource *res;
        struct cdns_uart *cdns_uart_data;
        const struct of_device_id *match;
-       struct uart_driver *cdns_uart_uart_driver;
-       char *driver_name;
-#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE
-       struct console *cdns_uart_console;
-#endif
 
        cdns_uart_data = devm_kzalloc(&pdev->dev, sizeof(*cdns_uart_data),
                        GFP_KERNEL);
@@ -1514,64 +1440,36 @@ static int cdns_uart_probe(struct platform_device *pdev)
        if (!port)
                return -ENOMEM;
 
-       cdns_uart_uart_driver = devm_kzalloc(&pdev->dev,
-                                            sizeof(*cdns_uart_uart_driver),
-                                            GFP_KERNEL);
-       if (!cdns_uart_uart_driver)
-               return -ENOMEM;
-
-       cdns_uart_data->id = cdns_get_id(pdev);
-       if (cdns_uart_data->id < 0)
-               return cdns_uart_data->id;
+       /* Look for a serialN alias */
+       id = of_alias_get_id(pdev->dev.of_node, "serial");
+       if (id < 0)
+               id = 0;
 
-       /* There is a need to use unique driver name */
-       driver_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s%d",
-                                    CDNS_UART_NAME, cdns_uart_data->id);
-       if (!driver_name) {
-               rc = -ENOMEM;
-               goto err_out_id;
+       if (id >= CDNS_UART_NR_PORTS) {
+               dev_err(&pdev->dev, "Cannot get uart_port structure\n");
+               return -ENODEV;
        }
 
-       cdns_uart_uart_driver->owner = THIS_MODULE;
-       cdns_uart_uart_driver->driver_name = driver_name;
-       cdns_uart_uart_driver->dev_name = CDNS_UART_TTY_NAME;
-       cdns_uart_uart_driver->major = uartps_major;
-       cdns_uart_uart_driver->minor = cdns_uart_data->id;
-       cdns_uart_uart_driver->nr = 1;
-
+       if (!cdns_uart_uart_driver.state) {
+               cdns_uart_uart_driver.owner = THIS_MODULE;
+               cdns_uart_uart_driver.driver_name = CDNS_UART_NAME;
+               cdns_uart_uart_driver.dev_name = CDNS_UART_TTY_NAME;
+               cdns_uart_uart_driver.major = CDNS_UART_MAJOR;
+               cdns_uart_uart_driver.minor = CDNS_UART_MINOR;
+               cdns_uart_uart_driver.nr = CDNS_UART_NR_PORTS;
 #ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE
-       cdns_uart_console = devm_kzalloc(&pdev->dev, sizeof(*cdns_uart_console),
-                                        GFP_KERNEL);
-       if (!cdns_uart_console) {
-               rc = -ENOMEM;
-               goto err_out_id;
-       }
-
-       strncpy(cdns_uart_console->name, CDNS_UART_TTY_NAME,
-               sizeof(cdns_uart_console->name));
-       cdns_uart_console->index = cdns_uart_data->id;
-       cdns_uart_console->write = cdns_uart_console_write;
-       cdns_uart_console->device = uart_console_device;
-       cdns_uart_console->setup = cdns_uart_console_setup;
-       cdns_uart_console->flags = CON_PRINTBUFFER;
-       cdns_uart_console->data = cdns_uart_uart_driver;
-       cdns_uart_uart_driver->cons = cdns_uart_console;
+               cdns_uart_uart_driver.cons = &cdns_uart_console;
+               cdns_uart_console.index = id;
 #endif
 
-       rc = uart_register_driver(cdns_uart_uart_driver);
-       if (rc < 0) {
-               dev_err(&pdev->dev, "Failed to register driver\n");
-               goto err_out_id;
+               rc = uart_register_driver(&cdns_uart_uart_driver);
+               if (rc < 0) {
+                       dev_err(&pdev->dev, "Failed to register driver\n");
+                       return rc;
+               }
        }
 
-       cdns_uart_data->cdns_uart_driver = cdns_uart_uart_driver;
-
-       /*
-        * Setting up proper name_base needs to be done after uart
-        * registration because tty_driver structure is not filled.
-        * name_base is 0 by default.
-        */
-       cdns_uart_uart_driver->tty_driver->name_base = cdns_uart_data->id;
+       cdns_uart_data->cdns_uart_driver = &cdns_uart_uart_driver;
 
        match = of_match_node(cdns_uart_of_match, pdev->dev.of_node);
        if (match && match->data) {
@@ -1649,6 +1547,7 @@ static int cdns_uart_probe(struct platform_device *pdev)
        port->ops       = &cdns_uart_ops;
        port->fifosize  = CDNS_UART_FIFO_SIZE;
        port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_XILINX_PS_UART_CONSOLE);
+       port->line      = id;
 
        /*
         * Register the port.
@@ -1680,7 +1579,7 @@ static int cdns_uart_probe(struct platform_device *pdev)
                console_port = port;
 #endif
 
-       rc = uart_add_one_port(cdns_uart_uart_driver, port);
+       rc = uart_add_one_port(&cdns_uart_uart_driver, port);
        if (rc) {
                dev_err(&pdev->dev,
                        "uart_add_one_port() failed; err=%i\n", rc);
@@ -1690,13 +1589,15 @@ static int cdns_uart_probe(struct platform_device *pdev)
 #ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE
        /* This is not port which is used for console that's why clean it up */
        if (console_port == port &&
-           !(cdns_uart_uart_driver->cons->flags & CON_ENABLED))
+           !(cdns_uart_uart_driver.cons->flags & CON_ENABLED))
                console_port = NULL;
 #endif
 
-       uartps_major = cdns_uart_uart_driver->tty_driver->major;
        cdns_uart_data->cts_override = of_property_read_bool(pdev->dev.of_node,
                                                             "cts-override");
+
+       instances++;
+
        return 0;
 
 err_out_pm_disable:
@@ -1712,12 +1613,8 @@ err_out_clk_disable:
 err_out_clk_dis_pclk:
        clk_disable_unprepare(cdns_uart_data->pclk);
 err_out_unregister_driver:
-       uart_unregister_driver(cdns_uart_data->cdns_uart_driver);
-err_out_id:
-       mutex_lock(&bitmap_lock);
-       if (cdns_uart_data->id < MAX_UART_INSTANCES)
-               clear_bit(cdns_uart_data->id, bitmap);
-       mutex_unlock(&bitmap_lock);
+       if (!instances)
+               uart_unregister_driver(cdns_uart_data->cdns_uart_driver);
        return rc;
 }
 
@@ -1740,10 +1637,6 @@ static int cdns_uart_remove(struct platform_device *pdev)
 #endif
        rc = uart_remove_one_port(cdns_uart_data->cdns_uart_driver, port);
        port->mapbase = 0;
-       mutex_lock(&bitmap_lock);
-       if (cdns_uart_data->id < MAX_UART_INSTANCES)
-               clear_bit(cdns_uart_data->id, bitmap);
-       mutex_unlock(&bitmap_lock);
        clk_disable_unprepare(cdns_uart_data->uartclk);
        clk_disable_unprepare(cdns_uart_data->pclk);
        pm_runtime_disable(&pdev->dev);
@@ -1756,13 +1649,8 @@ static int cdns_uart_remove(struct platform_device *pdev)
                console_port = NULL;
 #endif
 
-       /* If this is last instance major number should be initialized */
-       mutex_lock(&bitmap_lock);
-       if (bitmap_empty(bitmap, MAX_UART_INSTANCES))
-               uartps_major = 0;
-       mutex_unlock(&bitmap_lock);
-
-       uart_unregister_driver(cdns_uart_data->cdns_uart_driver);
+       if (!--instances)
+               uart_unregister_driver(cdns_uart_data->cdns_uart_driver);
        return rc;
 }
 
index 5e0d0813da5570f78f4ef247fe0977374b6770bc..0dc3878794fd021a60c434d36792f022073b8759 100644 (file)
@@ -74,6 +74,7 @@ int sysrq_mask(void)
                return 1;
        return sysrq_enabled;
 }
+EXPORT_SYMBOL_GPL(sysrq_mask);
 
 /*
  * A value of 1 means 'all', other nonzero values are an op mask:
@@ -1058,6 +1059,7 @@ int sysrq_toggle_support(int enable_mask)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(sysrq_toggle_support);
 
 static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
                                 struct sysrq_key_op *remove_op_p)
index 309a39197be0a0199929474901deb36ada29ad34..48a8199f7845dff3d4cefd892db27257962d18a6 100644 (file)
@@ -81,6 +81,7 @@
 #include <linux/errno.h>
 #include <linux/kd.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <linux/major.h>
 #include <linux/mm.h>
 #include <linux/console.h>
@@ -350,7 +351,7 @@ static struct uni_screen *vc_uniscr_alloc(unsigned int cols, unsigned int rows)
        /* allocate everything in one go */
        memsize = cols * rows * sizeof(char32_t);
        memsize += rows * sizeof(char32_t *);
-       p = kmalloc(memsize, GFP_KERNEL);
+       p = vmalloc(memsize);
        if (!p)
                return NULL;
 
@@ -364,9 +365,14 @@ static struct uni_screen *vc_uniscr_alloc(unsigned int cols, unsigned int rows)
        return uniscr;
 }
 
+static void vc_uniscr_free(struct uni_screen *uniscr)
+{
+       vfree(uniscr);
+}
+
 static void vc_uniscr_set(struct vc_data *vc, struct uni_screen *new_uniscr)
 {
-       kfree(vc->vc_uni_screen);
+       vc_uniscr_free(vc->vc_uni_screen);
        vc->vc_uni_screen = new_uniscr;
 }
 
@@ -1206,7 +1212,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
        if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
                return 0;
 
-       if (new_screen_size > (4 << 20))
+       if (new_screen_size > KMALLOC_MAX_SIZE)
                return -EINVAL;
        newscreen = kzalloc(new_screen_size, GFP_USER);
        if (!newscreen)
@@ -1229,7 +1235,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
        err = resize_screen(vc, new_cols, new_rows, user);
        if (err) {
                kfree(newscreen);
-               kfree(new_uniscr);
+               vc_uniscr_free(new_uniscr);
                return err;
        }
 
index af648ba6544d840c1fd2712f7332582c8a6f65b8..46105457e1caaee8aa723729a9f3b070caad62d5 100644 (file)
@@ -114,7 +114,7 @@ static int ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
                        hw_write_id_reg(ci, HS_PHY_GENCONFIG_2,
                                        HS_PHY_ULPI_TX_PKT_EN_CLR_FIX, 0);
 
-               if (!IS_ERR(ci->platdata->vbus_extcon.edev)) {
+               if (!IS_ERR(ci->platdata->vbus_extcon.edev) || ci->role_switch) {
                        hw_write_id_reg(ci, HS_PHY_GENCONFIG_2,
                                        HS_PHY_SESS_VLD_CTRL_EN,
                                        HS_PHY_SESS_VLD_CTRL_EN);
index 84d6f7df09a4ef453dd0ece34aaaafd32ab584bb..ded8d93834ca739bc11f7ff4e9f5d6c5c01e3f58 100644 (file)
@@ -412,9 +412,12 @@ static void acm_ctrl_irq(struct urb *urb)
 
 exit:
        retval = usb_submit_urb(urb, GFP_ATOMIC);
-       if (retval && retval != -EPERM)
+       if (retval && retval != -EPERM && retval != -ENODEV)
                dev_err(&acm->control->dev,
                        "%s - usb_submit_urb failed: %d\n", __func__, retval);
+       else
+               dev_vdbg(&acm->control->dev,
+                       "control resubmission terminated %d\n", retval);
 }
 
 static int acm_submit_read_urb(struct acm *acm, int index, gfp_t mem_flags)
@@ -430,6 +433,8 @@ static int acm_submit_read_urb(struct acm *acm, int index, gfp_t mem_flags)
                        dev_err(&acm->data->dev,
                                "urb %d failed submission with %d\n",
                                index, res);
+               } else {
+                       dev_vdbg(&acm->data->dev, "intended failure %d\n", res);
                }
                set_bit(index, &acm->read_urbs_free);
                return res;
@@ -471,6 +476,7 @@ static void acm_read_bulk_callback(struct urb *urb)
        int status = urb->status;
        bool stopped = false;
        bool stalled = false;
+       bool cooldown = false;
 
        dev_vdbg(&acm->data->dev, "got urb %d, len %d, status %d\n",
                rb->index, urb->actual_length, status);
@@ -497,6 +503,14 @@ static void acm_read_bulk_callback(struct urb *urb)
                        __func__, status);
                stopped = true;
                break;
+       case -EOVERFLOW:
+       case -EPROTO:
+               dev_dbg(&acm->data->dev,
+                       "%s - cooling babbling device\n", __func__);
+               usb_mark_last_busy(acm->dev);
+               set_bit(rb->index, &acm->urbs_in_error_delay);
+               cooldown = true;
+               break;
        default:
                dev_dbg(&acm->data->dev,
                        "%s - nonzero urb status received: %d\n",
@@ -518,9 +532,11 @@ static void acm_read_bulk_callback(struct urb *urb)
         */
        smp_mb__after_atomic();
 
-       if (stopped || stalled) {
+       if (stopped || stalled || cooldown) {
                if (stalled)
                        schedule_work(&acm->work);
+               else if (cooldown)
+                       schedule_delayed_work(&acm->dwork, HZ / 2);
                return;
        }
 
@@ -557,14 +573,20 @@ static void acm_softint(struct work_struct *work)
        struct acm *acm = container_of(work, struct acm, work);
 
        if (test_bit(EVENT_RX_STALL, &acm->flags)) {
-               if (!(usb_autopm_get_interface(acm->data))) {
+               smp_mb(); /* against acm_suspend() */
+               if (!acm->susp_count) {
                        for (i = 0; i < acm->rx_buflimit; i++)
                                usb_kill_urb(acm->read_urbs[i]);
                        usb_clear_halt(acm->dev, acm->in);
                        acm_submit_read_urbs(acm, GFP_KERNEL);
-                       usb_autopm_put_interface(acm->data);
+                       clear_bit(EVENT_RX_STALL, &acm->flags);
                }
-               clear_bit(EVENT_RX_STALL, &acm->flags);
+       }
+
+       if (test_and_clear_bit(ACM_ERROR_DELAY, &acm->flags)) {
+               for (i = 0; i < ACM_NR; i++) 
+                       if (test_and_clear_bit(i, &acm->urbs_in_error_delay))
+                                       acm_submit_read_urb(acm, i, GFP_NOIO);
        }
 
        if (test_and_clear_bit(EVENT_TTY_WAKEUP, &acm->flags))
@@ -1333,6 +1355,7 @@ made_compressed_probe:
        acm->readsize = readsize;
        acm->rx_buflimit = num_rx_buf;
        INIT_WORK(&acm->work, acm_softint);
+       INIT_DELAYED_WORK(&acm->dwork, acm_softint);
        init_waitqueue_head(&acm->wioctl);
        spin_lock_init(&acm->write_lock);
        spin_lock_init(&acm->read_lock);
@@ -1542,6 +1565,7 @@ static void acm_disconnect(struct usb_interface *intf)
 
        acm_kill_urbs(acm);
        cancel_work_sync(&acm->work);
+       cancel_delayed_work_sync(&acm->dwork);
 
        tty_unregister_device(acm_tty_driver, acm->minor);
 
@@ -1584,6 +1608,8 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
 
        acm_kill_urbs(acm);
        cancel_work_sync(&acm->work);
+       cancel_delayed_work_sync(&acm->dwork);
+       acm->urbs_in_error_delay = 0;
 
        return 0;
 }
index ca1c026382c2e1a98a330cde2043dee308d76aad..cd5e9d8ab237588bb2aa9cd615b9b1356b59e1cc 100644 (file)
@@ -109,8 +109,11 @@ struct acm {
 #              define EVENT_TTY_WAKEUP 0
 #              define EVENT_RX_STALL   1
 #              define ACM_THROTTLED    2
+#              define ACM_ERROR_DELAY  3
+       unsigned long urbs_in_error_delay;              /* these need to be restarted after a delay */
        struct usb_cdc_line_coding line;                /* bits, stop, parity */
-       struct work_struct work;                        /* work queue entry for line discipline waking up */
+       struct work_struct work;                        /* work queue entry for various purposes*/
+       struct delayed_work dwork;                      /* for cool downs needed in error recovery */
        unsigned int ctrlin;                            /* input control lines (DCD, DSR, RI, break, overruns) */
        unsigned int ctrlout;                           /* output control lines (DTR, RTS) */
        struct async_icount iocount;                    /* counters for control line changes */
index 6833c918abcee7b46bf076f70d6fcce8a740ba7c..b9db9812d6c5e1764d73c0a1bd0145f0b3a878fc 100644 (file)
@@ -217,6 +217,7 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct usb_memory *usbm = NULL;
        struct usb_dev_state *ps = file->private_data;
+       struct usb_hcd *hcd = bus_to_hcd(ps->dev->bus);
        size_t size = vma->vm_end - vma->vm_start;
        void *mem;
        unsigned long flags;
@@ -250,9 +251,7 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma)
        usbm->vma_use_count = 1;
        INIT_LIST_HEAD(&usbm->memlist);
 
-       if (remap_pfn_range(vma, vma->vm_start,
-                       virt_to_phys(usbm->mem) >> PAGE_SHIFT,
-                       size, vma->vm_page_prot) < 0) {
+       if (dma_mmap_coherent(hcd->self.sysdev, vma, mem, dma_handle, size)) {
                dec_usb_memory_use_count(usbm, &usbm->vma_use_count);
                return -EAGAIN;
        }
index 54cd8ef795ec042027a19e30ef754309adcf2329..2b6565c06c237d43f22493a43be39272f0355aef 100644 (file)
@@ -1223,6 +1223,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
 #ifdef CONFIG_PM
                        udev->reset_resume = 1;
 #endif
+                       /* Don't set the change_bits when the device
+                        * was powered off.
+                        */
+                       if (test_bit(port1, hub->power_bits))
+                               set_bit(port1, hub->change_bits);
 
                } else {
                        /* The power session is gone; tell hub_wq */
@@ -2723,13 +2728,11 @@ static bool use_new_scheme(struct usb_device *udev, int retry,
 {
        int old_scheme_first_port =
                port_dev->quirks & USB_PORT_QUIRK_OLD_SCHEME;
-       int quick_enumeration = (udev->speed == USB_SPEED_HIGH);
 
        if (udev->speed >= USB_SPEED_SUPER)
                return false;
 
-       return USE_NEW_SCHEME(retry, old_scheme_first_port || old_scheme_first
-                             || quick_enumeration);
+       return USE_NEW_SCHEME(retry, old_scheme_first_port || old_scheme_first);
 }
 
 /* Is a USB 3.0 port in the Inactive or Compliance Mode state?
@@ -3088,6 +3091,15 @@ static int check_port_resume_type(struct usb_device *udev,
                if (portchange & USB_PORT_STAT_C_ENABLE)
                        usb_clear_port_feature(hub->hdev, port1,
                                        USB_PORT_FEAT_C_ENABLE);
+
+               /*
+                * Whatever made this reset-resume necessary may have
+                * turned on the port1 bit in hub->change_bits.  But after
+                * a successful reset-resume we want the bit to be clear;
+                * if it was on it would indicate that something happened
+                * following the reset-resume.
+                */
+               clear_bit(port1, hub->change_bits);
        }
 
        return status;
index d5f834f16993258a4ad715224e54543510c51b0c..6197938dcc2d8f104efbd8e923bbc6e3d0b94c7b 100644 (file)
@@ -589,12 +589,13 @@ void usb_sg_cancel(struct usb_sg_request *io)
        int i, retval;
 
        spin_lock_irqsave(&io->lock, flags);
-       if (io->status) {
+       if (io->status || io->count == 0) {
                spin_unlock_irqrestore(&io->lock, flags);
                return;
        }
        /* shut everything down */
        io->status = -ECONNRESET;
+       io->count++;            /* Keep the request alive until we're done */
        spin_unlock_irqrestore(&io->lock, flags);
 
        for (i = io->entries - 1; i >= 0; --i) {
@@ -608,6 +609,12 @@ void usb_sg_cancel(struct usb_sg_request *io)
                        dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
                                 __func__, retval);
        }
+
+       spin_lock_irqsave(&io->lock, flags);
+       io->count--;
+       if (!io->count)
+               complete(&io->complete);
+       spin_unlock_irqrestore(&io->lock, flags);
 }
 EXPORT_SYMBOL_GPL(usb_sg_cancel);
 
@@ -1137,11 +1144,11 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr,
 
        if (usb_endpoint_out(epaddr)) {
                ep = dev->ep_out[epnum];
-               if (reset_hardware)
+               if (reset_hardware && epnum != 0)
                        dev->ep_out[epnum] = NULL;
        } else {
                ep = dev->ep_in[epnum];
-               if (reset_hardware)
+               if (reset_hardware && epnum != 0)
                        dev->ep_in[epnum] = NULL;
        }
        if (ep) {
index da30b5664ff3d5da22c5219159545e9faa72fdca..3e8efe759c3e69a8f8c29f5cafe8c0a6b1cca6fc 100644 (file)
@@ -430,6 +430,10 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Corsair K70 LUX */
        { USB_DEVICE(0x1b1c, 0x1b36), .driver_info = USB_QUIRK_DELAY_INIT },
 
+       /* Corsair K70 RGB RAPDIFIRE */
+       { USB_DEVICE(0x1b1c, 0x1b38), .driver_info = USB_QUIRK_DELAY_INIT |
+         USB_QUIRK_DELAY_CTRL_MSG },
+
        /* MIDI keyboard WORLDE MINI */
        { USB_DEVICE(0x1c75, 0x0204), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
index 6846eb0cba135236768d559277b9970731b09dc8..4c171a8e215f685b87110adaa91b0d98d0050501 100644 (file)
 
 /* Global TX Fifo Size Register */
 #define DWC31_GTXFIFOSIZ_TXFRAMNUM     BIT(15)         /* DWC_usb31 only */
-#define DWC31_GTXFIFOSIZ_TXFDEF(n)     ((n) & 0x7fff)  /* DWC_usb31 only */
-#define DWC3_GTXFIFOSIZ_TXFDEF(n)      ((n) & 0xffff)
+#define DWC31_GTXFIFOSIZ_TXFDEP(n)     ((n) & 0x7fff)  /* DWC_usb31 only */
+#define DWC3_GTXFIFOSIZ_TXFDEP(n)      ((n) & 0xffff)
 #define DWC3_GTXFIFOSIZ_TXFSTADDR(n)   ((n) & 0xffff0000)
 
+/* Global RX Fifo Size Register */
+#define DWC31_GRXFIFOSIZ_RXFDEP(n)     ((n) & 0x7fff)  /* DWC_usb31 only */
+#define DWC3_GRXFIFOSIZ_RXFDEP(n)      ((n) & 0xffff)
+
 /* Global Event Size Registers */
 #define DWC3_GEVNTSIZ_INTMASK          BIT(31)
 #define DWC3_GEVNTSIZ_SIZE(n)          ((n) & 0xffff)
index 4d3c79d90a6e4a420cc079dc62e2a25a49f1c705..00746c2848c060fd1eaa66b9c95612ffe74a9cfd 100644 (file)
@@ -1728,7 +1728,6 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc)
        u32                     reg;
 
        u8                      link_state;
-       u8                      speed;
 
        /*
         * According to the Databook Remote wakeup request should
@@ -1738,16 +1737,13 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc)
         */
        reg = dwc3_readl(dwc->regs, DWC3_DSTS);
 
-       speed = reg & DWC3_DSTS_CONNECTSPD;
-       if ((speed == DWC3_DSTS_SUPERSPEED) ||
-           (speed == DWC3_DSTS_SUPERSPEED_PLUS))
-               return 0;
-
        link_state = DWC3_DSTS_USBLNKST(reg);
 
        switch (link_state) {
+       case DWC3_LINK_STATE_RESET:
        case DWC3_LINK_STATE_RX_DET:    /* in HS, means Early Suspend */
        case DWC3_LINK_STATE_U3:        /* in HS, means SUSPEND */
+       case DWC3_LINK_STATE_RESUME:
                break;
        default:
                return -EINVAL;
@@ -2227,7 +2223,6 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
 {
        struct dwc3 *dwc = dep->dwc;
        int mdwidth;
-       int kbytes;
        int size;
 
        mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);
@@ -2236,24 +2231,24 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
 
        size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(dep->number >> 1));
        if (dwc3_is_usb31(dwc))
-               size = DWC31_GTXFIFOSIZ_TXFDEF(size);
+               size = DWC31_GTXFIFOSIZ_TXFDEP(size);
        else
-               size = DWC3_GTXFIFOSIZ_TXFDEF(size);
+               size = DWC3_GTXFIFOSIZ_TXFDEP(size);
 
        /* FIFO Depth is in MDWDITH bytes. Multiply */
        size *= mdwidth;
 
-       kbytes = size / 1024;
-       if (kbytes == 0)
-               kbytes = 1;
-
        /*
-        * FIFO sizes account an extra MDWIDTH * (kbytes + 1) bytes for
-        * internal overhead. We don't really know how these are used,
-        * but documentation say it exists.
+        * To meet performance requirement, a minimum TxFIFO size of 3x
+        * MaxPacketSize is recommended for endpoints that support burst and a
+        * minimum TxFIFO size of 2x MaxPacketSize for endpoints that don't
+        * support burst. Use those numbers and we can calculate the max packet
+        * limit as below.
         */
-       size -= mdwidth * (kbytes + 1);
-       size /= kbytes;
+       if (dwc->maximum_speed >= USB_SPEED_SUPER)
+               size /= 3;
+       else
+               size /= 2;
 
        usb_ep_set_maxpacket_limit(&dep->endpoint, size);
 
@@ -2271,8 +2266,39 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
 static int dwc3_gadget_init_out_endpoint(struct dwc3_ep *dep)
 {
        struct dwc3 *dwc = dep->dwc;
+       int mdwidth;
+       int size;
+
+       mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);
 
-       usb_ep_set_maxpacket_limit(&dep->endpoint, 1024);
+       /* MDWIDTH is represented in bits, convert to bytes */
+       mdwidth /= 8;
+
+       /* All OUT endpoints share a single RxFIFO space */
+       size = dwc3_readl(dwc->regs, DWC3_GRXFIFOSIZ(0));
+       if (dwc3_is_usb31(dwc))
+               size = DWC31_GRXFIFOSIZ_RXFDEP(size);
+       else
+               size = DWC3_GRXFIFOSIZ_RXFDEP(size);
+
+       /* FIFO depth is in MDWDITH bytes */
+       size *= mdwidth;
+
+       /*
+        * To meet performance requirement, a minimum recommended RxFIFO size
+        * is defined as follow:
+        * RxFIFO size >= (3 x MaxPacketSize) +
+        * (3 x 8 bytes setup packets size) + (16 bytes clock crossing margin)
+        *
+        * Then calculate the max packet limit as below.
+        */
+       size -= (3 * 8) + 16;
+       if (size < 0)
+               size = 0;
+       else
+               size /= 3;
+
+       usb_ep_set_maxpacket_limit(&dep->endpoint, size);
        dep->endpoint.max_streams = 15;
        dep->endpoint.ops = &dwc3_gadget_ep_ops;
        list_add_tail(&dep->endpoint.ep_list,
@@ -2484,14 +2510,7 @@ static int dwc3_gadget_ep_reclaim_trb_linear(struct dwc3_ep *dep,
 
 static bool dwc3_gadget_ep_request_completed(struct dwc3_request *req)
 {
-       /*
-        * For OUT direction, host may send less than the setup
-        * length. Return true for all OUT requests.
-        */
-       if (!req->direction)
-               return true;
-
-       return req->request.actual == req->request.length;
+       return req->num_pending_sgs == 0;
 }
 
 static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
@@ -2515,8 +2534,7 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
 
        req->request.actual = req->request.length - req->remaining;
 
-       if (!dwc3_gadget_ep_request_completed(req) ||
-                       req->num_pending_sgs) {
+       if (!dwc3_gadget_ep_request_completed(req)) {
                __dwc3_gadget_kick_transfer(dep);
                goto out;
        }
index 971c6b92484add56e477f22f600c7aa974bde664..171280c8022849c898b75df2280b33924572b1f1 100644 (file)
@@ -728,19 +728,19 @@ static void xdbc_handle_tx_event(struct xdbc_trb *evt_trb)
        case COMP_USB_TRANSACTION_ERROR:
        case COMP_STALL_ERROR:
        default:
-               if (ep_id == XDBC_EPID_OUT)
+               if (ep_id == XDBC_EPID_OUT || ep_id == XDBC_EPID_OUT_INTEL)
                        xdbc.flags |= XDBC_FLAGS_OUT_STALL;
-               if (ep_id == XDBC_EPID_IN)
+               if (ep_id == XDBC_EPID_IN || ep_id == XDBC_EPID_IN_INTEL)
                        xdbc.flags |= XDBC_FLAGS_IN_STALL;
 
                xdbc_trace("endpoint %d stalled\n", ep_id);
                break;
        }
 
-       if (ep_id == XDBC_EPID_IN) {
+       if (ep_id == XDBC_EPID_IN || ep_id == XDBC_EPID_IN_INTEL) {
                xdbc.flags &= ~XDBC_FLAGS_IN_PROCESS;
                xdbc_bulk_transfer(NULL, XDBC_MAX_PACKET, true);
-       } else if (ep_id == XDBC_EPID_OUT) {
+       } else if (ep_id == XDBC_EPID_OUT || ep_id == XDBC_EPID_OUT_INTEL) {
                xdbc.flags &= ~XDBC_FLAGS_OUT_PROCESS;
        } else {
                xdbc_trace("invalid endpoint id %d\n", ep_id);
index 673686eeddd74e71c828ba5efc9970bdcc4dea25..6e2b7266a695255236e58b00d388e6673bcbd4d6 100644 (file)
@@ -120,8 +120,22 @@ struct xdbc_ring {
        u32                     cycle_state;
 };
 
-#define XDBC_EPID_OUT          2
-#define XDBC_EPID_IN           3
+/*
+ * These are the "Endpoint ID" (also known as "Context Index") values for the
+ * OUT Transfer Ring and the IN Transfer Ring of a Debug Capability Context data
+ * structure.
+ * According to the "eXtensible Host Controller Interface for Universal Serial
+ * Bus (xHCI)" specification, section "7.6.3.2 Endpoint Contexts and Transfer
+ * Rings", these should be 0 and 1, and those are the values AMD machines give
+ * you; but Intel machines seem to use the formula from section "4.5.1 Device
+ * Context Index", which is supposed to be used for the Device Context only.
+ * Luckily the values from Intel don't overlap with those from AMD, so we can
+ * just test for both.
+ */
+#define XDBC_EPID_OUT          0
+#define XDBC_EPID_IN           1
+#define XDBC_EPID_OUT_INTEL    2
+#define XDBC_EPID_IN_INTEL     3
 
 struct xdbc_state {
        u16                     vendor;
index c81023b195c3cf34eee295a2723b77fc96a45eb9..10f01f974f67e071031b7ac4976d669b393d8f53 100644 (file)
@@ -1813,6 +1813,10 @@ static void ffs_data_reset(struct ffs_data *ffs)
        ffs->state = FFS_READ_DESCRIPTORS;
        ffs->setup_state = FFS_NO_SETUP;
        ffs->flags = 0;
+
+       ffs->ms_os_descs_ext_prop_count = 0;
+       ffs->ms_os_descs_ext_prop_name_len = 0;
+       ffs->ms_os_descs_ext_prop_data_len = 0;
 }
 
 
index 76406343fbe577d2d8e9fafe03c72a27dba8a051..ca7d95bf7397e15364206cc473b712a92e7dd862 100644 (file)
@@ -81,6 +81,7 @@ static int raw_event_queue_add(struct raw_event_queue *queue,
 static struct usb_raw_event *raw_event_queue_fetch(
                                struct raw_event_queue *queue)
 {
+       int ret;
        unsigned long flags;
        struct usb_raw_event *event;
 
@@ -89,11 +90,18 @@ static struct usb_raw_event *raw_event_queue_fetch(
         * there's at least one event queued by decrementing the semaphore,
         * and then take the lock to protect queue struct fields.
         */
-       if (down_interruptible(&queue->sema))
-               return NULL;
+       ret = down_interruptible(&queue->sema);
+       if (ret)
+               return ERR_PTR(ret);
        spin_lock_irqsave(&queue->lock, flags);
-       if (WARN_ON(!queue->size))
-               return NULL;
+       /*
+        * queue->size must have the same value as queue->sema counter (before
+        * the down_interruptible() call above), so this check is a fail-safe.
+        */
+       if (WARN_ON(!queue->size)) {
+               spin_unlock_irqrestore(&queue->lock, flags);
+               return ERR_PTR(-ENODEV);
+       }
        event = queue->events[0];
        queue->size--;
        memmove(&queue->events[0], &queue->events[1],
@@ -392,9 +400,8 @@ static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
        char *udc_device_name;
        unsigned long flags;
 
-       ret = copy_from_user(&arg, (void __user *)value, sizeof(arg));
-       if (ret)
-               return ret;
+       if (copy_from_user(&arg, (void __user *)value, sizeof(arg)))
+               return -EFAULT;
 
        switch (arg.speed) {
        case USB_SPEED_UNKNOWN:
@@ -501,15 +508,13 @@ out_unlock:
 
 static int raw_ioctl_event_fetch(struct raw_dev *dev, unsigned long value)
 {
-       int ret = 0;
        struct usb_raw_event arg;
        unsigned long flags;
        struct usb_raw_event *event;
        uint32_t length;
 
-       ret = copy_from_user(&arg, (void __user *)value, sizeof(arg));
-       if (ret)
-               return ret;
+       if (copy_from_user(&arg, (void __user *)value, sizeof(arg)))
+               return -EFAULT;
 
        spin_lock_irqsave(&dev->lock, flags);
        if (dev->state != STATE_DEV_RUNNING) {
@@ -525,25 +530,31 @@ static int raw_ioctl_event_fetch(struct raw_dev *dev, unsigned long value)
        spin_unlock_irqrestore(&dev->lock, flags);
 
        event = raw_event_queue_fetch(&dev->queue);
-       if (!event) {
+       if (PTR_ERR(event) == -EINTR) {
                dev_dbg(&dev->gadget->dev, "event fetching interrupted\n");
                return -EINTR;
        }
+       if (IS_ERR(event)) {
+               dev_err(&dev->gadget->dev, "failed to fetch event\n");
+               spin_lock_irqsave(&dev->lock, flags);
+               dev->state = STATE_DEV_FAILED;
+               spin_unlock_irqrestore(&dev->lock, flags);
+               return -ENODEV;
+       }
        length = min(arg.length, event->length);
-       ret = copy_to_user((void __user *)value, event,
-                               sizeof(*event) + length);
-       return ret;
+       if (copy_to_user((void __user *)value, event, sizeof(*event) + length))
+               return -EFAULT;
+
+       return 0;
 }
 
 static void *raw_alloc_io_data(struct usb_raw_ep_io *io, void __user *ptr,
                                bool get_from_user)
 {
-       int ret;
        void *data;
 
-       ret = copy_from_user(io, ptr, sizeof(*io));
-       if (ret)
-               return ERR_PTR(ret);
+       if (copy_from_user(io, ptr, sizeof(*io)))
+               return ERR_PTR(-EFAULT);
        if (io->ep >= USB_RAW_MAX_ENDPOINTS)
                return ERR_PTR(-EINVAL);
        if (!usb_raw_io_flags_valid(io->flags))
@@ -658,12 +669,13 @@ static int raw_ioctl_ep0_read(struct raw_dev *dev, unsigned long value)
        if (IS_ERR(data))
                return PTR_ERR(data);
        ret = raw_process_ep0_io(dev, &io, data, false);
-       if (ret < 0) {
-               kfree(data);
-               return ret;
-       }
+       if (ret)
+               goto free;
+
        length = min(io.length, (unsigned int)ret);
-       ret = copy_to_user((void __user *)(value + sizeof(io)), data, length);
+       if (copy_to_user((void __user *)(value + sizeof(io)), data, length))
+               ret = -EFAULT;
+free:
        kfree(data);
        return ret;
 }
@@ -952,12 +964,13 @@ static int raw_ioctl_ep_read(struct raw_dev *dev, unsigned long value)
        if (IS_ERR(data))
                return PTR_ERR(data);
        ret = raw_process_ep_io(dev, &io, data, false);
-       if (ret < 0) {
-               kfree(data);
-               return ret;
-       }
+       if (ret)
+               goto free;
+
        length = min(io.length, (unsigned int)ret);
-       ret = copy_to_user((void __user *)(value + sizeof(io)), data, length);
+       if (copy_to_user((void __user *)(value + sizeof(io)), data, length))
+               ret = -EFAULT;
+free:
        kfree(data);
        return ret;
 }
index 6e0432141c40911b29448ed1600b6d8e663387c1..22200341c8ec3a93f73d0132187616b98519a79b 100644 (file)
@@ -1951,10 +1951,10 @@ static irqreturn_t usba_vbus_irq_thread(int irq, void *devid)
                        usba_start(udc);
                } else {
                        udc->suspended = false;
-                       usba_stop(udc);
-
                        if (udc->driver->disconnect)
                                udc->driver->disconnect(&udc->gadget);
+
+                       usba_stop(udc);
                }
                udc->vbus_prev = vbus;
        }
index a4d9b5e1e50ea09747edc4b1bb0a4fadf7b440d8..d49c6dc1082dc980b47620a63fb28e35f5780c67 100644 (file)
@@ -540,7 +540,7 @@ static void bdc_req_complete(struct bdc_ep *ep, struct bdc_req *req,
 {
        struct bdc *bdc = ep->bdc;
 
-       if (req == NULL  || &req->queue == NULL || &req->usb_req == NULL)
+       if (req == NULL)
                return;
 
        dev_dbg(bdc->dev, "%s ep:%s status:%d\n", __func__, ep->name, status);
index 9eca1fe81061c81dd46d9a00fa2e6664f00f61bf..f37316d2c8fa4ff056ebe142c6422cbcf4d98416 100644 (file)
@@ -1571,6 +1571,8 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
                }
                if ((temp & PORT_RC))
                        reset_change = true;
+               if (temp & PORT_OC)
+                       status = 1;
        }
        if (!status && !reset_change) {
                xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
@@ -1636,6 +1638,13 @@ retry:
                                 port_index);
                        goto retry;
                }
+               /* bail out if port detected a over-current condition */
+               if (t1 & PORT_OC) {
+                       bus_state->bus_suspended = 0;
+                       spin_unlock_irqrestore(&xhci->lock, flags);
+                       xhci_dbg(xhci, "Bus suspend bailout, port over-current detected\n");
+                       return -EBUSY;
+               }
                /* suspend ports in U0, or bail out for new connect changes */
                if ((t1 & PORT_PE) && (t1 & PORT_PLS_MASK) == XDEV_U0) {
                        if ((t1 & PORT_CSC) && wake_enabled) {
index a78787bb513366ec6830ecf3dea8bf460670febe..0fda0c0f4d31fce5cc555dabceda120ee12fa9c4 100644 (file)
@@ -547,6 +547,23 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
                                stream_id);
                return;
        }
+       /*
+        * A cancelled TD can complete with a stall if HW cached the trb.
+        * In this case driver can't find cur_td, but if the ring is empty we
+        * can move the dequeue pointer to the current enqueue position.
+        */
+       if (!cur_td) {
+               if (list_empty(&ep_ring->td_list)) {
+                       state->new_deq_seg = ep_ring->enq_seg;
+                       state->new_deq_ptr = ep_ring->enqueue;
+                       state->new_cycle_state = ep_ring->cycle_state;
+                       goto done;
+               } else {
+                       xhci_warn(xhci, "Can't find new dequeue state, missing cur_td\n");
+                       return;
+               }
+       }
+
        /* Dig out the cycle state saved by the xHC during the stop ep cmd */
        xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
                        "Finding endpoint context");
@@ -592,6 +609,7 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
        state->new_deq_seg = new_seg;
        state->new_deq_ptr = new_deq;
 
+done:
        /* Don't update the ring cycle state for the producer (us). */
        xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
                        "Cycle state = 0x%x", state->new_cycle_state);
@@ -1856,8 +1874,8 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
 
        if (reset_type == EP_HARD_RESET) {
                ep->ep_state |= EP_HARD_CLEAR_TOGGLE;
-               xhci_cleanup_stalled_ring(xhci, ep_index, stream_id, td);
-               xhci_clear_hub_tt_buffer(xhci, td, ep);
+               xhci_cleanup_stalled_ring(xhci, slot_id, ep_index, stream_id,
+                                         td);
        }
        xhci_ring_cmd_db(xhci);
 }
@@ -1978,11 +1996,18 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
        if (trb_comp_code == COMP_STALL_ERROR ||
                xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
                                                trb_comp_code)) {
-               /* Issue a reset endpoint command to clear the host side
-                * halt, followed by a set dequeue command to move the
-                * dequeue pointer past the TD.
-                * The class driver clears the device side halt later.
+               /*
+                * xhci internal endpoint state will go to a "halt" state for
+                * any stall, including default control pipe protocol stall.
+                * To clear the host side halt we need to issue a reset endpoint
+                * command, followed by a set dequeue command to move past the
+                * TD.
+                * Class drivers clear the device side halt from a functional
+                * stall later. Hub TT buffer should only be cleared for FS/LS
+                * devices behind HS hubs for functional stalls.
                 */
+               if ((ep_index != 0) || (trb_comp_code != COMP_STALL_ERROR))
+                       xhci_clear_hub_tt_buffer(xhci, td, ep);
                xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index,
                                        ep_ring->stream_id, td, EP_HARD_RESET);
        } else {
@@ -2539,6 +2564,15 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                                xhci_dbg(xhci, "td_list is empty while skip flag set. Clear skip flag for slot %u ep %u.\n",
                                         slot_id, ep_index);
                        }
+                       if (trb_comp_code == COMP_STALL_ERROR ||
+                           xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
+                                                             trb_comp_code)) {
+                               xhci_cleanup_halted_endpoint(xhci, slot_id,
+                                                            ep_index,
+                                                            ep_ring->stream_id,
+                                                            NULL,
+                                                            EP_HARD_RESET);
+                       }
                        goto cleanup;
                }
 
index fe38275363e0f61d5968c0f546cdd9af79589453..bee5deccc83d81d09977dfa3ea334e61869b1cce 100644 (file)
@@ -3031,19 +3031,19 @@ static void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
                        added_ctxs, added_ctxs);
 }
 
-void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index,
-                              unsigned int stream_id, struct xhci_td *td)
+void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int slot_id,
+                              unsigned int ep_index, unsigned int stream_id,
+                              struct xhci_td *td)
 {
        struct xhci_dequeue_state deq_state;
-       struct usb_device *udev = td->urb->dev;
 
        xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep,
                        "Cleaning up stalled endpoint ring");
        /* We need to move the HW's dequeue pointer past this TD,
         * or it will attempt to resend it on the next doorbell ring.
         */
-       xhci_find_new_dequeue_state(xhci, udev->slot_id,
-                       ep_index, stream_id, td, &deq_state);
+       xhci_find_new_dequeue_state(xhci, slot_id, ep_index, stream_id, td,
+                                   &deq_state);
 
        if (!deq_state.new_deq_ptr || !deq_state.new_deq_seg)
                return;
@@ -3054,7 +3054,7 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index,
        if (!(xhci->quirks & XHCI_RESET_EP_QUIRK)) {
                xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep,
                                "Queueing new dequeue state");
-               xhci_queue_new_dequeue_state(xhci, udev->slot_id,
+               xhci_queue_new_dequeue_state(xhci, slot_id,
                                ep_index, &deq_state);
        } else {
                /* Better hope no one uses the input context between now and the
@@ -3065,7 +3065,7 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index,
                xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
                                "Setting up input context for "
                                "configure endpoint command");
-               xhci_setup_input_ctx_for_quirk(xhci, udev->slot_id,
+               xhci_setup_input_ctx_for_quirk(xhci, slot_id,
                                ep_index, &deq_state);
        }
 }
index 3289bb51620172c8490135aa3f9f7849a55246fb..86cfefdd6632b33f2a4e06805867777ee733e921 100644 (file)
@@ -2116,8 +2116,9 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
                unsigned int slot_id, unsigned int ep_index,
                struct xhci_dequeue_state *deq_state);
-void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index,
-               unsigned int stream_id, struct xhci_td *td);
+void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int slot_id,
+                              unsigned int ep_index, unsigned int stream_id,
+                              struct xhci_td *td);
 void xhci_stop_endpoint_command_watchdog(struct timer_list *t);
 void xhci_handle_command_timeout(struct work_struct *work);
 
index 2ab9600d0898bc2b85e7663fcfe86551d078925c..fc8a5da4a07c9adeb8d4f447e9d323a6519d6c15 100644 (file)
@@ -1199,18 +1199,18 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
 /* High level: Gfx (indexed) register access */
 
 #ifdef CONFIG_USB_SISUSBVGA_CON
-int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
+int sisusb_setreg(struct sisusb_usb_data *sisusb, u32 port, u8 data)
 {
        return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
 }
 
-int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
+int sisusb_getreg(struct sisusb_usb_data *sisusb, u32 port, u8 *data)
 {
        return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
 }
 #endif
 
-int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port,
+int sisusb_setidxreg(struct sisusb_usb_data *sisusb, u32 port,
                u8 index, u8 data)
 {
        int ret;
@@ -1220,7 +1220,7 @@ int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port,
        return ret;
 }
 
-int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port,
+int sisusb_getidxreg(struct sisusb_usb_data *sisusb, u32 port,
                u8 index, u8 *data)
 {
        int ret;
@@ -1230,7 +1230,7 @@ int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port,
        return ret;
 }
 
-int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
+int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, u32 port, u8 idx,
                u8 myand, u8 myor)
 {
        int ret;
@@ -1245,7 +1245,7 @@ int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
 }
 
 static int sisusb_setidxregmask(struct sisusb_usb_data *sisusb,
-               int port, u8 idx, u8 data, u8 mask)
+               u32 port, u8 idx, u8 data, u8 mask)
 {
        int ret;
        u8 tmp;
@@ -1258,13 +1258,13 @@ static int sisusb_setidxregmask(struct sisusb_usb_data *sisusb,
        return ret;
 }
 
-int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port,
+int sisusb_setidxregor(struct sisusb_usb_data *sisusb, u32 port,
                u8 index, u8 myor)
 {
        return sisusb_setidxregandor(sisusb, port, index, 0xff, myor);
 }
 
-int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
+int sisusb_setidxregand(struct sisusb_usb_data *sisusb, u32 port,
                u8 idx, u8 myand)
 {
        return sisusb_setidxregandor(sisusb, port, idx, myand, 0x00);
@@ -2785,8 +2785,8 @@ static loff_t sisusb_lseek(struct file *file, loff_t offset, int orig)
 static int sisusb_handle_command(struct sisusb_usb_data *sisusb,
                struct sisusb_command *y, unsigned long arg)
 {
-       int     retval, port, length;
-       u32     address;
+       int     retval, length;
+       u32     port, address;
 
        /* All our commands require the device
         * to be initialized.
index 1782c759c4ad582fbf9fb6e6fc7f6ce78bf7739a..ace09985dae4c53a81efe333a1e2b93204da150c 100644 (file)
@@ -812,17 +812,17 @@ static const struct SiS_VCLKData SiSUSB_VCLKData[] = {
 int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
 int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
 
-extern int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
-extern int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 * data);
-extern int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port,
+extern int sisusb_setreg(struct sisusb_usb_data *sisusb, u32 port, u8 data);
+extern int sisusb_getreg(struct sisusb_usb_data *sisusb, u32 port, u8 * data);
+extern int sisusb_setidxreg(struct sisusb_usb_data *sisusb, u32 port,
                            u8 index, u8 data);
-extern int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port,
+extern int sisusb_getidxreg(struct sisusb_usb_data *sisusb, u32 port,
                            u8 index, u8 * data);
-extern int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port,
+extern int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, u32 port,
                                 u8 idx, u8 myand, u8 myor);
-extern int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port,
+extern int sisusb_setidxregor(struct sisusb_usb_data *sisusb, u32 port,
                              u8 index, u8 myor);
-extern int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
+extern int sisusb_setidxregand(struct sisusb_usb_data *sisusb, u32 port,
                               u8 idx, u8 myand);
 
 void sisusb_delete(struct kref *kref);
index ffd984142171747c6f45e17936bf507b7e4c70b2..d63072fee099ce062757ebb9aa25bd25ba901f51 100644 (file)
@@ -1138,8 +1138,8 @@ static void garmin_read_process(struct garmin_data *garmin_data_p,
                   send it directly to the tty port */
                if (garmin_data_p->flags & FLAGS_QUEUING) {
                        pkt_add(garmin_data_p, data, data_length);
-               } else if (bulk_data ||
-                          getLayerId(data) == GARMIN_LAYERID_APPL) {
+               } else if (bulk_data || (data_length >= sizeof(u32) &&
+                               getLayerId(data) == GARMIN_LAYERID_APPL)) {
 
                        spin_lock_irqsave(&garmin_data_p->lock, flags);
                        garmin_data_p->flags |= APP_RESP_SEEN;
index 613f91add03da189c0fd5334cbccbbf720060079..ce0401d3137f1341929b3c3027175ac11938ca2f 100644 (file)
@@ -173,6 +173,7 @@ static const struct usb_device_id id_table[] = {
        {DEVICE_SWI(0x413c, 0x81b3)},   /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */
        {DEVICE_SWI(0x413c, 0x81b5)},   /* Dell Wireless 5811e QDL */
        {DEVICE_SWI(0x413c, 0x81b6)},   /* Dell Wireless 5811e QDL */
+       {DEVICE_SWI(0x413c, 0x81cc)},   /* Dell Wireless 5816e */
        {DEVICE_SWI(0x413c, 0x81cf)},   /* Dell Wireless 5819 */
        {DEVICE_SWI(0x413c, 0x81d0)},   /* Dell Wireless 5819 */
        {DEVICE_SWI(0x413c, 0x81d1)},   /* Dell Wireless 5818 */
index 3670fda02c3460000b06be6e0d496a3eb014fbb7..d592071119ba6b84275dbe19916b8eaa20e24c82 100644 (file)
@@ -81,6 +81,19 @@ static void uas_free_streams(struct uas_dev_info *devinfo);
 static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *prefix,
                                int status);
 
+/*
+ * This driver needs its own workqueue, as we need to control memory allocation.
+ *
+ * In the course of error handling and power management uas_wait_for_pending_cmnds()
+ * needs to flush pending work items. In these contexts we cannot allocate memory
+ * by doing block IO as we would deadlock. For the same reason we cannot wait
+ * for anything allocating memory not heeding these constraints.
+ *
+ * So we have to control all work items that can be on the workqueue we flush.
+ * Hence we cannot share a queue and need our own.
+ */
+static struct workqueue_struct *workqueue;
+
 static void uas_do_work(struct work_struct *work)
 {
        struct uas_dev_info *devinfo =
@@ -109,7 +122,7 @@ static void uas_do_work(struct work_struct *work)
                if (!err)
                        cmdinfo->state &= ~IS_IN_WORK_LIST;
                else
-                       schedule_work(&devinfo->work);
+                       queue_work(workqueue, &devinfo->work);
        }
 out:
        spin_unlock_irqrestore(&devinfo->lock, flags);
@@ -134,7 +147,7 @@ static void uas_add_work(struct uas_cmd_info *cmdinfo)
 
        lockdep_assert_held(&devinfo->lock);
        cmdinfo->state |= IS_IN_WORK_LIST;
-       schedule_work(&devinfo->work);
+       queue_work(workqueue, &devinfo->work);
 }
 
 static void uas_zap_pending(struct uas_dev_info *devinfo, int result)
@@ -190,6 +203,9 @@ static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *prefix,
        struct uas_cmd_info *ci = (void *)&cmnd->SCp;
        struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
 
+       if (status == -ENODEV) /* too late */
+               return;
+
        scmd_printk(KERN_INFO, cmnd,
                    "%s %d uas-tag %d inflight:%s%s%s%s%s%s%s%s%s%s%s%s ",
                    prefix, status, cmdinfo->uas_tag,
@@ -1226,7 +1242,31 @@ static struct usb_driver uas_driver = {
        .id_table = uas_usb_ids,
 };
 
-module_usb_driver(uas_driver);
+static int __init uas_init(void)
+{
+       int rv;
+
+       workqueue = alloc_workqueue("uas", WQ_MEM_RECLAIM, 0);
+       if (!workqueue)
+               return -ENOMEM;
+
+       rv = usb_register(&uas_driver);
+       if (rv) {
+               destroy_workqueue(workqueue);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static void __exit uas_exit(void)
+{
+       usb_deregister(&uas_driver);
+       destroy_workqueue(workqueue);
+}
+
+module_init(uas_init);
+module_exit(uas_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_IMPORT_NS(USB_STORAGE);
index 1880f3e13f57633d7c401998d33f859e0423cc31..f6c3681fa2e9efa4d861199aa2fe12a1c8334652 100644 (file)
@@ -2323,6 +2323,13 @@ UNUSUAL_DEV(  0x3340, 0xffff, 0x0000, 0x0000,
                USB_SC_DEVICE,USB_PR_DEVICE,NULL,
                US_FL_MAX_SECTORS_64 ),
 
+/* Reported by Cyril Roelandt <tipecaml@gmail.com> */
+UNUSUAL_DEV(  0x357d, 0x7788, 0x0114, 0x0114,
+               "JMicron",
+               "USB to ATA/ATAPI Bridge",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_BROKEN_FUA ),
+
 /* Reported by Andrey Rahmatullin <wrar@altlinux.org> */
 UNUSUAL_DEV(  0x4102, 0x1020, 0x0100,  0x0100,
                "iRiver",
index 1b23741036ee8e913f6a8e508e754a94d78fb19e..37157ed9a881a358968d85803428f95786628fc5 100644 (file)
  * and don't forget to CC: the USB development list <linux-usb@vger.kernel.org>
  */
 
+/* Reported-by: Julian Groß <julian.g@posteo.de> */
+UNUSUAL_DEV(0x059f, 0x105f, 0x0000, 0x9999,
+               "LaCie",
+               "2Big Quadra USB3",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NO_REPORT_OPCODES),
+
 /*
  * Apricorn USB3 dongle sometimes returns "USBSUSBSUSBS" in response to SCSI
  * commands in UAS mode.  Observed with the 1.28 firmware; are there others?
index c823122f9cb7b30f66d6fe1082344d36c3f7137d..e8ddb81cb6df4a23d537955acc625b08a2612152 100644 (file)
@@ -198,7 +198,10 @@ EXPORT_SYMBOL_GPL(typec_altmode_vdm);
 const struct typec_altmode *
 typec_altmode_get_partner(struct typec_altmode *adev)
 {
-       return adev ? &to_altmode(adev)->partner->adev : NULL;
+       if (!adev || !to_altmode(adev)->partner)
+               return NULL;
+
+       return &to_altmode(adev)->partner->adev;
 }
 EXPORT_SYMBOL_GPL(typec_altmode_get_partner);
 
index f5c5e0aef66f069e428e49724eb3e9dabd2ab17a..67c5139cfa0deeb6e4ad784ac0335b85d08e7c3f 100644 (file)
@@ -157,6 +157,10 @@ pmc_usb_mux_dp(struct pmc_usb_port *port, struct typec_mux_state *state)
        req.mode_data |= (state->mode - TYPEC_STATE_MODAL) <<
                         PMC_USB_ALTMODE_DP_MODE_SHIFT;
 
+       if (data->status & DP_STATUS_HPD_STATE)
+               req.mode_data |= PMC_USB_DP_HPD_LVL <<
+                                PMC_USB_ALTMODE_DP_MODE_SHIFT;
+
        return pmc_usb_command(port, (void *)&req, sizeof(req));
 }
 
@@ -298,11 +302,11 @@ static int pmc_usb_register_port(struct pmc_usb *pmc, int index,
        struct typec_mux_desc mux_desc = { };
        int ret;
 
-       ret = fwnode_property_read_u8(fwnode, "usb2-port", &port->usb2_port);
+       ret = fwnode_property_read_u8(fwnode, "usb2-port-number", &port->usb2_port);
        if (ret)
                return ret;
 
-       ret = fwnode_property_read_u8(fwnode, "usb3-port", &port->usb3_port);
+       ret = fwnode_property_read_u8(fwnode, "usb3-port-number", &port->usb3_port);
        if (ret)
                return ret;
 
index 46457c133d2bcaa33121a4064ed1d0f5238ab076..7afe275b17d03459564d4288eb2021e406e1414a 100644 (file)
@@ -114,8 +114,8 @@ pi3usb30532_mux_set(struct typec_mux *mux, struct typec_mux_state *state)
 static int pi3usb30532_probe(struct i2c_client *client)
 {
        struct device *dev = &client->dev;
-       struct typec_switch_desc sw_desc;
-       struct typec_mux_desc mux_desc;
+       struct typec_switch_desc sw_desc = { };
+       struct typec_mux_desc mux_desc = { };
        struct pi3usb30532 *pi;
        int ret;
 
index de3576e6530ab2abdd9dc07a4c4c88b51521f0ca..82b19ebd7838e0c129d3bcff33a80b0217d80940 100644 (file)
@@ -3794,6 +3794,14 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
                 */
                break;
 
+       case PORT_RESET:
+       case PORT_RESET_WAIT_OFF:
+               /*
+                * State set back to default mode once the timer completes.
+                * Ignore CC changes here.
+                */
+               break;
+
        default:
                if (tcpm_port_is_disconnected(port))
                        tcpm_set_state(port, unattached_state(port), 0);
@@ -3855,6 +3863,15 @@ static void _tcpm_pd_vbus_on(struct tcpm_port *port)
        case SRC_TRY_DEBOUNCE:
                /* Do nothing, waiting for sink detection */
                break;
+
+       case PORT_RESET:
+       case PORT_RESET_WAIT_OFF:
+               /*
+                * State set back to default mode once the timer completes.
+                * Ignore vbus changes here.
+                */
+               break;
+
        default:
                break;
        }
@@ -3908,10 +3925,19 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
        case PORT_RESET_WAIT_OFF:
                tcpm_set_state(port, tcpm_default_state(port), 0);
                break;
+
        case SRC_TRY_WAIT:
        case SRC_TRY_DEBOUNCE:
                /* Do nothing, waiting for sink detection */
                break;
+
+       case PORT_RESET:
+               /*
+                * State set back to default mode once the timer completes.
+                * Ignore vbus changes here.
+                */
+               break;
+
        default:
                if (port->pwr_role == TYPEC_SINK &&
                    port->attached)
index 7db1460104b78993ddf66a6e44e7361b9f56bfb0..e8140065c8a53f93ab97e7fbca4f49375284e30c 100644 (file)
@@ -1,21 +1,16 @@
 # SPDX-License-Identifier: GPL-2.0-only
-config VDPA
-       tristate
+menuconfig VDPA
+       tristate "vDPA drivers"
        help
          Enable this module to support vDPA device that uses a
          datapath which complies with virtio specifications with
          vendor specific control path.
 
-menuconfig VDPA_MENU
-       bool "VDPA drivers"
-       default n
-
-if VDPA_MENU
+if VDPA
 
 config VDPA_SIM
        tristate "vDPA device simulator"
-       depends on RUNTIME_TESTING_MENU
-       select VDPA
+       depends on RUNTIME_TESTING_MENU && HAS_DMA && VHOST_DPN
        select VHOST_RING
        default n
        help
@@ -24,9 +19,8 @@ config VDPA_SIM
          development of vDPA.
 
 config IFCVF
-       tristate "Intel IFC VF VDPA driver"
+       tristate "Intel IFC VF vDPA driver"
        depends on PCI_MSI
-       select VDPA
        default n
        help
          This kernel module can drive Intel IFC VF NIC to offload
@@ -34,4 +28,4 @@ config IFCVF
          To compile this driver as a module, choose M here: the module will
          be called ifcvf.
 
-endif # VDPA_MENU
+endif # VDPA
index b61b06ea26d346bc5ca13c0d986aa3c8bd03eace..e24371d644b5062c41357bf14eef66ffa76977be 100644 (file)
@@ -301,12 +301,10 @@ int ifcvf_set_vq_state(struct ifcvf_hw *hw, u16 qid, u64 num)
 
 static int ifcvf_hw_enable(struct ifcvf_hw *hw)
 {
-       struct ifcvf_lm_cfg __iomem *ifcvf_lm;
        struct virtio_pci_common_cfg __iomem *cfg;
        struct ifcvf_adapter *ifcvf;
        u32 i;
 
-       ifcvf_lm = (struct ifcvf_lm_cfg __iomem *)hw->lm_cfg;
        ifcvf = vf_to_adapter(hw);
        cfg = hw->common_cfg;
        ifc_iowrite16(IFCVF_MSI_CONFIG_OFF, &cfg->msix_config);
index 8d54dc5b08d2453b31d1b5046f4eda2959aa7dec..abf6a061cab6583db4e167235c9b4706add5dcfb 100644 (file)
@@ -31,11 +31,9 @@ static irqreturn_t ifcvf_intr_handler(int irq, void *arg)
 static int ifcvf_start_datapath(void *private)
 {
        struct ifcvf_hw *vf = ifcvf_private_to_vf(private);
-       struct ifcvf_adapter *ifcvf;
        u8 status;
        int ret;
 
-       ifcvf = vf_to_adapter(vf);
        vf->nr_vring = IFCVF_MAX_QUEUE_PAIRS * 2;
        ret = ifcvf_start_hw(vf);
        if (ret < 0) {
@@ -228,7 +226,7 @@ static u32 ifcvf_vdpa_get_vendor_id(struct vdpa_device *vdpa_dev)
        return IFCVF_SUBSYS_VENDOR_ID;
 }
 
-static u16 ifcvf_vdpa_get_vq_align(struct vdpa_device *vdpa_dev)
+static u32 ifcvf_vdpa_get_vq_align(struct vdpa_device *vdpa_dev)
 {
        return IFCVF_QUEUE_ALIGNMENT;
 }
index e9ed6a2b635b9ea9cf0c14f6834884c31eeb7f2c..ff6562f602e055fe14024572cbaf22cdddce2ae9 100644 (file)
@@ -116,7 +116,7 @@ EXPORT_SYMBOL_GPL(__vdpa_alloc_device);
 
 /**
  * vdpa_register_device - register a vDPA device
- * Callers must have a succeed call of vdpa_init_device() before.
+ * Callers must have a succeed call of vdpa_alloc_device() before.
  * @vdev: the vdpa device to be registered to vDPA bus
  *
  * Returns an error when fail to add to vDPA bus
index 6e8a0cf2fdebbc10acb530ea9ee4f73e88d99f2d..7957d2d41fc4b4cbc71c81441d612b3b7a47cbdc 100644 (file)
@@ -435,7 +435,7 @@ static u64 vdpasim_get_vq_state(struct vdpa_device *vdpa, u16 idx)
        return vrh->last_avail_idx;
 }
 
-static u16 vdpasim_get_vq_align(struct vdpa_device *vdpa)
+static u32 vdpasim_get_vq_align(struct vdpa_device *vdpa)
 {
        return VDPASIM_QUEUE_ALIGN;
 }
@@ -488,7 +488,7 @@ static u8 vdpasim_get_status(struct vdpa_device *vdpa)
        status = vdpasim->status;
        spin_unlock(&vdpasim->lock);
 
-       return vdpasim->status;
+       return status;
 }
 
 static void vdpasim_set_status(struct vdpa_device *vdpa, u8 status)
index 85b32c3252829de7fb42b5fcb3c6ebde6e989555..cc1d64765ce791ee48e14960620bd039028fffc2 100644 (file)
@@ -342,8 +342,8 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
        vma = find_vma_intersection(mm, vaddr, vaddr + 1);
 
        if (vma && vma->vm_flags & VM_PFNMAP) {
-               *pfn = ((vaddr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
-               if (is_invalid_reserved_pfn(*pfn))
+               if (!follow_pfn(vma, vaddr, pfn) &&
+                   is_invalid_reserved_pfn(*pfn))
                        ret = 0;
        }
 done:
@@ -555,7 +555,7 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data,
                        continue;
                }
 
-               remote_vaddr = dma->vaddr + iova - dma->iova;
+               remote_vaddr = dma->vaddr + (iova - dma->iova);
                ret = vfio_pin_page_external(dma, remote_vaddr, &phys_pfn[i],
                                             do_accounting);
                if (ret)
@@ -2345,10 +2345,10 @@ static int vfio_iommu_type1_dma_rw_chunk(struct vfio_iommu *iommu,
        vaddr = dma->vaddr + offset;
 
        if (write)
-               *copied = __copy_to_user((void __user *)vaddr, data,
+               *copied = copy_to_user((void __user *)vaddr, data,
                                         count) ? 0 : count;
        else
-               *copied = __copy_from_user(data, (void __user *)vaddr,
+               *copied = copy_from_user(data, (void __user *)vaddr,
                                           count) ? 0 : count;
        if (kthread)
                unuse_mm(mm);
index 362b832f5338cd62a327518bd33e478f156e2472..c4f27379359537ecc983da9611214e8547edb3bf 100644 (file)
@@ -3,6 +3,8 @@ config VHOST_IOTLB
        tristate
        help
          Generic IOTLB implementation for vhost and vringh.
+         This option is selected by any driver which needs to support
+         an IOMMU in software.
 
 config VHOST_RING
        tristate
@@ -11,6 +13,15 @@ config VHOST_RING
          This option is selected by any driver which needs to access
          the host side of a virtio ring.
 
+config VHOST_DPN
+       bool
+       depends on !ARM || AEABI
+       default y
+       help
+         Anything selecting VHOST or VHOST_RING must depend on VHOST_DPN.
+         This excludes the deprecated ARM ABI since that forces a 4 byte
+         alignment on all structs - incompatible with virtio spec requirements.
+
 config VHOST
        tristate
        select VHOST_IOTLB
@@ -26,7 +37,7 @@ if VHOST_MENU
 
 config VHOST_NET
        tristate "Host kernel accelerator for virtio net"
-       depends on NET && EVENTFD && (TUN || !TUN) && (TAP || !TAP)
+       depends on NET && EVENTFD && (TUN || !TUN) && (TAP || !TAP) && VHOST_DPN
        select VHOST
        ---help---
          This kernel module can be loaded in host kernel to accelerate
@@ -38,7 +49,7 @@ config VHOST_NET
 
 config VHOST_SCSI
        tristate "VHOST_SCSI TCM fabric driver"
-       depends on TARGET_CORE && EVENTFD
+       depends on TARGET_CORE && EVENTFD && VHOST_DPN
        select VHOST
        default n
        ---help---
@@ -47,7 +58,7 @@ config VHOST_SCSI
 
 config VHOST_VSOCK
        tristate "vhost virtio-vsock driver"
-       depends on VSOCKETS && EVENTFD
+       depends on VSOCKETS && EVENTFD && VHOST_DPN
        select VHOST
        select VIRTIO_VSOCKETS_COMMON
        default n
@@ -61,9 +72,9 @@ config VHOST_VSOCK
 
 config VHOST_VDPA
        tristate "Vhost driver for vDPA-based backend"
-       depends on EVENTFD
+       depends on EVENTFD && VHOST_DPN
        select VHOST
-       select VDPA
+       depends on VDPA
        help
          This kernel module can be loaded in host kernel to accelerate
          guest virtio devices with the vDPA-based backends.
index 87469d67ede8d889df6a855d90f7f05dcc2d44c5..2927f02cc7e1b5af56c1626973f1499c96b25244 100644 (file)
@@ -424,7 +424,7 @@ static void vhost_net_disable_vq(struct vhost_net *n,
        struct vhost_net_virtqueue *nvq =
                container_of(vq, struct vhost_net_virtqueue, vq);
        struct vhost_poll *poll = n->poll + (nvq - n->vqs);
-       if (!vq->private_data)
+       if (!vhost_vq_get_backend(vq))
                return;
        vhost_poll_stop(poll);
 }
@@ -437,7 +437,7 @@ static int vhost_net_enable_vq(struct vhost_net *n,
        struct vhost_poll *poll = n->poll + (nvq - n->vqs);
        struct socket *sock;
 
-       sock = vq->private_data;
+       sock = vhost_vq_get_backend(vq);
        if (!sock)
                return 0;
 
@@ -524,7 +524,7 @@ static void vhost_net_busy_poll(struct vhost_net *net,
                return;
 
        vhost_disable_notify(&net->dev, vq);
-       sock = rvq->private_data;
+       sock = vhost_vq_get_backend(rvq);
 
        busyloop_timeout = poll_rx ? rvq->busyloop_timeout:
                                     tvq->busyloop_timeout;
@@ -570,8 +570,10 @@ static int vhost_net_tx_get_vq_desc(struct vhost_net *net,
 
        if (r == tvq->num && tvq->busyloop_timeout) {
                /* Flush batched packets first */
-               if (!vhost_sock_zcopy(tvq->private_data))
-                       vhost_tx_batch(net, tnvq, tvq->private_data, msghdr);
+               if (!vhost_sock_zcopy(vhost_vq_get_backend(tvq)))
+                       vhost_tx_batch(net, tnvq,
+                                      vhost_vq_get_backend(tvq),
+                                      msghdr);
 
                vhost_net_busy_poll(net, rvq, tvq, busyloop_intr, false);
 
@@ -685,7 +687,7 @@ static int vhost_net_build_xdp(struct vhost_net_virtqueue *nvq,
        struct vhost_virtqueue *vq = &nvq->vq;
        struct vhost_net *net = container_of(vq->dev, struct vhost_net,
                                             dev);
-       struct socket *sock = vq->private_data;
+       struct socket *sock = vhost_vq_get_backend(vq);
        struct page_frag *alloc_frag = &net->page_frag;
        struct virtio_net_hdr *gso;
        struct xdp_buff *xdp = &nvq->xdp[nvq->batched_xdp];
@@ -952,7 +954,7 @@ static void handle_tx(struct vhost_net *net)
        struct socket *sock;
 
        mutex_lock_nested(&vq->mutex, VHOST_NET_VQ_TX);
-       sock = vq->private_data;
+       sock = vhost_vq_get_backend(vq);
        if (!sock)
                goto out;
 
@@ -1121,7 +1123,7 @@ static void handle_rx(struct vhost_net *net)
        int recv_pkts = 0;
 
        mutex_lock_nested(&vq->mutex, VHOST_NET_VQ_RX);
-       sock = vq->private_data;
+       sock = vhost_vq_get_backend(vq);
        if (!sock)
                goto out;
 
@@ -1345,9 +1347,9 @@ static struct socket *vhost_net_stop_vq(struct vhost_net *n,
                container_of(vq, struct vhost_net_virtqueue, vq);
 
        mutex_lock(&vq->mutex);
-       sock = vq->private_data;
+       sock = vhost_vq_get_backend(vq);
        vhost_net_disable_vq(n, vq);
-       vq->private_data = NULL;
+       vhost_vq_set_backend(vq, NULL);
        vhost_net_buf_unproduce(nvq);
        nvq->rx_ring = NULL;
        mutex_unlock(&vq->mutex);
@@ -1521,7 +1523,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
        }
 
        /* start polling new socket */
-       oldsock = vq->private_data;
+       oldsock = vhost_vq_get_backend(vq);
        if (sock != oldsock) {
                ubufs = vhost_net_ubuf_alloc(vq,
                                             sock && vhost_sock_zcopy(sock));
@@ -1531,7 +1533,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
                }
 
                vhost_net_disable_vq(n, vq);
-               vq->private_data = sock;
+               vhost_vq_set_backend(vq, sock);
                vhost_net_buf_unproduce(nvq);
                r = vhost_vq_init_access(vq);
                if (r)
@@ -1568,7 +1570,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
        return 0;
 
 err_used:
-       vq->private_data = oldsock;
+       vhost_vq_set_backend(vq, oldsock);
        vhost_net_enable_vq(n, vq);
        if (ubufs)
                vhost_net_ubuf_put_wait_and_free(ubufs);
index 7653667a8cdcbd8aa3e331548833449b8d629f92..c39952243fd3289f23844fb9bef6c41e175a0dba 100644 (file)
@@ -452,7 +452,7 @@ vhost_scsi_do_evt_work(struct vhost_scsi *vs, struct vhost_scsi_evt *evt)
        unsigned out, in;
        int head, ret;
 
-       if (!vq->private_data) {
+       if (!vhost_vq_get_backend(vq)) {
                vs->vs_events_missed = true;
                return;
        }
@@ -892,7 +892,7 @@ vhost_scsi_get_req(struct vhost_virtqueue *vq, struct vhost_scsi_ctx *vc,
        } else {
                struct vhost_scsi_tpg **vs_tpg, *tpg;
 
-               vs_tpg = vq->private_data;      /* validated at handler entry */
+               vs_tpg = vhost_vq_get_backend(vq);      /* validated at handler entry */
 
                tpg = READ_ONCE(vs_tpg[*vc->target]);
                if (unlikely(!tpg)) {
@@ -929,7 +929,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
         * We can handle the vq only after the endpoint is setup by calling the
         * VHOST_SCSI_SET_ENDPOINT ioctl.
         */
-       vs_tpg = vq->private_data;
+       vs_tpg = vhost_vq_get_backend(vq);
        if (!vs_tpg)
                goto out;
 
@@ -1184,7 +1184,7 @@ vhost_scsi_ctl_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
         * We can handle the vq only after the endpoint is setup by calling the
         * VHOST_SCSI_SET_ENDPOINT ioctl.
         */
-       if (!vq->private_data)
+       if (!vhost_vq_get_backend(vq))
                goto out;
 
        memset(&vc, 0, sizeof(vc));
@@ -1322,7 +1322,7 @@ static void vhost_scsi_evt_handle_kick(struct vhost_work *work)
        struct vhost_scsi *vs = container_of(vq->dev, struct vhost_scsi, dev);
 
        mutex_lock(&vq->mutex);
-       if (!vq->private_data)
+       if (!vhost_vq_get_backend(vq))
                goto out;
 
        if (vs->vs_events_missed)
@@ -1460,7 +1460,7 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs,
                for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) {
                        vq = &vs->vqs[i].vq;
                        mutex_lock(&vq->mutex);
-                       vq->private_data = vs_tpg;
+                       vhost_vq_set_backend(vq, vs_tpg);
                        vhost_vq_init_access(vq);
                        mutex_unlock(&vq->mutex);
                }
@@ -1547,7 +1547,7 @@ vhost_scsi_clear_endpoint(struct vhost_scsi *vs,
                for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) {
                        vq = &vs->vqs[i].vq;
                        mutex_lock(&vq->mutex);
-                       vq->private_data = NULL;
+                       vhost_vq_set_backend(vq, NULL);
                        mutex_unlock(&vq->mutex);
                }
        }
index e37c92d4d7ada2ca4f06b8f91d3f6b2a6b303610..9a3a09005e03b16a5f561c9c34f9974a89733c31 100644 (file)
@@ -49,7 +49,7 @@ static void handle_vq(struct vhost_test *n)
        void *private;
 
        mutex_lock(&vq->mutex);
-       private = vq->private_data;
+       private = vhost_vq_get_backend(vq);
        if (!private) {
                mutex_unlock(&vq->mutex);
                return;
@@ -120,7 +120,7 @@ static int vhost_test_open(struct inode *inode, struct file *f)
        vqs[VHOST_TEST_VQ] = &n->vqs[VHOST_TEST_VQ];
        n->vqs[VHOST_TEST_VQ].handle_kick = handle_vq_kick;
        vhost_dev_init(dev, vqs, VHOST_TEST_VQ_MAX, UIO_MAXIOV,
-                      VHOST_TEST_PKT_WEIGHT, VHOST_TEST_WEIGHT);
+                      VHOST_TEST_PKT_WEIGHT, VHOST_TEST_WEIGHT, NULL);
 
        f->private_data = n;
 
@@ -133,8 +133,8 @@ static void *vhost_test_stop_vq(struct vhost_test *n,
        void *private;
 
        mutex_lock(&vq->mutex);
-       private = vq->private_data;
-       vq->private_data = NULL;
+       private = vhost_vq_get_backend(vq);
+       vhost_vq_set_backend(vq, NULL);
        mutex_unlock(&vq->mutex);
        return private;
 }
@@ -198,8 +198,8 @@ static long vhost_test_run(struct vhost_test *n, int test)
                priv = test ? n : NULL;
 
                /* start polling new socket */
-               oldpriv = vq->private_data;
-               vq->private_data = priv;
+               oldpriv = vhost_vq_get_backend(vq);
+               vhost_vq_set_backend(vq, priv);
 
                r = vhost_vq_init_access(&n->vqs[index]);
 
@@ -225,7 +225,7 @@ static long vhost_test_reset_owner(struct vhost_test *n)
 {
        void *priv = NULL;
        long err;
-       struct vhost_umem *umem;
+       struct vhost_iotlb *umem;
 
        mutex_lock(&n->dev.mutex);
        err = vhost_dev_check_owner(&n->dev);
index 421f02a8530af2bfb0b1f1c4c7aef0f338929d2d..0968361e3b7745906c1b7da2eab84a7bda4767bc 100644 (file)
@@ -296,7 +296,6 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
        struct vdpa_callback cb;
        struct vhost_virtqueue *vq;
        struct vhost_vring_state s;
-       u8 status;
        u32 idx;
        long r;
 
@@ -310,8 +309,6 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
        idx = array_index_nospec(idx, v->nvqs);
        vq = &v->vqs[idx];
 
-       status = ops->get_status(vdpa);
-
        if (cmd == VHOST_VDPA_SET_VRING_ENABLE) {
                if (copy_from_user(&s, argp, sizeof(s)))
                        return -EFAULT;
@@ -678,8 +675,6 @@ static int vhost_vdpa_open(struct inode *inode, struct file *filep)
        int nvqs, i, r, opened;
 
        v = container_of(inode->i_cdev, struct vhost_vdpa, cdev);
-       if (!v)
-               return -ENODEV;
 
        opened = atomic_cmpxchg(&v->opened, 0, 1);
        if (opened)
index 181382185bbce99c894a52d3269c7da566179d77..f8403bd46b85dd5d0183baee2ef650cdd37e0fa6 100644 (file)
@@ -231,6 +231,33 @@ enum {
                         (1ULL << VIRTIO_F_VERSION_1)
 };
 
+/**
+ * vhost_vq_set_backend - Set backend.
+ *
+ * @vq            Virtqueue.
+ * @private_data  The private data.
+ *
+ * Context: Need to call with vq->mutex acquired.
+ */
+static inline void vhost_vq_set_backend(struct vhost_virtqueue *vq,
+                                       void *private_data)
+{
+       vq->private_data = private_data;
+}
+
+/**
+ * vhost_vq_get_backend - Get backend.
+ *
+ * @vq            Virtqueue.
+ *
+ * Context: Need to call with vq->mutex acquired.
+ * Return: Private data previously set with vhost_vq_set_backend.
+ */
+static inline void *vhost_vq_get_backend(struct vhost_virtqueue *vq)
+{
+       return vq->private_data;
+}
+
 static inline bool vhost_has_feature(struct vhost_virtqueue *vq, int bit)
 {
        return vq->acked_features & (1ULL << bit);
index ee0491f579ace20c7c1ac000e7f7540b5a40bdd0..ba8e0d6cfd9748dfdd39fa28865287a578f4e960 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#if IS_REACHABLE(CONFIG_VHOST_IOTLB)
 #include <linux/bvec.h>
 #include <linux/highmem.h>
 #include <linux/vhost_iotlb.h>
+#endif
 #include <uapi/linux/virtio_config.h>
 
 static __printf(1,2) __cold void vringh_bad(const char *fmt, ...)
@@ -1059,6 +1061,8 @@ int vringh_need_notify_kern(struct vringh *vrh)
 }
 EXPORT_SYMBOL(vringh_need_notify_kern);
 
+#if IS_REACHABLE(CONFIG_VHOST_IOTLB)
+
 static int iotlb_translate(const struct vringh *vrh,
                           u64 addr, u64 len, struct bio_vec iov[],
                           int iov_size, u32 perm)
@@ -1416,5 +1420,6 @@ int vringh_need_notify_iotlb(struct vringh *vrh)
 }
 EXPORT_SYMBOL(vringh_need_notify_iotlb);
 
+#endif
 
 MODULE_LICENSE("GPL");
index 97669484a3f690f5f699fd9f4cadc32719cfb65e..fb4e944c4d0d77d18c7aa6ebccecd66e33d0e289 100644 (file)
@@ -91,7 +91,7 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
 
        mutex_lock(&vq->mutex);
 
-       if (!vq->private_data)
+       if (!vhost_vq_get_backend(vq))
                goto out;
 
        /* Avoid further vmexits, we're already processing the virtqueue */
@@ -181,14 +181,14 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
                        break;
                }
 
-               vhost_add_used(vq, head, sizeof(pkt->hdr) + payload_len);
-               added = true;
-
-               /* Deliver to monitoring devices all correctly transmitted
-                * packets.
+               /* Deliver to monitoring devices all packets that we
+                * will transmit.
                 */
                virtio_transport_deliver_tap_pkt(pkt);
 
+               vhost_add_used(vq, head, sizeof(pkt->hdr) + payload_len);
+               added = true;
+
                pkt->off += payload_len;
                total_len += payload_len;
 
@@ -196,6 +196,12 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
                 * to send it with the next available buffer.
                 */
                if (pkt->off < pkt->len) {
+                       /* We are queueing the same virtio_vsock_pkt to handle
+                        * the remaining bytes, and we want to deliver it
+                        * to monitoring devices in the next iteration.
+                        */
+                       pkt->tap_delivered = false;
+
                        spin_lock_bh(&vsock->send_pkt_list_lock);
                        list_add(&pkt->list, &vsock->send_pkt_list);
                        spin_unlock_bh(&vsock->send_pkt_list_lock);
@@ -440,7 +446,7 @@ static void vhost_vsock_handle_tx_kick(struct vhost_work *work)
 
        mutex_lock(&vq->mutex);
 
-       if (!vq->private_data)
+       if (!vhost_vq_get_backend(vq))
                goto out;
 
        vhost_disable_notify(&vsock->dev, vq);
@@ -533,8 +539,8 @@ static int vhost_vsock_start(struct vhost_vsock *vsock)
                        goto err_vq;
                }
 
-               if (!vq->private_data) {
-                       vq->private_data = vsock;
+               if (!vhost_vq_get_backend(vq)) {
+                       vhost_vq_set_backend(vq, vsock);
                        ret = vhost_vq_init_access(vq);
                        if (ret)
                                goto err_vq;
@@ -543,18 +549,23 @@ static int vhost_vsock_start(struct vhost_vsock *vsock)
                mutex_unlock(&vq->mutex);
        }
 
+       /* Some packets may have been queued before the device was started,
+        * let's kick the send worker to send them.
+        */
+       vhost_work_queue(&vsock->dev, &vsock->send_pkt_work);
+
        mutex_unlock(&vsock->dev.mutex);
        return 0;
 
 err_vq:
-       vq->private_data = NULL;
+       vhost_vq_set_backend(vq, NULL);
        mutex_unlock(&vq->mutex);
 
        for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) {
                vq = &vsock->vqs[i];
 
                mutex_lock(&vq->mutex);
-               vq->private_data = NULL;
+               vhost_vq_set_backend(vq, NULL);
                mutex_unlock(&vq->mutex);
        }
 err:
@@ -577,7 +588,7 @@ static int vhost_vsock_stop(struct vhost_vsock *vsock)
                struct vhost_virtqueue *vq = &vsock->vqs[i];
 
                mutex_lock(&vq->mutex);
-               vq->private_data = NULL;
+               vhost_vq_set_backend(vq, NULL);
                mutex_unlock(&vq->mutex);
        }
 
index 2bbf94b15bba219e50a370299552a4097e872410..69a32dfc318a59c8ff5cf05e9e6114b421d1c73b 100644 (file)
@@ -45,7 +45,7 @@ config VIRTIO_PCI_LEGACY
 
 config VIRTIO_VDPA
        tristate "vDPA driver for virtio devices"
-       select VDPA
+       depends on VDPA
        select VIRTIO
        help
          This driver provides support for virtio based paravirtual
index 0ef16566c3f3390936a3e3d97e99a1fb97f40193..51086a5afdd4179d52ba109fc346564bcee29eb8 100644 (file)
@@ -165,7 +165,7 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
 
 }
 
-int virtballoon_free_page_report(struct page_reporting_dev_info *pr_dev_info,
+static int virtballoon_free_page_report(struct page_reporting_dev_info *pr_dev_info,
                                   struct scatterlist *sg, unsigned int nents)
 {
        struct virtio_balloon *vb =
@@ -580,7 +580,7 @@ static u32 virtio_balloon_cmd_id_received(struct virtio_balloon *vb)
        if (test_and_clear_bit(VIRTIO_BALLOON_CONFIG_READ_CMD_ID,
                               &vb->config_read_bitmap))
                virtio_cread(vb->vdev, struct virtio_balloon_config,
-                            free_page_report_cmd_id,
+                            free_page_hint_cmd_id,
                             &vb->cmd_id_received_cache);
 
        return vb->cmd_id_received_cache;
index 5ae529671b3d34b33813ec62bce0931d04c5f359..efaf65b0f42d08f563fa545d382067a941548aab 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/virtio.h>
 #include <linux/virtio_config.h>
 #include <linux/input.h>
+#include <linux/slab.h>
 
 #include <uapi/linux/virtio_ids.h>
 #include <uapi/linux/virtio_input.h>
index 53e04926a7b2d3ffb6748278550cbd845a34f3ea..190d26e2e75f9e7a8c5bf2fd35fe4c202d9380f3 100644 (file)
@@ -137,10 +137,14 @@ wdt_restart(struct watchdog_device *wdd, unsigned long mode, void *cmd)
 {
        struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
 
+       writel_relaxed(UNLOCK, wdt->base + WDTLOCK);
        writel_relaxed(0, wdt->base + WDTCONTROL);
        writel_relaxed(0, wdt->base + WDTLOAD);
        writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL);
 
+       /* Flush posted writes. */
+       readl_relaxed(wdt->base + WDTLOCK);
+
        return 0;
 }
 
index 385843256865e44b68d2d57071fb89ecedafad83..040d2a43e8e350924f259a3aaa8468b65edba15f 100644 (file)
@@ -448,7 +448,14 @@ EXPORT_SYMBOL_GPL(xenbus_free_evtchn);
 int xenbus_map_ring_valloc(struct xenbus_device *dev, grant_ref_t *gnt_refs,
                           unsigned int nr_grefs, void **vaddr)
 {
-       return ring_ops->map(dev, gnt_refs, nr_grefs, vaddr);
+       int err;
+
+       err = ring_ops->map(dev, gnt_refs, nr_grefs, vaddr);
+       /* Some hypervisors are buggy and can return 1. */
+       if (err > 0)
+               err = GNTST_general_error;
+
+       return err;
 }
 EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc);
 
index 6765949b3aab61cedc3167852c4fb1d1c3199bd1..380ad5ace7cfd54c09463a5e44e5c63c9c21b7ec 100644 (file)
@@ -169,7 +169,7 @@ static int afs_record_cm_probe(struct afs_call *call, struct afs_server *server)
 
        spin_lock(&server->probe_lock);
 
-       if (!test_bit(AFS_SERVER_FL_HAVE_EPOCH, &server->flags)) {
+       if (!test_and_set_bit(AFS_SERVER_FL_HAVE_EPOCH, &server->flags)) {
                server->cm_epoch = call->epoch;
                server->probe.cm_epoch = call->epoch;
                goto out;
index 5c794f4b051afcc953f97ceff3b562402a31b4e0..d1e1caa23c8b3fd4895473cc951772693ed77bfa 100644 (file)
@@ -1032,7 +1032,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
        struct dentry *parent;
        struct inode *inode;
        struct key *key;
-       afs_dataversion_t dir_version;
+       afs_dataversion_t dir_version, invalid_before;
        long de_version;
        int ret;
 
@@ -1084,8 +1084,8 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
        if (de_version == (long)dir_version)
                goto out_valid_noupdate;
 
-       dir_version = dir->invalid_before;
-       if (de_version - (long)dir_version >= 0)
+       invalid_before = dir->invalid_before;
+       if (de_version - (long)invalid_before >= 0)
                goto out_valid;
 
        _debug("dir modified");
@@ -1275,6 +1275,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        struct afs_fs_cursor fc;
        struct afs_vnode *dvnode = AFS_FS_I(dir);
        struct key *key;
+       afs_dataversion_t data_version;
        int ret;
 
        mode |= S_IFDIR;
@@ -1295,7 +1296,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
-               afs_dataversion_t data_version = dvnode->status.data_version + 1;
+               data_version = dvnode->status.data_version + 1;
 
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(dvnode);
@@ -1316,10 +1317,14 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
                goto error_key;
        }
 
-       if (ret == 0 &&
-           test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
-               afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
-                                afs_edit_dir_for_create);
+       if (ret == 0) {
+               down_write(&dvnode->validate_lock);
+               if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
+                   dvnode->status.data_version == data_version)
+                       afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
+                                        afs_edit_dir_for_create);
+               up_write(&dvnode->validate_lock);
+       }
 
        key_put(key);
        kfree(scb);
@@ -1360,6 +1365,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
        struct afs_fs_cursor fc;
        struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL;
        struct key *key;
+       afs_dataversion_t data_version;
        int ret;
 
        _enter("{%llx:%llu},{%pd}",
@@ -1391,7 +1397,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
 
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
-               afs_dataversion_t data_version = dvnode->status.data_version + 1;
+               data_version = dvnode->status.data_version + 1;
 
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(dvnode);
@@ -1404,9 +1410,12 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
                ret = afs_end_vnode_operation(&fc);
                if (ret == 0) {
                        afs_dir_remove_subdir(dentry);
-                       if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
+                       down_write(&dvnode->validate_lock);
+                       if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
+                           dvnode->status.data_version == data_version)
                                afs_edit_dir_remove(dvnode, &dentry->d_name,
                                                    afs_edit_dir_for_rmdir);
+                       up_write(&dvnode->validate_lock);
                }
        }
 
@@ -1544,10 +1553,15 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
                ret = afs_end_vnode_operation(&fc);
                if (ret == 0 && !(scb[1].have_status || scb[1].have_error))
                        ret = afs_dir_remove_link(dvnode, dentry, key);
-               if (ret == 0 &&
-                   test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
-                       afs_edit_dir_remove(dvnode, &dentry->d_name,
-                                           afs_edit_dir_for_unlink);
+
+               if (ret == 0) {
+                       down_write(&dvnode->validate_lock);
+                       if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
+                           dvnode->status.data_version == data_version)
+                               afs_edit_dir_remove(dvnode, &dentry->d_name,
+                                                   afs_edit_dir_for_unlink);
+                       up_write(&dvnode->validate_lock);
+               }
        }
 
        if (need_rehash && ret < 0 && ret != -ENOENT)
@@ -1573,6 +1587,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        struct afs_status_cb *scb;
        struct afs_vnode *dvnode = AFS_FS_I(dir);
        struct key *key;
+       afs_dataversion_t data_version;
        int ret;
 
        mode |= S_IFREG;
@@ -1597,7 +1612,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
-               afs_dataversion_t data_version = dvnode->status.data_version + 1;
+               data_version = dvnode->status.data_version + 1;
 
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(dvnode);
@@ -1618,9 +1633,12 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
                goto error_key;
        }
 
-       if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
+       down_write(&dvnode->validate_lock);
+       if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
+           dvnode->status.data_version == data_version)
                afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
                                 afs_edit_dir_for_create);
+       up_write(&dvnode->validate_lock);
 
        kfree(scb);
        key_put(key);
@@ -1648,6 +1666,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
        struct afs_vnode *dvnode = AFS_FS_I(dir);
        struct afs_vnode *vnode = AFS_FS_I(d_inode(from));
        struct key *key;
+       afs_dataversion_t data_version;
        int ret;
 
        _enter("{%llx:%llu},{%llx:%llu},{%pd}",
@@ -1672,7 +1691,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
 
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
-               afs_dataversion_t data_version = dvnode->status.data_version + 1;
+               data_version = dvnode->status.data_version + 1;
 
                if (mutex_lock_interruptible_nested(&vnode->io_lock, 1) < 0) {
                        afs_end_vnode_operation(&fc);
@@ -1702,9 +1721,12 @@ static int afs_link(struct dentry *from, struct inode *dir,
                goto error_key;
        }
 
-       if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
+       down_write(&dvnode->validate_lock);
+       if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
+           dvnode->status.data_version == data_version)
                afs_edit_dir_add(dvnode, &dentry->d_name, &vnode->fid,
                                 afs_edit_dir_for_link);
+       up_write(&dvnode->validate_lock);
 
        key_put(key);
        kfree(scb);
@@ -1732,6 +1754,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
        struct afs_status_cb *scb;
        struct afs_vnode *dvnode = AFS_FS_I(dir);
        struct key *key;
+       afs_dataversion_t data_version;
        int ret;
 
        _enter("{%llx:%llu},{%pd},%s",
@@ -1759,7 +1782,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
 
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
-               afs_dataversion_t data_version = dvnode->status.data_version + 1;
+               data_version = dvnode->status.data_version + 1;
 
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(dvnode);
@@ -1780,9 +1803,12 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
                goto error_key;
        }
 
-       if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
+       down_write(&dvnode->validate_lock);
+       if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
+           dvnode->status.data_version == data_version)
                afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
                                 afs_edit_dir_for_symlink);
+       up_write(&dvnode->validate_lock);
 
        key_put(key);
        kfree(scb);
@@ -1812,6 +1838,8 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct dentry *tmp = NULL, *rehash = NULL;
        struct inode *new_inode;
        struct key *key;
+       afs_dataversion_t orig_data_version;
+       afs_dataversion_t new_data_version;
        bool new_negative = d_is_negative(new_dentry);
        int ret;
 
@@ -1890,10 +1918,6 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) {
-               afs_dataversion_t orig_data_version;
-               afs_dataversion_t new_data_version;
-               struct afs_status_cb *new_scb = &scb[1];
-
                orig_data_version = orig_dvnode->status.data_version + 1;
 
                if (orig_dvnode != new_dvnode) {
@@ -1904,7 +1928,6 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        new_data_version = new_dvnode->status.data_version + 1;
                } else {
                        new_data_version = orig_data_version;
-                       new_scb = &scb[0];
                }
 
                while (afs_select_fileserver(&fc)) {
@@ -1912,7 +1935,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        fc.cb_break_2 = afs_calc_vnode_cb_break(new_dvnode);
                        afs_fs_rename(&fc, old_dentry->d_name.name,
                                      new_dvnode, new_dentry->d_name.name,
-                                     &scb[0], new_scb);
+                                     &scb[0], &scb[1]);
                }
 
                afs_vnode_commit_status(&fc, orig_dvnode, fc.cb_break,
@@ -1930,18 +1953,25 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
        if (ret == 0) {
                if (rehash)
                        d_rehash(rehash);
-               if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags))
-                   afs_edit_dir_remove(orig_dvnode, &old_dentry->d_name,
-                                       afs_edit_dir_for_rename_0);
+               down_write(&orig_dvnode->validate_lock);
+               if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags) &&
+                   orig_dvnode->status.data_version == orig_data_version)
+                       afs_edit_dir_remove(orig_dvnode, &old_dentry->d_name,
+                                           afs_edit_dir_for_rename_0);
+               if (orig_dvnode != new_dvnode) {
+                       up_write(&orig_dvnode->validate_lock);
 
-               if (!new_negative &&
-                   test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags))
-                       afs_edit_dir_remove(new_dvnode, &new_dentry->d_name,
-                                           afs_edit_dir_for_rename_1);
+                       down_write(&new_dvnode->validate_lock);
+               }
+               if (test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags) &&
+                   orig_dvnode->status.data_version == new_data_version) {
+                       if (!new_negative)
+                               afs_edit_dir_remove(new_dvnode, &new_dentry->d_name,
+                                                   afs_edit_dir_for_rename_1);
 
-               if (test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags))
                        afs_edit_dir_add(new_dvnode, &new_dentry->d_name,
                                         &vnode->fid, afs_edit_dir_for_rename_2);
+               }
 
                new_inode = d_inode(new_dentry);
                if (new_inode) {
@@ -1957,14 +1987,10 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
                 * Note that if we ever implement RENAME_EXCHANGE, we'll have
                 * to update both dentries with opposing dir versions.
                 */
-               if (new_dvnode != orig_dvnode) {
-                       afs_update_dentry_version(&fc, old_dentry, &scb[1]);
-                       afs_update_dentry_version(&fc, new_dentry, &scb[1]);
-               } else {
-                       afs_update_dentry_version(&fc, old_dentry, &scb[0]);
-                       afs_update_dentry_version(&fc, new_dentry, &scb[0]);
-               }
+               afs_update_dentry_version(&fc, old_dentry, &scb[1]);
+               afs_update_dentry_version(&fc, new_dentry, &scb[1]);
                d_move(old_dentry, new_dentry);
+               up_write(&new_dvnode->validate_lock);
                goto error_tmp;
        }
 
index 361088a5edb98cc2fe75062b85f0daf587c4f904..d94e2b7cddff0bfac21bf01333b177ad752ad447 100644 (file)
@@ -21,6 +21,7 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode
 {
        struct afs_fs_cursor fc;
        struct afs_status_cb *scb;
+       afs_dataversion_t dir_data_version;
        int ret = -ERESTARTSYS;
 
        _enter("%pd,%pd", old, new);
@@ -31,7 +32,7 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode
 
        trace_afs_silly_rename(vnode, false);
        if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
-               afs_dataversion_t dir_data_version = dvnode->status.data_version + 1;
+               dir_data_version = dvnode->status.data_version + 1;
 
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(dvnode);
@@ -54,12 +55,15 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode
                        dvnode->silly_key = key_get(key);
                }
 
-               if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
+               down_write(&dvnode->validate_lock);
+               if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
+                   dvnode->status.data_version == dir_data_version) {
                        afs_edit_dir_remove(dvnode, &old->d_name,
                                            afs_edit_dir_for_silly_0);
-               if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
                        afs_edit_dir_add(dvnode, &new->d_name,
                                         &vnode->fid, afs_edit_dir_for_silly_1);
+               }
+               up_write(&dvnode->validate_lock);
        }
 
        kfree(scb);
@@ -181,10 +185,14 @@ static int afs_do_silly_unlink(struct afs_vnode *dvnode, struct afs_vnode *vnode
                                clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
                        }
                }
-               if (ret == 0 &&
-                   test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
-                       afs_edit_dir_remove(dvnode, &dentry->d_name,
-                                           afs_edit_dir_for_unlink);
+               if (ret == 0) {
+                       down_write(&dvnode->validate_lock);
+                       if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
+                           dvnode->status.data_version == dir_data_version)
+                               afs_edit_dir_remove(dvnode, &dentry->d_name,
+                                                   afs_edit_dir_for_unlink);
+                       up_write(&dvnode->validate_lock);
+               }
        }
 
        kfree(scb);
index e1b9ed679045de54dfbfb857a9bb17d24c28f301..a587767b6ae15a549a57052f389e57381c9599f4 100644 (file)
@@ -117,11 +117,8 @@ out:
               (unsigned int)rtt, ret);
 
        have_result |= afs_fs_probe_done(server);
-       if (have_result) {
-               server->probe.have_result = true;
-               wake_up_var(&server->probe.have_result);
+       if (have_result)
                wake_up_all(&server->probe_wq);
-       }
 }
 
 /*
index 1f9c5d8e6fe5538a0702d00824719bdb7cc90d02..68fc46634346a13270497bbcf87cfb0d99340d02 100644 (file)
@@ -65,6 +65,7 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
        bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus);
        u64 data_version, size;
        u32 type, abort_code;
+       int ret;
 
        abort_code = ntohl(xdr->abort_code);
 
@@ -78,7 +79,7 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
                         */
                        status->abort_code = abort_code;
                        scb->have_error = true;
-                       return 0;
+                       goto good;
                }
 
                pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
@@ -87,7 +88,8 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
 
        if (abort_code != 0 && inline_error) {
                status->abort_code = abort_code;
-               return 0;
+               scb->have_error = true;
+               goto good;
        }
 
        type = ntohl(xdr->type);
@@ -123,13 +125,16 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
        data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
        status->data_version = data_version;
        scb->have_status = true;
-
+good:
+       ret = 0;
+advance:
        *_bp = (const void *)*_bp + sizeof(*xdr);
-       return 0;
+       return ret;
 
 bad:
        xdr_dump_bad(*_bp);
-       return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
+       ret = afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
+       goto advance;
 }
 
 static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry)
@@ -981,16 +986,16 @@ static int afs_deliver_fs_rename(struct afs_call *call)
        if (ret < 0)
                return ret;
 
-       /* unmarshall the reply once we've received all of it */
+       /* If the two dirs are the same, we have two copies of the same status
+        * report, so we just decode it twice.
+        */
        bp = call->buffer;
        ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
        if (ret < 0)
                return ret;
-       if (call->out_dir_scb != call->out_scb) {
-               ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
-               if (ret < 0)
-                       return ret;
-       }
+       ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
+       if (ret < 0)
+               return ret;
        xdr_decode_AFSVolSync(&bp, call->out_volsync);
 
        _leave(" = 0 [done]");
index ef732dd4e7ef54a2beb08b1adcae0fabd25db950..80255513e2307ab1ab015292a37f8dd4f9e60bdf 100644 (file)
@@ -533,12 +533,10 @@ struct afs_server {
                u32             abort_code;
                u32             cm_epoch;
                short           error;
-               bool            have_result;
                bool            responded:1;
                bool            is_yfs:1;
                bool            not_yfs:1;
                bool            local_failure:1;
-               bool            no_epoch:1;
                bool            cm_probed:1;
                bool            said_rebooted:1;
                bool            said_inconsistent:1;
@@ -1335,7 +1333,7 @@ extern struct afs_volume *afs_create_volume(struct afs_fs_context *);
 extern void afs_activate_volume(struct afs_volume *);
 extern void afs_deactivate_volume(struct afs_volume *);
 extern void afs_put_volume(struct afs_cell *, struct afs_volume *);
-extern int afs_check_volume_status(struct afs_volume *, struct key *);
+extern int afs_check_volume_status(struct afs_volume *, struct afs_fs_cursor *);
 
 /*
  * write.c
index 172ba569cd602b0544d7b763b7f20c2bf6d7d8cd..2a3305e42b145cc1a5ea336092793a302c79ee4a 100644 (file)
@@ -192,7 +192,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
                        write_unlock(&vnode->volume->servers_lock);
 
                        set_bit(AFS_VOLUME_NEEDS_UPDATE, &vnode->volume->flags);
-                       error = afs_check_volume_status(vnode->volume, fc->key);
+                       error = afs_check_volume_status(vnode->volume, fc);
                        if (error < 0)
                                goto failed_set_error;
 
@@ -281,7 +281,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
 
                        set_bit(AFS_VOLUME_WAIT, &vnode->volume->flags);
                        set_bit(AFS_VOLUME_NEEDS_UPDATE, &vnode->volume->flags);
-                       error = afs_check_volume_status(vnode->volume, fc->key);
+                       error = afs_check_volume_status(vnode->volume, fc);
                        if (error < 0)
                                goto failed_set_error;
 
@@ -341,7 +341,7 @@ start:
        /* See if we need to do an update of the volume record.  Note that the
         * volume may have moved or even have been deleted.
         */
-       error = afs_check_volume_status(vnode->volume, fc->key);
+       error = afs_check_volume_status(vnode->volume, fc);
        if (error < 0)
                goto failed_set_error;
 
index b7f3cb2130caee38a6458d3d81422f83637698f7..11b90ac7ea30f57c88d2a048bee657341637a942 100644 (file)
@@ -594,12 +594,9 @@ retry:
        }
 
        ret = wait_on_bit(&server->flags, AFS_SERVER_FL_UPDATING,
-                         TASK_INTERRUPTIBLE);
+                         (fc->flags & AFS_FS_CURSOR_INTR) ?
+                         TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
        if (ret == -ERESTARTSYS) {
-               if (!(fc->flags & AFS_FS_CURSOR_INTR) && server->addresses) {
-                       _leave(" = t [intr]");
-                       return true;
-               }
                fc->error = ret;
                _leave(" = f [intr]");
                return false;
index 9a5ce9687779cb55b854689b429ba83447b1da9f..72eacc14e6e1b14eed726d18e669dd0255ae0879 100644 (file)
@@ -302,8 +302,8 @@ static void afs_vl_dump_edestaddrreq(const struct afs_vl_cursor *vc)
                                pr_notice("VC:  - nr=%u/%u/%u pf=%u\n",
                                          a->nr_ipv4, a->nr_addrs, a->max_addrs,
                                          a->preferred);
-                               pr_notice("VC:  - pr=%lx R=%lx F=%lx\n",
-                                         a->probed, a->responded, a->failed);
+                               pr_notice("VC:  - R=%lx F=%lx\n",
+                                         a->responded, a->failed);
                                if (a == vc->ac.alist)
                                        pr_notice("VC:  - current\n");
                        }
index 92ca5e27573b7a1d345f7edbc329206cbf548d69..4310336b9bb8c10543c0157950d4b19d2a4d0eab 100644 (file)
@@ -281,7 +281,7 @@ error:
 /*
  * Make sure the volume record is up to date.
  */
-int afs_check_volume_status(struct afs_volume *volume, struct key *key)
+int afs_check_volume_status(struct afs_volume *volume, struct afs_fs_cursor *fc)
 {
        time64_t now = ktime_get_real_seconds();
        int ret, retries = 0;
@@ -299,7 +299,7 @@ retry:
        }
 
        if (!test_and_set_bit_lock(AFS_VOLUME_UPDATING, &volume->flags)) {
-               ret = afs_update_volume_status(volume, key);
+               ret = afs_update_volume_status(volume, fc->key);
                clear_bit_unlock(AFS_VOLUME_WAIT, &volume->flags);
                clear_bit_unlock(AFS_VOLUME_UPDATING, &volume->flags);
                wake_up_bit(&volume->flags, AFS_VOLUME_WAIT);
@@ -312,7 +312,9 @@ retry:
                return 0;
        }
 
-       ret = wait_on_bit(&volume->flags, AFS_VOLUME_WAIT, TASK_INTERRUPTIBLE);
+       ret = wait_on_bit(&volume->flags, AFS_VOLUME_WAIT,
+                         (fc->flags & AFS_FS_CURSOR_INTR) ?
+                         TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
        if (ret == -ERESTARTSYS) {
                _leave(" = %d", ret);
                return ret;
index a26126ac7bf1d17c3b0280c2a54e05609b5d6e0c..b5b45c57e1b1d3f94db891811b2f8e9cb457c837 100644 (file)
@@ -165,15 +165,15 @@ static void xdr_dump_bad(const __be32 *bp)
        int i;
 
        pr_notice("YFS XDR: Bad status record\n");
-       for (i = 0; i < 5 * 4 * 4; i += 16) {
+       for (i = 0; i < 6 * 4 * 4; i += 16) {
                memcpy(x, bp, 16);
                bp += 4;
                pr_notice("%03x: %08x %08x %08x %08x\n",
                          i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3]));
        }
 
-       memcpy(x, bp, 4);
-       pr_notice("0x50: %08x\n", ntohl(x[0]));
+       memcpy(x, bp, 8);
+       pr_notice("0x60: %08x %08x\n", ntohl(x[0]), ntohl(x[1]));
 }
 
 /*
@@ -186,13 +186,14 @@ static int xdr_decode_YFSFetchStatus(const __be32 **_bp,
        const struct yfs_xdr_YFSFetchStatus *xdr = (const void *)*_bp;
        struct afs_file_status *status = &scb->status;
        u32 type;
+       int ret;
 
        status->abort_code = ntohl(xdr->abort_code);
        if (status->abort_code != 0) {
                if (status->abort_code == VNOVNODE)
                        status->nlink = 0;
                scb->have_error = true;
-               return 0;
+               goto good;
        }
 
        type = ntohl(xdr->type);
@@ -220,13 +221,16 @@ static int xdr_decode_YFSFetchStatus(const __be32 **_bp,
        status->size            = xdr_to_u64(xdr->size);
        status->data_version    = xdr_to_u64(xdr->data_version);
        scb->have_status        = true;
-
+good:
+       ret = 0;
+advance:
        *_bp += xdr_size(xdr);
-       return 0;
+       return ret;
 
 bad:
        xdr_dump_bad(*_bp);
-       return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
+       ret = afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
+       goto advance;
 }
 
 /*
@@ -1153,11 +1157,9 @@ static int yfs_deliver_fs_rename(struct afs_call *call)
        ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
        if (ret < 0)
                return ret;
-       if (call->out_dir_scb != call->out_scb) {
-               ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
-               if (ret < 0)
-                       return ret;
-       }
+       ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
+       if (ret < 0)
+               return ret;
 
        xdr_decode_YFSVolSync(&bp, call->out_volsync);
        _leave(" = 0 [done]");
index 52b6f646cdbd0af27d827d9e4d983ec1455c87f0..93672c3f1c78c886eaeffaff6746bf2ee2937d99 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/module.h>
 #include <linux/blkpg.h>
 #include <linux/magic.h>
-#include <linux/dax.h>
 #include <linux/buffer_head.h>
 #include <linux/swap.h>
 #include <linux/pagevec.h>
@@ -1893,6 +1892,16 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
        struct gendisk *disk = bdev->bd_disk;
        struct block_device *victim = NULL;
 
+       /*
+        * Sync early if it looks like we're the last one.  If someone else
+        * opens the block device between now and the decrement of bd_openers
+        * then we did a sync that we didn't need to, but that's not the end
+        * of the world and we want to avoid long (could be several minute)
+        * syncs while holding the mutex.
+        */
+       if (bdev->bd_openers == 1)
+               sync_blockdev(bdev);
+
        mutex_lock_nested(&bdev->bd_mutex, for_part);
        if (for_part)
                bdev->bd_part_count--;
index 9c380e7edf629155af9a351873f4b7c615888bfb..0cc02577577bc98ddc3a68f53be308f4a6fcf62c 100644 (file)
@@ -391,7 +391,7 @@ static int is_shared_data_backref(struct preftrees *preftrees, u64 bytenr)
        struct rb_node **p = &preftrees->direct.root.rb_root.rb_node;
        struct rb_node *parent = NULL;
        struct prelim_ref *ref = NULL;
-       struct prelim_ref target = {0};
+       struct prelim_ref target = {};
        int result;
 
        target.parent = bytenr;
index 786849fcc319ade0c53d82338acffc626566ff98..696f47103cfc93b9234d1bb9e27f06be49a1495c 100644 (file)
@@ -916,7 +916,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
        path = btrfs_alloc_path();
        if (!path) {
                ret = -ENOMEM;
-               goto out;
+               goto out_put_group;
        }
 
        /*
@@ -954,7 +954,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                ret = btrfs_orphan_add(trans, BTRFS_I(inode));
                if (ret) {
                        btrfs_add_delayed_iput(inode);
-                       goto out;
+                       goto out_put_group;
                }
                clear_nlink(inode);
                /* One for the block groups ref */
@@ -977,13 +977,13 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 
        ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
        if (ret < 0)
-               goto out;
+               goto out_put_group;
        if (ret > 0)
                btrfs_release_path(path);
        if (ret == 0) {
                ret = btrfs_del_item(trans, tree_root, path);
                if (ret)
-                       goto out;
+                       goto out_put_group;
                btrfs_release_path(path);
        }
 
@@ -1102,9 +1102,9 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 
        ret = remove_block_group_free_space(trans, block_group);
        if (ret)
-               goto out;
+               goto out_put_group;
 
-       btrfs_put_block_group(block_group);
+       /* Once for the block groups rbtree */
        btrfs_put_block_group(block_group);
 
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
@@ -1127,6 +1127,10 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                /* once for the tree */
                free_extent_map(em);
        }
+
+out_put_group:
+       /* Once for the lookup reference */
+       btrfs_put_block_group(block_group);
 out:
        if (remove_rsv)
                btrfs_delayed_refs_rsv_release(fs_info, 1);
@@ -1288,11 +1292,15 @@ static bool clean_pinned_extents(struct btrfs_trans_handle *trans,
        if (ret)
                goto err;
        mutex_unlock(&fs_info->unused_bg_unpin_mutex);
+       if (prev_trans)
+               btrfs_put_transaction(prev_trans);
 
        return true;
 
 err:
        mutex_unlock(&fs_info->unused_bg_unpin_mutex);
+       if (prev_trans)
+               btrfs_put_transaction(prev_trans);
        btrfs_dec_block_group_ro(bg);
        return false;
 }
@@ -3370,6 +3378,7 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
                            space_info->bytes_reserved > 0 ||
                            space_info->bytes_may_use > 0))
                        btrfs_dump_space_info(info, space_info, 0, 0);
+               WARN_ON(space_info->reclaim_size > 0);
                list_del(&space_info->list);
                btrfs_sysfs_remove_space_info(space_info);
        }
index 21a15776dac421273316740a4d1741045a1134e6..353228d62f5a1232bea3363d3f702aa9b4ee842b 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 
 #ifndef BTRFS_DISCARD_H
 #define BTRFS_DISCARD_H
index a6cb5cbbdb9f56a849cacceba0b96b3ee825cb97..d10c7be10f3b80158201c81707c116e9b9ab9e42 100644 (file)
@@ -2036,9 +2036,6 @@ void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info)
                for (i = 0; i < ret; i++)
                        btrfs_drop_and_free_fs_root(fs_info, gang[i]);
        }
-
-       if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state))
-               btrfs_free_log_root_tree(NULL, fs_info);
 }
 
 static void btrfs_init_scrub(struct btrfs_fs_info *fs_info)
@@ -3888,7 +3885,7 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info,
        spin_unlock(&fs_info->fs_roots_radix_lock);
 
        if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) {
-               btrfs_free_log(NULL, root);
+               ASSERT(root->log_root == NULL);
                if (root->reloc_root) {
                        btrfs_put_root(root->reloc_root);
                        root->reloc_root = NULL;
@@ -4211,6 +4208,36 @@ static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info)
        up_write(&fs_info->cleanup_work_sem);
 }
 
+static void btrfs_drop_all_logs(struct btrfs_fs_info *fs_info)
+{
+       struct btrfs_root *gang[8];
+       u64 root_objectid = 0;
+       int ret;
+
+       spin_lock(&fs_info->fs_roots_radix_lock);
+       while ((ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix,
+                                            (void **)gang, root_objectid,
+                                            ARRAY_SIZE(gang))) != 0) {
+               int i;
+
+               for (i = 0; i < ret; i++)
+                       gang[i] = btrfs_grab_root(gang[i]);
+               spin_unlock(&fs_info->fs_roots_radix_lock);
+
+               for (i = 0; i < ret; i++) {
+                       if (!gang[i])
+                               continue;
+                       root_objectid = gang[i]->root_key.objectid;
+                       btrfs_free_log(NULL, gang[i]);
+                       btrfs_put_root(gang[i]);
+               }
+               root_objectid++;
+               spin_lock(&fs_info->fs_roots_radix_lock);
+       }
+       spin_unlock(&fs_info->fs_roots_radix_lock);
+       btrfs_free_log_root_tree(NULL, fs_info);
+}
+
 static void btrfs_destroy_ordered_extents(struct btrfs_root *root)
 {
        struct btrfs_ordered_extent *ordered;
@@ -4603,6 +4630,7 @@ static int btrfs_cleanup_transaction(struct btrfs_fs_info *fs_info)
        btrfs_destroy_delayed_inodes(fs_info);
        btrfs_assert_delayed_root_empty(fs_info);
        btrfs_destroy_all_delalloc_inodes(fs_info);
+       btrfs_drop_all_logs(fs_info);
        mutex_unlock(&fs_info->transaction_kthread_mutex);
 
        return 0;
index 8a144f9cb7ac756fd1883568ab10b3bbb37b7e53..719e68ab552c52f3a2647d0b9ae8fcf38c9697a1 100644 (file)
@@ -2097,6 +2097,21 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 
        atomic_inc(&root->log_batch);
 
+       /*
+        * If the inode needs a full sync, make sure we use a full range to
+        * avoid log tree corruption, due to hole detection racing with ordered
+        * extent completion for adjacent ranges and races between logging and
+        * completion of ordered extents for adjancent ranges - both races
+        * could lead to file extent items in the log with overlapping ranges.
+        * Do this while holding the inode lock, to avoid races with other
+        * tasks.
+        */
+       if (test_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
+                    &BTRFS_I(inode)->runtime_flags)) {
+               start = 0;
+               end = LLONG_MAX;
+       }
+
        /*
         * Before we acquired the inode's lock, someone may have dirtied more
         * pages in the target range. We need to make sure that writeback for
index d1973141d3bb819ed90d7aaa43f67f470ef40e1e..040009d1cc317f99f41e5a98a729714ce256fb51 100644 (file)
@@ -264,6 +264,7 @@ copy_inline_extent:
                            size);
        inode_add_bytes(dst, datal);
        set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &BTRFS_I(dst)->runtime_flags);
+       ret = btrfs_inode_set_file_extent_range(BTRFS_I(dst), 0, aligned_end);
 out:
        if (!ret && !trans) {
                /*
index f65595602aa87712e3a6e43c2cc0095941c328a9..03bc7134e8cbf4282d3b872b5544b4b7750ea6fc 100644 (file)
@@ -611,8 +611,8 @@ static int should_ignore_root(struct btrfs_root *root)
        if (!reloc_root)
                return 0;
 
-       if (btrfs_root_last_snapshot(&reloc_root->root_item) ==
-           root->fs_info->running_transaction->transid - 1)
+       if (btrfs_header_generation(reloc_root->commit_root) ==
+           root->fs_info->running_transaction->transid)
                return 0;
        /*
         * if there is reloc tree and it was created in previous
@@ -1527,8 +1527,7 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,
        int clear_rsv = 0;
        int ret;
 
-       if (!rc || !rc->create_reloc_tree ||
-           root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID)
+       if (!rc)
                return 0;
 
        /*
@@ -1538,12 +1537,28 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,
        if (reloc_root_is_dead(root))
                return 0;
 
+       /*
+        * This is subtle but important.  We do not do
+        * record_root_in_transaction for reloc roots, instead we record their
+        * corresponding fs root, and then here we update the last trans for the
+        * reloc root.  This means that we have to do this for the entire life
+        * of the reloc root, regardless of which stage of the relocation we are
+        * in.
+        */
        if (root->reloc_root) {
                reloc_root = root->reloc_root;
                reloc_root->last_trans = trans->transid;
                return 0;
        }
 
+       /*
+        * We are merging reloc roots, we do not need new reloc trees.  Also
+        * reloc trees never need their own reloc tree.
+        */
+       if (!rc->create_reloc_tree ||
+           root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID)
+               return 0;
+
        if (!trans->reloc_reserved) {
                rsv = trans->block_rsv;
                trans->block_rsv = rc->block_rsv;
@@ -4544,6 +4559,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
                if (IS_ERR(fs_root)) {
                        err = PTR_ERR(fs_root);
                        list_add_tail(&reloc_root->root_list, &reloc_roots);
+                       btrfs_end_transaction(trans);
                        goto out_unset;
                }
 
index 8b0fe053a25dadc5bc836f58a65e1c607d48340e..ff17a44203588c8ea98f7bbbbc35c8a5fd73431d 100644 (file)
@@ -361,6 +361,16 @@ int btrfs_can_overcommit(struct btrfs_fs_info *fs_info,
        return 0;
 }
 
+static void remove_ticket(struct btrfs_space_info *space_info,
+                         struct reserve_ticket *ticket)
+{
+       if (!list_empty(&ticket->list)) {
+               list_del_init(&ticket->list);
+               ASSERT(space_info->reclaim_size >= ticket->bytes);
+               space_info->reclaim_size -= ticket->bytes;
+       }
+}
+
 /*
  * This is for space we already have accounted in space_info->bytes_may_use, so
  * basically when we're returning space from block_rsv's.
@@ -388,9 +398,7 @@ again:
                        btrfs_space_info_update_bytes_may_use(fs_info,
                                                              space_info,
                                                              ticket->bytes);
-                       list_del_init(&ticket->list);
-                       ASSERT(space_info->reclaim_size >= ticket->bytes);
-                       space_info->reclaim_size -= ticket->bytes;
+                       remove_ticket(space_info, ticket);
                        ticket->bytes = 0;
                        space_info->tickets_id++;
                        wake_up(&ticket->wait);
@@ -899,7 +907,7 @@ static bool maybe_fail_all_tickets(struct btrfs_fs_info *fs_info,
                        btrfs_info(fs_info, "failing ticket with %llu bytes",
                                   ticket->bytes);
 
-               list_del_init(&ticket->list);
+               remove_ticket(space_info, ticket);
                ticket->error = -ENOSPC;
                wake_up(&ticket->wait);
 
@@ -1063,7 +1071,7 @@ static void wait_reserve_ticket(struct btrfs_fs_info *fs_info,
                         * despite getting an error, resulting in a space leak
                         * (bytes_may_use counter of our space_info).
                         */
-                       list_del_init(&ticket->list);
+                       remove_ticket(space_info, ticket);
                        ticket->error = -EINTR;
                        break;
                }
@@ -1121,7 +1129,7 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info,
                 * either the async reclaim job deletes the ticket from the list
                 * or we delete it ourselves at wait_reserve_ticket().
                 */
-               list_del_init(&ticket->list);
+               remove_ticket(space_info, ticket);
                if (!ret)
                        ret = -ENOSPC;
        }
index 8cede6eb9843c73f432325dbfd98af132c2563ba..2d5498136e5ef82798ece5a9230e3b72204b3513 100644 (file)
@@ -662,10 +662,19 @@ again:
        }
 
 got_it:
-       btrfs_record_root_in_trans(h, root);
-
        if (!current->journal_info)
                current->journal_info = h;
+
+       /*
+        * btrfs_record_root_in_trans() needs to alloc new extents, and may
+        * call btrfs_join_transaction() while we're also starting a
+        * transaction.
+        *
+        * Thus it need to be called after current->journal_info initialized,
+        * or we can deadlock.
+        */
+       btrfs_record_root_in_trans(h, root);
+
        return h;
 
 join_fail:
index 58c111474ba5bb5d0630bea17f85d1ad6927ddb6..02ebdd9edc193512ba58b29002d0d53e86fa4510 100644 (file)
@@ -96,8 +96,8 @@ enum {
 static int btrfs_log_inode(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root, struct btrfs_inode *inode,
                           int inode_only,
-                          u64 start,
-                          u64 end,
+                          const loff_t start,
+                          const loff_t end,
                           struct btrfs_log_ctx *ctx);
 static int link_to_fixup_dir(struct btrfs_trans_handle *trans,
                             struct btrfs_root *root,
@@ -4226,6 +4226,9 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans,
        const u64 ino = btrfs_ino(inode);
        struct btrfs_path *dst_path = NULL;
        bool dropped_extents = false;
+       u64 truncate_offset = i_size;
+       struct extent_buffer *leaf;
+       int slot;
        int ins_nr = 0;
        int start_slot;
        int ret;
@@ -4240,9 +4243,43 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans,
        if (ret < 0)
                goto out;
 
+       /*
+        * We must check if there is a prealloc extent that starts before the
+        * i_size and crosses the i_size boundary. This is to ensure later we
+        * truncate down to the end of that extent and not to the i_size, as
+        * otherwise we end up losing part of the prealloc extent after a log
+        * replay and with an implicit hole if there is another prealloc extent
+        * that starts at an offset beyond i_size.
+        */
+       ret = btrfs_previous_item(root, path, ino, BTRFS_EXTENT_DATA_KEY);
+       if (ret < 0)
+               goto out;
+
+       if (ret == 0) {
+               struct btrfs_file_extent_item *ei;
+
+               leaf = path->nodes[0];
+               slot = path->slots[0];
+               ei = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
+
+               if (btrfs_file_extent_type(leaf, ei) ==
+                   BTRFS_FILE_EXTENT_PREALLOC) {
+                       u64 extent_end;
+
+                       btrfs_item_key_to_cpu(leaf, &key, slot);
+                       extent_end = key.offset +
+                               btrfs_file_extent_num_bytes(leaf, ei);
+
+                       if (extent_end > i_size)
+                               truncate_offset = extent_end;
+               }
+       } else {
+               ret = 0;
+       }
+
        while (true) {
-               struct extent_buffer *leaf = path->nodes[0];
-               int slot = path->slots[0];
+               leaf = path->nodes[0];
+               slot = path->slots[0];
 
                if (slot >= btrfs_header_nritems(leaf)) {
                        if (ins_nr > 0) {
@@ -4280,7 +4317,7 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans,
                                ret = btrfs_truncate_inode_items(trans,
                                                         root->log_root,
                                                         &inode->vfs_inode,
-                                                        i_size,
+                                                        truncate_offset,
                                                         BTRFS_EXTENT_DATA_KEY);
                        } while (ret == -EAGAIN);
                        if (ret)
@@ -4533,15 +4570,13 @@ static int btrfs_log_all_xattrs(struct btrfs_trans_handle *trans,
 static int btrfs_log_holes(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root,
                           struct btrfs_inode *inode,
-                          struct btrfs_path *path,
-                          const u64 start,
-                          const u64 end)
+                          struct btrfs_path *path)
 {
        struct btrfs_fs_info *fs_info = root->fs_info;
        struct btrfs_key key;
        const u64 ino = btrfs_ino(inode);
        const u64 i_size = i_size_read(&inode->vfs_inode);
-       u64 prev_extent_end = start;
+       u64 prev_extent_end = 0;
        int ret;
 
        if (!btrfs_fs_incompat(fs_info, NO_HOLES) || i_size == 0)
@@ -4549,21 +4584,14 @@ static int btrfs_log_holes(struct btrfs_trans_handle *trans,
 
        key.objectid = ino;
        key.type = BTRFS_EXTENT_DATA_KEY;
-       key.offset = start;
+       key.offset = 0;
 
        ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
        if (ret < 0)
                return ret;
 
-       if (ret > 0 && path->slots[0] > 0) {
-               btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0] - 1);
-               if (key.objectid == ino && key.type == BTRFS_EXTENT_DATA_KEY)
-                       path->slots[0]--;
-       }
-
        while (true) {
                struct extent_buffer *leaf = path->nodes[0];
-               u64 extent_end;
 
                if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) {
                        ret = btrfs_next_leaf(root, path);
@@ -4580,18 +4608,9 @@ static int btrfs_log_holes(struct btrfs_trans_handle *trans,
                if (key.objectid != ino || key.type != BTRFS_EXTENT_DATA_KEY)
                        break;
 
-               extent_end = btrfs_file_extent_end(path);
-               if (extent_end <= start)
-                       goto next_slot;
-
                /* We have a hole, log it. */
                if (prev_extent_end < key.offset) {
-                       u64 hole_len;
-
-                       if (key.offset >= end)
-                               hole_len = end - prev_extent_end;
-                       else
-                               hole_len = key.offset - prev_extent_end;
+                       const u64 hole_len = key.offset - prev_extent_end;
 
                        /*
                         * Release the path to avoid deadlocks with other code
@@ -4621,20 +4640,16 @@ static int btrfs_log_holes(struct btrfs_trans_handle *trans,
                        leaf = path->nodes[0];
                }
 
-               prev_extent_end = min(extent_end, end);
-               if (extent_end >= end)
-                       break;
-next_slot:
+               prev_extent_end = btrfs_file_extent_end(path);
                path->slots[0]++;
                cond_resched();
        }
 
-       if (prev_extent_end < end && prev_extent_end < i_size) {
+       if (prev_extent_end < i_size) {
                u64 hole_len;
 
                btrfs_release_path(path);
-               hole_len = min(ALIGN(i_size, fs_info->sectorsize), end);
-               hole_len -= prev_extent_end;
+               hole_len = ALIGN(i_size - prev_extent_end, fs_info->sectorsize);
                ret = btrfs_insert_file_extent(trans, root->log_root,
                                               ino, prev_extent_end, 0, 0,
                                               hole_len, 0, hole_len,
@@ -4971,8 +4986,6 @@ static int copy_inode_items_to_log(struct btrfs_trans_handle *trans,
                                   const u64 logged_isize,
                                   const bool recursive_logging,
                                   const int inode_only,
-                                  const u64 start,
-                                  const u64 end,
                                   struct btrfs_log_ctx *ctx,
                                   bool *need_log_inode_item)
 {
@@ -4981,21 +4994,6 @@ static int copy_inode_items_to_log(struct btrfs_trans_handle *trans,
        int ins_nr = 0;
        int ret;
 
-       /*
-        * We must make sure we don't copy extent items that are entirely out of
-        * the range [start, end - 1]. This is not just an optimization to avoid
-        * copying but also needed to avoid a corruption where we end up with
-        * file extent items in the log tree that have overlapping ranges - this
-        * can happen if we race with ordered extent completion for ranges that
-        * are outside our target range. For example we copy an extent item and
-        * when we move to the next leaf, that extent was trimmed and a new one
-        * covering a subrange of it, but with a higher key, was inserted - we
-        * would then copy this other extent too, resulting in a log tree with
-        * 2 extent items that represent overlapping ranges.
-        *
-        * We can copy the entire extents at the range bondaries however, even
-        * if they cover an area outside the target range. That's ok.
-        */
        while (1) {
                ret = btrfs_search_forward(root, min_key, path, trans->transid);
                if (ret < 0)
@@ -5063,29 +5061,6 @@ again:
                        goto next_slot;
                }
 
-               if (min_key->type == BTRFS_EXTENT_DATA_KEY) {
-                       const u64 extent_end = btrfs_file_extent_end(path);
-
-                       if (extent_end <= start) {
-                               if (ins_nr > 0) {
-                                       ret = copy_items(trans, inode, dst_path,
-                                                        path, ins_start_slot,
-                                                        ins_nr, inode_only,
-                                                        logged_isize);
-                                       if (ret < 0)
-                                               return ret;
-                                       ins_nr = 0;
-                               }
-                               goto next_slot;
-                       }
-                       if (extent_end >= end) {
-                               ins_nr++;
-                               if (ins_nr == 1)
-                                       ins_start_slot = path->slots[0];
-                               break;
-                       }
-               }
-
                if (ins_nr && ins_start_slot + ins_nr == path->slots[0]) {
                        ins_nr++;
                        goto next_slot;
@@ -5151,8 +5126,8 @@ next_key:
 static int btrfs_log_inode(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root, struct btrfs_inode *inode,
                           int inode_only,
-                          u64 start,
-                          u64 end,
+                          const loff_t start,
+                          const loff_t end,
                           struct btrfs_log_ctx *ctx)
 {
        struct btrfs_fs_info *fs_info = root->fs_info;
@@ -5180,9 +5155,6 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
                return -ENOMEM;
        }
 
-       start = ALIGN_DOWN(start, fs_info->sectorsize);
-       end = ALIGN(end, fs_info->sectorsize);
-
        min_key.objectid = ino;
        min_key.type = BTRFS_INODE_ITEM_KEY;
        min_key.offset = 0;
@@ -5298,8 +5270,8 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
 
        err = copy_inode_items_to_log(trans, inode, &min_key, &max_key,
                                      path, dst_path, logged_isize,
-                                     recursive_logging, inode_only,
-                                     start, end, ctx, &need_log_inode_item);
+                                     recursive_logging, inode_only, ctx,
+                                     &need_log_inode_item);
        if (err)
                goto out_unlock;
 
@@ -5312,7 +5284,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
        if (max_key.type >= BTRFS_EXTENT_DATA_KEY && !fast_search) {
                btrfs_release_path(path);
                btrfs_release_path(dst_path);
-               err = btrfs_log_holes(trans, root, inode, path, start, end);
+               err = btrfs_log_holes(trans, root, inode, path);
                if (err)
                        goto out_unlock;
        }
index f73276d746bbfc7f2c98bf057938cc5f6c5e8ef0..a60f60396cfa06efb622d2bea25261bf0ea0771a 100644 (file)
@@ -967,7 +967,7 @@ grow_dev_page(struct block_device *bdev, sector_t block,
        struct page *page;
        struct buffer_head *bh;
        sector_t end_block;
-       int ret = 0;            /* Will call free_more_memory() */
+       int ret = 0;
        gfp_t gfp_mask;
 
        gfp_mask = mapping_gfp_constraint(inode->i_mapping, ~__GFP_FS) | gfp;
@@ -1371,6 +1371,17 @@ void __breadahead(struct block_device *bdev, sector_t block, unsigned size)
 }
 EXPORT_SYMBOL(__breadahead);
 
+void __breadahead_gfp(struct block_device *bdev, sector_t block, unsigned size,
+                     gfp_t gfp)
+{
+       struct buffer_head *bh = __getblk_gfp(bdev, block, size, gfp);
+       if (likely(bh)) {
+               ll_rw_block(REQ_OP_READ, REQ_RAHEAD, 1, &bh);
+               brelse(bh);
+       }
+}
+EXPORT_SYMBOL(__breadahead_gfp);
+
 /**
  *  __bread_gfp() - reads a specified block and returns the bh
  *  @bdev: the block_device to read from
index 185db76300b31c2d71a68fa6065752620d32689d..5f3aa4d607def2fd104a8c2349f37555cb53cfc3 100644 (file)
@@ -2749,7 +2749,7 @@ int ceph_try_get_caps(struct inode *inode, int need, int want,
 
        ret = try_get_cap_refs(inode, need, want, 0, flags, got);
        /* three special error codes */
-       if (ret == -EAGAIN || ret == -EFBIG || ret == -EAGAIN)
+       if (ret == -EAGAIN || ret == -EFBIG || ret == -ESTALE)
                ret = 0;
        return ret;
 }
@@ -3746,6 +3746,7 @@ retry:
                WARN_ON(1);
                tsession = NULL;
                target = -1;
+               mutex_lock(&session->s_mutex);
        }
        goto retry;
 
index 481ac97b4d25bd89d3d0390ad032c0a47220c2ee..dcaed75de9e6a095fb72b53c04c9567feb3c9545 100644 (file)
@@ -271,7 +271,7 @@ void ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
                                    &congestion_kb_fops);
 
        snprintf(name, sizeof(name), "../../bdi/%s",
-                dev_name(fsc->sb->s_bdi->dev));
+                bdi_dev_name(fsc->sb->s_bdi));
        fsc->debugfs_bdi =
                debugfs_create_symlink("bdi",
                                       fsc->client->debugfs_dir,
index d594c26274305ac44d46c647545b503c787232bc..4c4202c93b7151ea120cf49ba6545d8c7c8d9753 100644 (file)
@@ -1051,8 +1051,8 @@ static void ceph_async_unlink_cb(struct ceph_mds_client *mdsc,
 
        /* If op failed, mark everyone involved for errors */
        if (result) {
-               int pathlen;
-               u64 base;
+               int pathlen = 0;
+               u64 base = 0;
                char *path = ceph_mdsc_build_path(req->r_dentry, &pathlen,
                                                  &base, 0);
 
index 4a5ccbb7e808e40800f4133f898cece536a908b5..afdfca965a7fc59a12befb6731409e4155a6081f 100644 (file)
@@ -527,8 +527,8 @@ static void ceph_async_create_cb(struct ceph_mds_client *mdsc,
 
        if (result) {
                struct dentry *dentry = req->r_dentry;
-               int pathlen;
-               u64 base;
+               int pathlen = 0;
+               u64 base = 0;
                char *path = ceph_mdsc_build_path(req->r_dentry, &pathlen,
                                                  &base, 0);
 
index 486f91f9685b1748622a0c9ced523cc97344d163..7c63abf5bea91f5bded40475e2460f240f08ca2c 100644 (file)
@@ -3251,8 +3251,7 @@ static void handle_session(struct ceph_mds_session *session,
        void *end = p + msg->front.iov_len;
        struct ceph_mds_session_head *h;
        u32 op;
-       u64 seq;
-       unsigned long features = 0;
+       u64 seq, features = 0;
        int wake = 0;
        bool blacklisted = false;
 
@@ -3271,9 +3270,8 @@ static void handle_session(struct ceph_mds_session *session,
                        goto bad;
                /* version >= 3, feature bits */
                ceph_decode_32_safe(&p, end, len, bad);
-               ceph_decode_need(&p, end, len, bad);
-               memcpy(&features, p, min_t(size_t, len, sizeof(features)));
-               p += len;
+               ceph_decode_64_safe(&p, end, features, bad);
+               p += len - sizeof(features);
        }
 
        mutex_lock(&mdsc->mutex);
index 4e5be79bf0803bdb647b5612db76676766999165..903d9edfd4bf203f83b654e3c328901fb23b3d1b 100644 (file)
@@ -521,7 +521,7 @@ extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc);
 
 static inline void ceph_mdsc_free_path(char *path, int len)
 {
-       if (path)
+       if (!IS_ERR_OR_NULL(path))
                __putname(path - (PATH_MAX - 1 - len));
 }
 
index de56dee60540bae9aad7bf45c995a529d43dfd0b..19507e2fdb57fe70526fb01485b81a4413fff47a 100644 (file)
@@ -159,8 +159,8 @@ static struct inode *lookup_quotarealm_inode(struct ceph_mds_client *mdsc,
        }
 
        if (IS_ERR(in)) {
-               pr_warn("Can't lookup inode %llx (err: %ld)\n",
-                       realm->ino, PTR_ERR(in));
+               dout("Can't lookup inode %llx (err: %ld)\n",
+                    realm->ino, PTR_ERR(in));
                qri->timeout = jiffies + msecs_to_jiffies(60 * 1000); /* XXX */
        } else {
                qri->timeout = 0;
index 05dd3dea684b478048deca2132be96b64af69ac4..39b708d9d86d069aa873d6a18fffbfba4fb0f028 100644 (file)
@@ -1891,7 +1891,8 @@ GLOBAL_EXTERN struct list_head            cifs_tcp_ses_list;
 /*
  * This lock protects the cifs_tcp_ses_list, the list of smb sessions per
  * tcp session, and the list of tcon's per smb session. It also protects
- * the reference counters for the server, smb session, and tcon. Finally,
+ * the reference counters for the server, smb session, and tcon. It also
+ * protects some fields in the TCP_Server_Info struct such as dstaddr. Finally,
  * changes to the tcon->tidStatus should be done while holding this lock.
  * generally the locks should be taken in order tcp_ses_lock before
  * tcon->open_file_lock and that before file->file_info_lock since the
index 140efc1a937469e73ac801820625ad18ab01705d..182b864b3075bdd1f0b079f9047c8a0f4a5d796d 100644 (file)
@@ -594,6 +594,8 @@ decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
                               cifs_max_pending);
        set_credits(server, server->maxReq);
        server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
+       /* set up max_read for readpages check */
+       server->max_read = server->maxBuf;
        /* even though we do not use raw we might as well set this
        accurately, in case we ever find a need for it */
        if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
@@ -755,6 +757,8 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
        set_credits(server, server->maxReq);
        /* probably no need to store and check maxvcs */
        server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
+       /* set up max_read for readpages check */
+       server->max_read = server->maxBuf;
        server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
        cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
        server->capabilities = le32_to_cpu(pSMBr->Capabilities);
index 95b3ab0ca8c0859ab145f32a2ad37858b3294d7f..28268ed461b8286fb302ed732b47b2776b10209a 100644 (file)
@@ -375,8 +375,10 @@ static int reconn_set_ipaddr(struct TCP_Server_Info *server)
                return rc;
        }
 
+       spin_lock(&cifs_tcp_ses_lock);
        rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
                                  strlen(ipaddr));
+       spin_unlock(&cifs_tcp_ses_lock);
        kfree(ipaddr);
 
        return !rc ? -1 : 0;
@@ -3373,6 +3375,10 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
        spin_lock(&cifs_tcp_ses_lock);
        list_for_each(tmp, &ses->tcon_list) {
                tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
+#ifdef CONFIG_CIFS_DFS_UPCALL
+               if (tcon->dfs_path)
+                       continue;
+#endif
                if (!match_tcon(tcon, volume_info))
                        continue;
                ++tcon->tc_count;
index 8fbbdcdad8ffa89fda849927cec56fdb7666fda6..390d2b15ef6ef9d7014e90069cdad3d2880806d3 100644 (file)
@@ -61,7 +61,7 @@ static void cifs_set_ops(struct inode *inode)
                }
 
                /* check if server can support readpages */
-               if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf <
+               if (cifs_sb_master_tcon(cifs_sb)->ses->server->max_read <
                                PAGE_SIZE + MAX_CIFS_HDR_SIZE)
                        inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
                else
index a456febd4109ba41ad795fcafa672e2e47c2aafa..550ce9020a3eebe8e3cd5a8f216284aa545b024b 100644 (file)
@@ -1025,51 +1025,99 @@ int copy_path_name(char *dst, const char *src)
 }
 
 struct super_cb_data {
-       struct TCP_Server_Info *server;
+       void *data;
        struct super_block *sb;
 };
 
-static void super_cb(struct super_block *sb, void *arg)
+static void tcp_super_cb(struct super_block *sb, void *arg)
 {
-       struct super_cb_data *d = arg;
+       struct super_cb_data *sd = arg;
+       struct TCP_Server_Info *server = sd->data;
        struct cifs_sb_info *cifs_sb;
        struct cifs_tcon *tcon;
 
-       if (d->sb)
+       if (sd->sb)
                return;
 
        cifs_sb = CIFS_SB(sb);
        tcon = cifs_sb_master_tcon(cifs_sb);
-       if (tcon->ses->server == d->server)
-               d->sb = sb;
+       if (tcon->ses->server == server)
+               sd->sb = sb;
 }
 
-struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server)
+static struct super_block *__cifs_get_super(void (*f)(struct super_block *, void *),
+                                           void *data)
 {
-       struct super_cb_data d = {
-               .server = server,
+       struct super_cb_data sd = {
+               .data = data,
                .sb = NULL,
        };
 
-       iterate_supers_type(&cifs_fs_type, super_cb, &d);
+       iterate_supers_type(&cifs_fs_type, f, &sd);
 
-       if (unlikely(!d.sb))
-               return ERR_PTR(-ENOENT);
+       if (!sd.sb)
+               return ERR_PTR(-EINVAL);
        /*
         * Grab an active reference in order to prevent automounts (DFS links)
         * of expiring and then freeing up our cifs superblock pointer while
         * we're doing failover.
         */
-       cifs_sb_active(d.sb);
-       return d.sb;
+       cifs_sb_active(sd.sb);
+       return sd.sb;
 }
 
-void cifs_put_tcp_super(struct super_block *sb)
+static void __cifs_put_super(struct super_block *sb)
 {
        if (!IS_ERR_OR_NULL(sb))
                cifs_sb_deactive(sb);
 }
 
+struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server)
+{
+       return __cifs_get_super(tcp_super_cb, server);
+}
+
+void cifs_put_tcp_super(struct super_block *sb)
+{
+       __cifs_put_super(sb);
+}
+
+#ifdef CONFIG_CIFS_DFS_UPCALL
+static void tcon_super_cb(struct super_block *sb, void *arg)
+{
+       struct super_cb_data *sd = arg;
+       struct cifs_tcon *tcon = sd->data;
+       struct cifs_sb_info *cifs_sb;
+
+       if (sd->sb)
+               return;
+
+       cifs_sb = CIFS_SB(sb);
+       if (tcon->dfs_path && cifs_sb->origin_fullpath &&
+           !strcasecmp(tcon->dfs_path, cifs_sb->origin_fullpath))
+               sd->sb = sb;
+}
+
+static inline struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon)
+{
+       return __cifs_get_super(tcon_super_cb, tcon);
+}
+
+static inline void cifs_put_tcon_super(struct super_block *sb)
+{
+       __cifs_put_super(sb);
+}
+#else
+static inline struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon)
+{
+       return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline void cifs_put_tcon_super(struct super_block *sb)
+{
+}
+#endif
+
 int update_super_prepath(struct cifs_tcon *tcon, const char *prefix,
                         size_t prefix_len)
 {
@@ -1077,7 +1125,7 @@ int update_super_prepath(struct cifs_tcon *tcon, const char *prefix,
        struct cifs_sb_info *cifs_sb;
        int rc = 0;
 
-       sb = cifs_get_tcp_super(tcon->ses->server);
+       sb = cifs_get_tcon_super(tcon);
        if (IS_ERR(sb))
                return PTR_ERR(sb);
 
@@ -1099,6 +1147,6 @@ int update_super_prepath(struct cifs_tcon *tcon, const char *prefix,
        cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
 
 out:
-       cifs_put_tcp_super(sb);
+       cifs_put_tcon_super(sb);
        return rc;
 }
index b36c46f48705c7cc6c46683313b6b02505fd3ebb..f829f4165d38c1b196481b91d2d172b1c96090ec 100644 (file)
@@ -687,6 +687,11 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
        if (smb3_encryption_required(tcon))
                flags |= CIFS_TRANSFORM_REQ;
 
+       if (!server->ops->new_lease_key)
+               return -EIO;
+
+       server->ops->new_lease_key(pfid);
+
        memset(rqst, 0, sizeof(rqst));
        resp_buftype[0] = resp_buftype[1] = CIFS_NO_BUFFER;
        memset(rsp_iov, 0, sizeof(rsp_iov));
index 47d3e382ecaac269fd447a381dfa1fa56ca61e64..b30aa3cdd845f333304de9fcbdc95f1ae3ec5e99 100644 (file)
@@ -1552,6 +1552,21 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
        }
 
        rc = SMB2_sess_establish_session(sess_data);
+#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
+       if (ses->server->dialect < SMB30_PROT_ID) {
+               cifs_dbg(VFS, "%s: dumping generated SMB2 session keys\n", __func__);
+               /*
+                * The session id is opaque in terms of endianness, so we can't
+                * print it as a long long. we dump it as we got it on the wire
+                */
+               cifs_dbg(VFS, "Session Id    %*ph\n", (int)sizeof(ses->Suid),
+                        &ses->Suid);
+               cifs_dbg(VFS, "Session Key   %*ph\n",
+                        SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);
+               cifs_dbg(VFS, "Signing Key   %*ph\n",
+                        SMB3_SIGN_KEY_SIZE, ses->auth_key.response);
+       }
+#endif
 out:
        kfree(ntlmssp_blob);
        SMB2_sess_free_buffer(sess_data);
index 1a6c227ada8f52597b9d87ae760659290a6502ab..c0348e3b1695828f0178c55d52bd4024b0e8b474 100644 (file)
@@ -660,8 +660,8 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
                return rc;
 
        if (memcmp(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE)) {
-               dump_stack();
-               cifs_dbg(VFS, "sign fail cmd 0x%x message id 0x%llx\n", shdr->Command, shdr->MessageId);
+               cifs_dbg(VFS, "sign fail cmd 0x%x message id 0x%llx\n",
+                       shdr->Command, shdr->MessageId);
                return -EACCES;
        } else
                return 0;
index cf7b7e1d5bd7254fe174ebf22d7a02aeb67bcf35..cb733652ecca6cd0679b57acf3db93efdd4751d4 100644 (file)
@@ -1519,6 +1519,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
                spin_lock(&configfs_dirent_lock);
                configfs_detach_rollback(dentry);
                spin_unlock(&configfs_dirent_lock);
+               config_item_put(parent_item);
                return -EINTR;
        }
        frag->frag_dead = true;
index f8296a82d01dfd70deb38ede24feab53331825bd..478a0d810136adff4dd62ca1013baff51227df5c 100644 (file)
@@ -211,6 +211,8 @@ static int format_corename(struct core_name *cn, struct coredump_params *cprm,
                        return -ENOMEM;
                (*argv)[(*argc)++] = 0;
                ++pat_ptr;
+               if (!(*pat_ptr))
+                       return -ENOMEM;
        }
 
        /* Repeat as long as we have more pattern to process and more output
@@ -786,6 +788,14 @@ void do_coredump(const kernel_siginfo_t *siginfo)
        if (displaced)
                put_files_struct(displaced);
        if (!dump_interrupted()) {
+               /*
+                * umh disabled with CONFIG_STATIC_USERMODEHELPER_PATH="" would
+                * have this set to NULL.
+                */
+               if (!cprm.file) {
+                       pr_info("Core dump to |%s disabled\n", cn.corename);
+                       goto close_fail;
+               }
                file_start_write(cprm.file);
                core_dumped = binfmt->core_dump(&cprm);
                file_end_write(cprm.file);
index 2d357680094cb434a935aa18666756e981270e38..ae49a55bda001bbe3877c0256cfaac6e51d92c13 100644 (file)
@@ -506,20 +506,11 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%llu\n");
  * This function creates a file in debugfs with the given name that
  * contains the value of the variable @value.  If the @mode variable is so
  * set, it can be read from, and written to.
- *
- * 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_u32(const char *name, umode_t mode,
-                                struct dentry *parent, u32 *value)
+void debugfs_create_u32(const char *name, umode_t mode, struct dentry *parent,
+                       u32 *value)
 {
-       return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u32,
+       debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u32,
                                   &fops_u32_ro, &fops_u32_wo);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_u32);
index 8c596641a72b09733920dd12643194e2bd4b3ab1..aba03ee749f88183f91761699d0a022283d12992 100644 (file)
@@ -1171,6 +1171,10 @@ static inline bool chain_epi_lockless(struct epitem *epi)
 {
        struct eventpoll *ep = epi->ep;
 
+       /* Fast preliminary check */
+       if (epi->next != EP_UNACTIVE_PTR)
+               return false;
+
        /* Check that the same epi has not been just chained from another CPU */
        if (cmpxchg(&epi->next, EP_UNACTIVE_PTR, NULL) != EP_UNACTIVE_PTR)
                return false;
@@ -1237,16 +1241,12 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v
         * chained in ep->ovflist and requeued later on.
         */
        if (READ_ONCE(ep->ovflist) != EP_UNACTIVE_PTR) {
-               if (epi->next == EP_UNACTIVE_PTR &&
-                   chain_epi_lockless(epi))
+               if (chain_epi_lockless(epi))
+                       ep_pm_stay_awake_rcu(epi);
+       } else if (!ep_is_linked(epi)) {
+               /* In the usual case, add event to ready list. */
+               if (list_add_tail_lockless(&epi->rdllink, &ep->rdllist))
                        ep_pm_stay_awake_rcu(epi);
-               goto out_unlock;
-       }
-
-       /* If this file is already in the ready list we exit soon */
-       if (!ep_is_linked(epi) &&
-           list_add_tail_lockless(&epi->rdllink, &ep->rdllist)) {
-               ep_pm_stay_awake_rcu(epi);
        }
 
        /*
@@ -1822,7 +1822,6 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
 {
        int res = 0, eavail, timed_out = 0;
        u64 slack = 0;
-       bool waiter = false;
        wait_queue_entry_t wait;
        ktime_t expires, *to = NULL;
 
@@ -1867,21 +1866,23 @@ fetch_events:
         */
        ep_reset_busy_poll_napi_id(ep);
 
-       /*
-        * We don't have any available event to return to the caller.  We need
-        * to sleep here, and we will be woken by ep_poll_callback() when events
-        * become available.
-        */
-       if (!waiter) {
-               waiter = true;
-               init_waitqueue_entry(&wait, current);
-
+       do {
+               /*
+                * Internally init_wait() uses autoremove_wake_function(),
+                * thus wait entry is removed from the wait queue on each
+                * wakeup. Why it is important? In case of several waiters
+                * each new wakeup will hit the next waiter, giving it the
+                * chance to harvest new event. Otherwise wakeup can be
+                * lost. This is also good performance-wise, because on
+                * normal wakeup path no need to call __remove_wait_queue()
+                * explicitly, thus ep->lock is not taken, which halts the
+                * event delivery.
+                */
+               init_wait(&wait);
                write_lock_irq(&ep->lock);
                __add_wait_queue_exclusive(&ep->wq, &wait);
                write_unlock_irq(&ep->lock);
-       }
 
-       for (;;) {
                /*
                 * We don't want to sleep if the ep_poll_callback() sends us
                 * a wakeup in between. That's why we set the task state
@@ -1911,10 +1912,20 @@ fetch_events:
                        timed_out = 1;
                        break;
                }
-       }
+
+               /* We were woken up, thus go and try to harvest some events */
+               eavail = 1;
+
+       } while (0);
 
        __set_current_state(TASK_RUNNING);
 
+       if (!list_empty_careful(&wait.entry)) {
+               write_lock_irq(&ep->lock);
+               __remove_wait_queue(&ep->wq, &wait);
+               write_unlock_irq(&ep->lock);
+       }
+
 send_events:
        /*
         * Try to transfer events to user space. In case we get 0 events and
@@ -1925,12 +1936,6 @@ send_events:
            !(res = ep_send_events(ep, events, maxevents)) && !timed_out)
                goto fetch_events;
 
-       if (waiter) {
-               write_lock_irq(&ep->lock);
-               __remove_wait_queue(&ep->wq, &wait);
-               write_unlock_irq(&ep->lock);
-       }
-
        return res;
 }
 
index 6a04cc02565a1f3823ad9a109238bad9553a82f1..6774a5a6ded8290fb790bf70f04a1c6e3253cd7a 100644 (file)
@@ -91,7 +91,6 @@ static int exfat_allocate_bitmap(struct super_block *sb,
                }
        }
 
-       sbi->pbr_bh = NULL;
        return 0;
 }
 
@@ -137,8 +136,6 @@ void exfat_free_bitmap(struct exfat_sb_info *sbi)
 {
        int i;
 
-       brelse(sbi->pbr_bh);
-
        for (i = 0; i < sbi->map_sectors; i++)
                __brelse(sbi->vol_amap[i]);
 
index 67d4e46fb81003d0c367862ee986b37c80e7fa4e..d67fb8a6f770c28db8f1618c78fde493e2a4b965 100644 (file)
@@ -507,6 +507,7 @@ void exfat_msg(struct super_block *sb, const char *lv, const char *fmt, ...)
                __printf(3, 4) __cold;
 void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
                u8 tz, __le16 time, __le16 date, u8 time_ms);
+void exfat_truncate_atime(struct timespec64 *ts);
 void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
                u8 *tz, __le16 *time, __le16 *date, u8 *time_ms);
 unsigned short exfat_calc_chksum_2byte(void *data, int len,
index 483f683757aa87420ba347afd3c9db9e94b8a14d..4f76764165cf6f63a99c5e192ab33685e8e987b7 100644 (file)
@@ -273,6 +273,7 @@ int exfat_getattr(const struct path *path, struct kstat *stat,
        struct exfat_inode_info *ei = EXFAT_I(inode);
 
        generic_fillattr(inode, stat);
+       exfat_truncate_atime(&stat->atime);
        stat->result_mask |= STATX_BTIME;
        stat->btime.tv_sec = ei->i_crtime.tv_sec;
        stat->btime.tv_nsec = ei->i_crtime.tv_nsec;
@@ -339,6 +340,7 @@ int exfat_setattr(struct dentry *dentry, struct iattr *attr)
        }
 
        setattr_copy(inode, attr);
+       exfat_truncate_atime(&inode->i_atime);
        mark_inode_dirty(inode);
 
 out:
index 14a3300848f6a0fb754b9d34bdacbc31b90f5d07..ebd2cbe3cbc11c2aede3819c414020b9344ec1f9 100644 (file)
@@ -88,7 +88,8 @@ void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
        if (time_ms) {
                ts->tv_sec += time_ms / 100;
                ts->tv_nsec = (time_ms % 100) * 10 * NSEC_PER_MSEC;
-       }
+       } else
+               ts->tv_nsec = 0;
 
        if (tz & EXFAT_TZ_VALID)
                /* Adjust timezone to UTC0. */
@@ -124,6 +125,17 @@ void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
        *tz = EXFAT_TZ_VALID;
 }
 
+/*
+ * The timestamp for access_time has double seconds granularity.
+ * (There is no 10msIncrement field for access_time unlike create/modify_time)
+ * atime also has only a 2-second resolution.
+ */
+void exfat_truncate_atime(struct timespec64 *ts)
+{
+       ts->tv_sec = round_down(ts->tv_sec, 2);
+       ts->tv_nsec = 0;
+}
+
 unsigned short exfat_calc_chksum_2byte(void *data, int len,
                unsigned short chksum, int type)
 {
index a8681d91f56900107ea3df90e2b6dd986045a7bc..b72d782568b811ece222db0dd3575fd8bf2c958a 100644 (file)
@@ -595,6 +595,7 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        inode_inc_iversion(inode);
        inode->i_mtime = inode->i_atime = inode->i_ctime =
                EXFAT_I(inode)->i_crtime = current_time(inode);
+       exfat_truncate_atime(&inode->i_atime);
        /* timestamp is already written, so mark_inode_dirty() is unneeded. */
 
        d_instantiate(dentry, inode);
@@ -854,6 +855,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
 
        inode_inc_iversion(dir);
        dir->i_mtime = dir->i_atime = current_time(dir);
+       exfat_truncate_atime(&dir->i_atime);
        if (IS_DIRSYNC(dir))
                exfat_sync_inode(dir);
        else
@@ -861,6 +863,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
 
        clear_nlink(inode);
        inode->i_mtime = inode->i_atime = current_time(inode);
+       exfat_truncate_atime(&inode->i_atime);
        exfat_unhash_inode(inode);
        exfat_d_version_set(dentry, inode_query_iversion(dir));
 unlock:
@@ -903,6 +906,7 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        inode_inc_iversion(inode);
        inode->i_mtime = inode->i_atime = inode->i_ctime =
                EXFAT_I(inode)->i_crtime = current_time(inode);
+       exfat_truncate_atime(&inode->i_atime);
        /* timestamp is already written, so mark_inode_dirty() is unneeded. */
 
        d_instantiate(dentry, inode);
@@ -1019,6 +1023,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
 
        inode_inc_iversion(dir);
        dir->i_mtime = dir->i_atime = current_time(dir);
+       exfat_truncate_atime(&dir->i_atime);
        if (IS_DIRSYNC(dir))
                exfat_sync_inode(dir);
        else
@@ -1027,6 +1032,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
 
        clear_nlink(inode);
        inode->i_mtime = inode->i_atime = current_time(inode);
+       exfat_truncate_atime(&inode->i_atime);
        exfat_unhash_inode(inode);
        exfat_d_version_set(dentry, inode_query_iversion(dir));
 unlock:
@@ -1387,6 +1393,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
        inode_inc_iversion(new_dir);
        new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime =
                EXFAT_I(new_dir)->i_crtime = current_time(new_dir);
+       exfat_truncate_atime(&new_dir->i_atime);
        if (IS_DIRSYNC(new_dir))
                exfat_sync_inode(new_dir);
        else
index 16ed202ef5279abc40b23d03cd346b4baf4c23d3..0565d5539d57c6678c81997228dc3b8116eb864c 100644 (file)
@@ -49,6 +49,7 @@ static void exfat_put_super(struct super_block *sb)
                sync_blockdev(sb->s_bdev);
        exfat_set_vol_flags(sb, VOL_CLEAN);
        exfat_free_bitmap(sbi);
+       brelse(sbi->pbr_bh);
        mutex_unlock(&sbi->s_lock);
 
        call_rcu(&sbi->rcu, exfat_delayed_free);
@@ -100,7 +101,7 @@ static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf)
 int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag)
 {
        struct exfat_sb_info *sbi = EXFAT_SB(sb);
-       struct pbr64 *bpb;
+       struct pbr64 *bpb = (struct pbr64 *)sbi->pbr_bh->b_data;
        bool sync = 0;
 
        /* flags are not changed */
@@ -115,15 +116,6 @@ int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag)
        if (sb_rdonly(sb))
                return 0;
 
-       if (!sbi->pbr_bh) {
-               sbi->pbr_bh = sb_bread(sb, 0);
-               if (!sbi->pbr_bh) {
-                       exfat_msg(sb, KERN_ERR, "failed to read boot sector");
-                       return -ENOMEM;
-               }
-       }
-
-       bpb = (struct pbr64 *)sbi->pbr_bh->b_data;
        bpb->bsx.vol_flags = cpu_to_le16(new_flag);
 
        if (new_flag == VOL_DIRTY && !buffer_dirty(sbi->pbr_bh))
@@ -159,7 +151,6 @@ static int exfat_show_options(struct seq_file *m, struct dentry *root)
                seq_puts(m, ",iocharset=utf8");
        else if (sbi->nls_io)
                seq_printf(m, ",iocharset=%s", sbi->nls_io->charset);
-       seq_printf(m, ",bps=%ld", sb->s_blocksize);
        if (opts->errors == EXFAT_ERRORS_CONT)
                seq_puts(m, ",errors=continue");
        else if (opts->errors == EXFAT_ERRORS_PANIC)
@@ -351,14 +342,15 @@ static int exfat_read_root(struct inode *inode)
        exfat_save_attr(inode, ATTR_SUBDIR);
        inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime =
                current_time(inode);
+       exfat_truncate_atime(&inode->i_atime);
        exfat_cache_init_inode(inode);
        return 0;
 }
 
-static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb,
-               struct buffer_head **prev_bh)
+static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb)
 {
-       struct pbr *p_pbr = (struct pbr *) (*prev_bh)->b_data;
+       struct exfat_sb_info *sbi = EXFAT_SB(sb);
+       struct pbr *p_pbr = (struct pbr *) (sbi->pbr_bh)->b_data;
        unsigned short logical_sect = 0;
 
        logical_sect = 1 << p_pbr->bsx.f64.sect_size_bits;
@@ -378,26 +370,23 @@ static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb,
        }
 
        if (logical_sect > sb->s_blocksize) {
-               struct buffer_head *bh = NULL;
-
-               __brelse(*prev_bh);
-               *prev_bh = NULL;
+               brelse(sbi->pbr_bh);
+               sbi->pbr_bh = NULL;
 
                if (!sb_set_blocksize(sb, logical_sect)) {
                        exfat_msg(sb, KERN_ERR,
                                "unable to set blocksize %u", logical_sect);
                        return NULL;
                }
-               bh = sb_bread(sb, 0);
-               if (!bh) {
+               sbi->pbr_bh = sb_bread(sb, 0);
+               if (!sbi->pbr_bh) {
                        exfat_msg(sb, KERN_ERR,
                                "unable to read boot sector (logical sector size = %lu)",
                                sb->s_blocksize);
                        return NULL;
                }
 
-               *prev_bh = bh;
-               p_pbr = (struct pbr *) bh->b_data;
+               p_pbr = (struct pbr *)sbi->pbr_bh->b_data;
        }
        return p_pbr;
 }
@@ -408,21 +397,20 @@ static int __exfat_fill_super(struct super_block *sb)
        int ret;
        struct pbr *p_pbr;
        struct pbr64 *p_bpb;
-       struct buffer_head *bh;
        struct exfat_sb_info *sbi = EXFAT_SB(sb);
 
        /* set block size to read super block */
        sb_min_blocksize(sb, 512);
 
        /* read boot sector */
-       bh = sb_bread(sb, 0);
-       if (!bh) {
+       sbi->pbr_bh = sb_bread(sb, 0);
+       if (!sbi->pbr_bh) {
                exfat_msg(sb, KERN_ERR, "unable to read boot sector");
                return -EIO;
        }
 
        /* PRB is read */
-       p_pbr = (struct pbr *)bh->b_data;
+       p_pbr = (struct pbr *)sbi->pbr_bh->b_data;
 
        /* check the validity of PBR */
        if (le16_to_cpu((p_pbr->signature)) != PBR_SIGNATURE) {
@@ -433,7 +421,7 @@ static int __exfat_fill_super(struct super_block *sb)
 
 
        /* check logical sector size */
-       p_pbr = exfat_read_pbr_with_logical_sector(sb, &bh);
+       p_pbr = exfat_read_pbr_with_logical_sector(sb);
        if (!p_pbr) {
                ret = -EIO;
                goto free_bh;
@@ -514,7 +502,7 @@ free_alloc_bitmap:
 free_upcase_table:
        exfat_free_upcase_table(sbi);
 free_bh:
-       brelse(bh);
+       brelse(sbi->pbr_bh);
        return ret;
 }
 
@@ -531,17 +519,18 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc)
        if (opts->discard) {
                struct request_queue *q = bdev_get_queue(sb->s_bdev);
 
-               if (!blk_queue_discard(q))
+               if (!blk_queue_discard(q)) {
                        exfat_msg(sb, KERN_WARNING,
                                "mounting with \"discard\" option, but the device does not support discard");
-               opts->discard = 0;
+                       opts->discard = 0;
+               }
        }
 
        sb->s_flags |= SB_NODIRATIME;
        sb->s_magic = EXFAT_SUPER_MAGIC;
        sb->s_op = &exfat_sops;
 
-       sb->s_time_gran = 1;
+       sb->s_time_gran = 10 * NSEC_PER_MSEC;
        sb->s_time_min = EXFAT_MIN_TIMESTAMP_SECS;
        sb->s_time_max = EXFAT_MAX_TIMESTAMP_SECS;
 
@@ -605,6 +594,7 @@ put_inode:
 free_table:
        exfat_free_upcase_table(sbi);
        exfat_free_bitmap(sbi);
+       brelse(sbi->pbr_bh);
 
 check_nls_io:
        unload_nls(sbi->nls_io);
@@ -717,6 +707,7 @@ static void __exit exit_exfat_fs(void)
 module_init(init_exfat_fs);
 module_exit(exit_exfat_fs);
 
+MODULE_ALIAS_FS("exfat");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("exFAT filesystem support");
 MODULE_AUTHOR("Samsung Electronics Co., Ltd.");
index 0e0a4d6209c7d71afa09da41a8cf0d7d45f5eeff..a32e5f7b53853ffce8c8249c0753ff3ad554d5b1 100644 (file)
@@ -410,7 +410,7 @@ verified:
  * Read the bitmap for a given block_group,and validate the
  * bits for block/inode/inode tables are set in the bitmaps
  *
- * Return buffer_head on success or NULL in case of failure.
+ * Return buffer_head on success or an ERR_PTR in case of failure.
  */
 struct buffer_head *
 ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
@@ -502,7 +502,7 @@ out:
        return ERR_PTR(err);
 }
 
-/* Returns 0 on success, 1 on error */
+/* Returns 0 on success, -errno on error */
 int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group,
                           struct buffer_head *bh)
 {
index 7f16e1af8d5cc6fb371f98b64e9d0b127aec4ca7..0c76cdd44d90d02316114172da2ea8bd5120e6a9 100644 (file)
@@ -338,9 +338,6 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
                if (inode && inode_needs_sync(inode)) {
                        sync_dirty_buffer(bh);
                        if (buffer_req(bh) && !buffer_uptodate(bh)) {
-                               struct ext4_super_block *es;
-
-                               es = EXT4_SB(inode->i_sb)->s_es;
                                ext4_error_inode_err(inode, where, line,
                                                     bh->b_blocknr, EIO,
                                        "IO error syncing itable block");
index 031752cfb6f753648d06d9dd3312ba9507116891..f2b577b315a09371210b180934f3c0019134756e 100644 (file)
@@ -3374,8 +3374,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
                (unsigned long long)map->m_lblk, map_len);
 
        sbi = EXT4_SB(inode->i_sb);
-       eof_block = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
-               inode->i_sb->s_blocksize_bits;
+       eof_block = (EXT4_I(inode)->i_disksize + inode->i_sb->s_blocksize - 1)
+                       >> inode->i_sb->s_blocksize_bits;
        if (eof_block < map->m_lblk + map_len)
                eof_block = map->m_lblk + map_len;
 
@@ -3627,8 +3627,8 @@ static int ext4_split_convert_extents(handle_t *handle,
                  __func__, inode->i_ino,
                  (unsigned long long)map->m_lblk, map->m_len);
 
-       eof_block = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
-               inode->i_sb->s_blocksize_bits;
+       eof_block = (EXT4_I(inode)->i_disksize + inode->i_sb->s_blocksize - 1)
+                       >> inode->i_sb->s_blocksize_bits;
        if (eof_block < map->m_lblk + map->m_len)
                eof_block = map->m_lblk + map->m_len;
        /*
index b420c9dc444de454b0bbd298d31e0d7074d210fb..4b8c9a9bdf0c8c0e77a39aaa7e0bb653d4c64b40 100644 (file)
@@ -113,7 +113,7 @@ verified:
  * Read the inode allocation bitmap for a given block_group, reading
  * into the specified slot in the superblock's bitmap cache.
  *
- * Return buffer_head of bitmap on success or NULL.
+ * Return buffer_head of bitmap on success, or an ERR_PTR on error.
  */
 static struct buffer_head *
 ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
@@ -662,7 +662,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
  * block has been written back to disk.  (Yes, these values are
  * somewhat arbitrary...)
  */
-#define RECENTCY_MIN   5
+#define RECENTCY_MIN   60
 #define RECENTCY_DIRTY 300
 
 static int recently_deleted(struct super_block *sb, ext4_group_t group, int ino)
index e416096fc081372d0047ebe9ed90c4a2038dab46..2a4aae6acdcb9e4acb79647baa24c218fb6cca2a 100644 (file)
@@ -1973,7 +1973,7 @@ static int ext4_writepage(struct page *page,
        bool keep_towrite = false;
 
        if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) {
-               ext4_invalidatepage(page, 0, PAGE_SIZE);
+               inode->i_mapping->a_ops->invalidatepage(page, 0, PAGE_SIZE);
                unlock_page(page);
                return -EIO;
        }
@@ -4364,7 +4364,7 @@ make_io:
                        if (end > table)
                                end = table;
                        while (b <= end)
-                               sb_breadahead(sb, b++);
+                               sb_breadahead_unmovable(sb, b++);
                }
 
                /*
index 87c85be4c12e568d3d272cc8cf87f634ee13cf9a..30d5d97548c42117decfcca690f70b9b48dc490b 100644 (file)
@@ -1943,7 +1943,8 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
        int free;
 
        free = e4b->bd_info->bb_free;
-       BUG_ON(free <= 0);
+       if (WARN_ON(free <= 0))
+               return;
 
        i = e4b->bd_info->bb_first_free;
 
@@ -1966,7 +1967,8 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
                }
 
                mb_find_extent(e4b, i, ac->ac_g_ex.fe_len, &ex);
-               BUG_ON(ex.fe_len <= 0);
+               if (WARN_ON(ex.fe_len <= 0))
+                       break;
                if (free < ex.fe_len) {
                        ext4_grp_locked_error(sb, e4b->bd_group, 0, 0,
                                        "%d free clusters as per "
index 9728e7b0e84fcae5b7f0d4753c1572dc08f813bb..bf5fcb477f667211f031c6f1cff42f54a1a5235d 100644 (file)
@@ -596,7 +596,6 @@ void __ext4_error_file(struct file *file, const char *function,
 {
        va_list args;
        struct va_format vaf;
-       struct ext4_super_block *es;
        struct inode *inode = file_inode(file);
        char pathname[80], *path;
 
@@ -604,7 +603,6 @@ void __ext4_error_file(struct file *file, const char *function,
                return;
 
        trace_ext4_error(inode->i_sb, function, line);
-       es = EXT4_SB(inode->i_sb)->s_es;
        if (ext4_error_ratelimit(inode->i_sb)) {
                path = file_path(file, pathname, sizeof(pathname));
                if (IS_ERR(path))
@@ -4340,7 +4338,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        /* Pre-read the descriptors into the buffer cache */
        for (i = 0; i < db_count; i++) {
                block = descriptor_loc(sb, logical_sb_block, i);
-               sb_breadahead(sb, block);
+               sb_breadahead_unmovable(sb, block);
        }
 
        for (i = 0; i < db_count; i++) {
index 5190bfb6a6657e6ead1ab2c7da97ad1dbfcc1e0e..979d9f977409a0c5d4f190264897b69272d8bcc8 100644 (file)
@@ -357,7 +357,6 @@ struct io_timeout_data {
        struct hrtimer                  timer;
        struct timespec64               ts;
        enum hrtimer_mode               mode;
-       u32                             seq_offset;
 };
 
 struct io_accept {
@@ -385,7 +384,7 @@ struct io_timeout {
        struct file                     *file;
        u64                             addr;
        int                             flags;
-       unsigned                        count;
+       u32                             count;
 };
 
 struct io_rw {
@@ -508,6 +507,7 @@ enum {
        REQ_F_FORCE_ASYNC_BIT   = IOSQE_ASYNC_BIT,
        REQ_F_BUFFER_SELECT_BIT = IOSQE_BUFFER_SELECT_BIT,
 
+       REQ_F_LINK_HEAD_BIT,
        REQ_F_LINK_NEXT_BIT,
        REQ_F_FAIL_LINK_BIT,
        REQ_F_INFLIGHT_BIT,
@@ -524,6 +524,7 @@ enum {
        REQ_F_OVERFLOW_BIT,
        REQ_F_POLLED_BIT,
        REQ_F_BUFFER_SELECTED_BIT,
+       REQ_F_NO_FILE_TABLE_BIT,
 
        /* not a real bit, just to check we're not overflowing the space */
        __REQ_F_LAST_BIT,
@@ -543,6 +544,8 @@ enum {
        /* IOSQE_BUFFER_SELECT */
        REQ_F_BUFFER_SELECT     = BIT(REQ_F_BUFFER_SELECT_BIT),
 
+       /* head of a link */
+       REQ_F_LINK_HEAD         = BIT(REQ_F_LINK_HEAD_BIT),
        /* already grabbed next link */
        REQ_F_LINK_NEXT         = BIT(REQ_F_LINK_NEXT_BIT),
        /* fail rest of links */
@@ -575,6 +578,8 @@ enum {
        REQ_F_POLLED            = BIT(REQ_F_POLLED_BIT),
        /* buffer already selected */
        REQ_F_BUFFER_SELECTED   = BIT(REQ_F_BUFFER_SELECTED_BIT),
+       /* doesn't need file table for this request */
+       REQ_F_NO_FILE_TABLE     = BIT(REQ_F_NO_FILE_TABLE_BIT),
 };
 
 struct async_poll {
@@ -675,8 +680,6 @@ struct io_op_def {
        unsigned                needs_mm : 1;
        /* needs req->file assigned */
        unsigned                needs_file : 1;
-       /* needs req->file assigned IFF fd is >= 0 */
-       unsigned                fd_non_neg : 1;
        /* hash wq insertion if file is a regular file */
        unsigned                hash_reg_file : 1;
        /* unbound wq insertion if file is a non-regular file */
@@ -779,8 +782,6 @@ static const struct io_op_def io_op_defs[] = {
                .needs_file             = 1,
        },
        [IORING_OP_OPENAT] = {
-               .needs_file             = 1,
-               .fd_non_neg             = 1,
                .file_table             = 1,
                .needs_fs               = 1,
        },
@@ -794,9 +795,8 @@ static const struct io_op_def io_op_defs[] = {
        },
        [IORING_OP_STATX] = {
                .needs_mm               = 1,
-               .needs_file             = 1,
-               .fd_non_neg             = 1,
                .needs_fs               = 1,
+               .file_table             = 1,
        },
        [IORING_OP_READ] = {
                .needs_mm               = 1,
@@ -831,8 +831,6 @@ static const struct io_op_def io_op_defs[] = {
                .buffer_select          = 1,
        },
        [IORING_OP_OPENAT2] = {
-               .needs_file             = 1,
-               .fd_non_neg             = 1,
                .file_table             = 1,
                .needs_fs               = 1,
        },
@@ -955,8 +953,8 @@ static inline bool __req_need_defer(struct io_kiocb *req)
 {
        struct io_ring_ctx *ctx = req->ctx;
 
-       return req->sequence != ctx->cached_cq_tail + ctx->cached_sq_dropped
-                                       + atomic_read(&ctx->cached_cq_overflow);
+       return req->sequence != ctx->cached_cq_tail
+                               + atomic_read(&ctx->cached_cq_overflow);
 }
 
 static inline bool req_need_defer(struct io_kiocb *req)
@@ -1289,7 +1287,7 @@ static struct io_kiocb *io_get_fallback_req(struct io_ring_ctx *ctx)
        struct io_kiocb *req;
 
        req = ctx->fallback_req;
-       if (!test_and_set_bit_lock(0, (unsigned long *) ctx->fallback_req))
+       if (!test_and_set_bit_lock(0, (unsigned long *) &ctx->fallback_req))
                return req;
 
        return NULL;
@@ -1376,7 +1374,7 @@ static void __io_free_req(struct io_kiocb *req)
        if (likely(!io_is_fallback_req(req)))
                kmem_cache_free(req_cachep, req);
        else
-               clear_bit_unlock(0, (unsigned long *) req->ctx->fallback_req);
+               clear_bit_unlock(0, (unsigned long *) &req->ctx->fallback_req);
 }
 
 struct req_batch {
@@ -1437,7 +1435,7 @@ static bool io_link_cancel_timeout(struct io_kiocb *req)
        if (ret != -1) {
                io_cqring_fill_event(req, -ECANCELED);
                io_commit_cqring(ctx);
-               req->flags &= ~REQ_F_LINK;
+               req->flags &= ~REQ_F_LINK_HEAD;
                io_put_req(req);
                return true;
        }
@@ -1473,7 +1471,7 @@ static void io_req_link_next(struct io_kiocb *req, struct io_kiocb **nxtptr)
 
                list_del_init(&req->link_list);
                if (!list_empty(&nxt->link_list))
-                       nxt->flags |= REQ_F_LINK;
+                       nxt->flags |= REQ_F_LINK_HEAD;
                *nxtptr = nxt;
                break;
        }
@@ -1484,7 +1482,7 @@ static void io_req_link_next(struct io_kiocb *req, struct io_kiocb **nxtptr)
 }
 
 /*
- * Called if REQ_F_LINK is set, and we fail the head request
+ * Called if REQ_F_LINK_HEAD is set, and we fail the head request
  */
 static void io_fail_links(struct io_kiocb *req)
 {
@@ -1517,7 +1515,7 @@ static void io_fail_links(struct io_kiocb *req)
 
 static void io_req_find_next(struct io_kiocb *req, struct io_kiocb **nxt)
 {
-       if (likely(!(req->flags & REQ_F_LINK)))
+       if (likely(!(req->flags & REQ_F_LINK_HEAD)))
                return;
 
        /*
@@ -1669,7 +1667,7 @@ static inline unsigned int io_sqring_entries(struct io_ring_ctx *ctx)
 
 static inline bool io_req_multi_free(struct req_batch *rb, struct io_kiocb *req)
 {
-       if ((req->flags & REQ_F_LINK) || io_is_fallback_req(req))
+       if ((req->flags & REQ_F_LINK_HEAD) || io_is_fallback_req(req))
                return false;
 
        if (!(req->flags & REQ_F_FIXED_FILE) || req->io)
@@ -2032,7 +2030,7 @@ static struct file *__io_file_get(struct io_submit_state *state, int fd)
  * any file. For now, just ensure that anything potentially problematic is done
  * inline.
  */
-static bool io_file_supports_async(struct file *file)
+static bool io_file_supports_async(struct file *file, int rw)
 {
        umode_t mode = file_inode(file)->i_mode;
 
@@ -2041,7 +2039,13 @@ static bool io_file_supports_async(struct file *file)
        if (S_ISREG(mode) && file->f_op != &io_uring_fops)
                return true;
 
-       return false;
+       if (!(file->f_mode & FMODE_NOWAIT))
+               return false;
+
+       if (rw == READ)
+               return file->f_op->read_iter != NULL;
+
+       return file->f_op->write_iter != NULL;
 }
 
 static int io_prep_rw(struct io_kiocb *req, const struct io_uring_sqe *sqe,
@@ -2562,14 +2566,14 @@ static int io_read(struct io_kiocb *req, bool force_nonblock)
 
        req->result = 0;
        io_size = ret;
-       if (req->flags & REQ_F_LINK)
+       if (req->flags & REQ_F_LINK_HEAD)
                req->result = io_size;
 
        /*
         * If the file doesn't support async, mark it as REQ_F_MUST_PUNT so
         * we know to async punt it even if it was opened O_NONBLOCK
         */
-       if (force_nonblock && !io_file_supports_async(req->file))
+       if (force_nonblock && !io_file_supports_async(req->file, READ))
                goto copy_iov;
 
        iov_count = iov_iter_count(&iter);
@@ -2592,7 +2596,8 @@ copy_iov:
                        if (ret)
                                goto out_free;
                        /* any defer here is final, must blocking retry */
-                       if (!(req->flags & REQ_F_NOWAIT))
+                       if (!(req->flags & REQ_F_NOWAIT) &&
+                           !file_can_poll(req->file))
                                req->flags |= REQ_F_MUST_PUNT;
                        return -EAGAIN;
                }
@@ -2653,14 +2658,14 @@ static int io_write(struct io_kiocb *req, bool force_nonblock)
 
        req->result = 0;
        io_size = ret;
-       if (req->flags & REQ_F_LINK)
+       if (req->flags & REQ_F_LINK_HEAD)
                req->result = io_size;
 
        /*
         * If the file doesn't support async, mark it as REQ_F_MUST_PUNT so
         * we know to async punt it even if it was opened O_NONBLOCK
         */
-       if (force_nonblock && !io_file_supports_async(req->file))
+       if (force_nonblock && !io_file_supports_async(req->file, WRITE))
                goto copy_iov;
 
        /* file path doesn't support NOWAIT for non-direct_IO */
@@ -2714,7 +2719,8 @@ copy_iov:
                        if (ret)
                                goto out_free;
                        /* any defer here is final, must blocking retry */
-                       req->flags |= REQ_F_MUST_PUNT;
+                       if (!file_can_poll(req->file))
+                               req->flags |= REQ_F_MUST_PUNT;
                        return -EAGAIN;
                }
        }
@@ -2754,15 +2760,6 @@ static int io_splice_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        return 0;
 }
 
-static bool io_splice_punt(struct file *file)
-{
-       if (get_pipe_info(file))
-               return false;
-       if (!io_file_supports_async(file))
-               return true;
-       return !(file->f_mode & O_NONBLOCK);
-}
-
 static int io_splice(struct io_kiocb *req, bool force_nonblock)
 {
        struct io_splice *sp = &req->splice;
@@ -2772,11 +2769,8 @@ static int io_splice(struct io_kiocb *req, bool force_nonblock)
        loff_t *poff_in, *poff_out;
        long ret;
 
-       if (force_nonblock) {
-               if (io_splice_punt(in) || io_splice_punt(out))
-                       return -EAGAIN;
-               flags |= SPLICE_F_NONBLOCK;
-       }
+       if (force_nonblock)
+               return -EAGAIN;
 
        poff_in = (sp->off_in == -1) ? NULL : &sp->off_in;
        poff_out = (sp->off_out == -1) ? NULL : &sp->off_out;
@@ -3353,8 +3347,12 @@ static int io_statx(struct io_kiocb *req, bool force_nonblock)
        struct kstat stat;
        int ret;
 
-       if (force_nonblock)
+       if (force_nonblock) {
+               /* only need file table for an actual valid fd */
+               if (ctx->dfd == -1 || ctx->dfd == AT_FDCWD)
+                       req->flags |= REQ_F_NO_FILE_TABLE;
                return -EAGAIN;
+       }
 
        if (vfs_stat_set_lookup_flags(&lookup_flags, ctx->how.flags))
                return -EINVAL;
@@ -3500,7 +3498,7 @@ static void io_sync_file_range_finish(struct io_wq_work **workptr)
        if (io_req_cancelled(req))
                return;
        __io_sync_file_range(req);
-       io_put_req(req); /* put submission ref */
+       io_steal_work(req, workptr);
 }
 
 static int io_sync_file_range(struct io_kiocb *req, bool force_nonblock)
@@ -4153,25 +4151,62 @@ static int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *poll,
        return 1;
 }
 
+static bool io_poll_rewait(struct io_kiocb *req, struct io_poll_iocb *poll)
+       __acquires(&req->ctx->completion_lock)
+{
+       struct io_ring_ctx *ctx = req->ctx;
+
+       if (!req->result && !READ_ONCE(poll->canceled)) {
+               struct poll_table_struct pt = { ._key = poll->events };
+
+               req->result = vfs_poll(req->file, &pt) & poll->events;
+       }
+
+       spin_lock_irq(&ctx->completion_lock);
+       if (!req->result && !READ_ONCE(poll->canceled)) {
+               add_wait_queue(poll->head, &poll->wait);
+               return true;
+       }
+
+       return false;
+}
+
 static void io_async_task_func(struct callback_head *cb)
 {
        struct io_kiocb *req = container_of(cb, struct io_kiocb, task_work);
        struct async_poll *apoll = req->apoll;
        struct io_ring_ctx *ctx = req->ctx;
+       bool canceled;
 
        trace_io_uring_task_run(req->ctx, req->opcode, req->user_data);
 
-       WARN_ON_ONCE(!list_empty(&req->apoll->poll.wait.entry));
+       if (io_poll_rewait(req, &apoll->poll)) {
+               spin_unlock_irq(&ctx->completion_lock);
+               return;
+       }
 
-       if (hash_hashed(&req->hash_node)) {
-               spin_lock_irq(&ctx->completion_lock);
+       if (hash_hashed(&req->hash_node))
                hash_del(&req->hash_node);
-               spin_unlock_irq(&ctx->completion_lock);
+
+       canceled = READ_ONCE(apoll->poll.canceled);
+       if (canceled) {
+               io_cqring_fill_event(req, -ECANCELED);
+               io_commit_cqring(ctx);
        }
 
+       spin_unlock_irq(&ctx->completion_lock);
+
        /* restore ->work in case we need to retry again */
        memcpy(&req->work, &apoll->work, sizeof(req->work));
 
+       if (canceled) {
+               kfree(apoll);
+               io_cqring_ev_posted(ctx);
+               req_set_fail_links(req);
+               io_double_put_req(req);
+               return;
+       }
+
        __set_current_state(TASK_RUNNING);
        mutex_lock(&ctx->uring_lock);
        __io_queue_sqe(req, NULL);
@@ -4315,11 +4350,13 @@ static bool __io_poll_remove_one(struct io_kiocb *req,
 
 static bool io_poll_remove_one(struct io_kiocb *req)
 {
+       struct async_poll *apoll = NULL;
        bool do_complete;
 
        if (req->opcode == IORING_OP_POLL_ADD) {
                do_complete = __io_poll_remove_one(req, &req->poll);
        } else {
+               apoll = req->apoll;
                /* non-poll requests have submit ref still */
                do_complete = __io_poll_remove_one(req, &req->apoll->poll);
                if (do_complete)
@@ -4328,6 +4365,14 @@ static bool io_poll_remove_one(struct io_kiocb *req)
 
        hash_del(&req->hash_node);
 
+       if (do_complete && apoll) {
+               /*
+                * restore ->work because we need to call io_req_work_drop_env.
+                */
+               memcpy(&req->work, &apoll->work, sizeof(req->work));
+               kfree(apoll);
+       }
+
        if (do_complete) {
                io_cqring_fill_event(req, -ECANCELED);
                io_commit_cqring(req->ctx);
@@ -4342,7 +4387,7 @@ static void io_poll_remove_all(struct io_ring_ctx *ctx)
 {
        struct hlist_node *tmp;
        struct io_kiocb *req;
-       int i;
+       int posted = 0, i;
 
        spin_lock_irq(&ctx->completion_lock);
        for (i = 0; i < (1U << ctx->cancel_hash_bits); i++) {
@@ -4350,11 +4395,12 @@ static void io_poll_remove_all(struct io_ring_ctx *ctx)
 
                list = &ctx->cancel_hash[i];
                hlist_for_each_entry_safe(req, tmp, list, hash_node)
-                       io_poll_remove_one(req);
+                       posted += io_poll_remove_one(req);
        }
        spin_unlock_irq(&ctx->completion_lock);
 
-       io_cqring_ev_posted(ctx);
+       if (posted)
+               io_cqring_ev_posted(ctx);
 }
 
 static int io_poll_cancel(struct io_ring_ctx *ctx, __u64 sqe_addr)
@@ -4423,18 +4469,11 @@ static void io_poll_task_handler(struct io_kiocb *req, struct io_kiocb **nxt)
        struct io_ring_ctx *ctx = req->ctx;
        struct io_poll_iocb *poll = &req->poll;
 
-       if (!req->result && !READ_ONCE(poll->canceled)) {
-               struct poll_table_struct pt = { ._key = poll->events };
-
-               req->result = vfs_poll(req->file, &pt) & poll->events;
-       }
-
-       spin_lock_irq(&ctx->completion_lock);
-       if (!req->result && !READ_ONCE(poll->canceled)) {
-               add_wait_queue(poll->head, &poll->wait);
+       if (io_poll_rewait(req, poll)) {
                spin_unlock_irq(&ctx->completion_lock);
                return;
        }
+
        hash_del(&req->hash_node);
        io_poll_complete(req, req->result, 0);
        req->flags |= REQ_F_COMP_LOCKED;
@@ -4665,11 +4704,12 @@ static int io_timeout_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe,
 
 static int io_timeout(struct io_kiocb *req)
 {
-       unsigned count;
        struct io_ring_ctx *ctx = req->ctx;
        struct io_timeout_data *data;
        struct list_head *entry;
        unsigned span = 0;
+       u32 count = req->timeout.count;
+       u32 seq = req->sequence;
 
        data = &req->io->timeout;
 
@@ -4678,7 +4718,6 @@ static int io_timeout(struct io_kiocb *req)
         * timeout event to be satisfied. If it isn't set, then this is
         * a pure timeout request, sequence isn't used.
         */
-       count = req->timeout.count;
        if (!count) {
                req->flags |= REQ_F_TIMEOUT_NOSEQ;
                spin_lock_irq(&ctx->completion_lock);
@@ -4686,8 +4725,7 @@ static int io_timeout(struct io_kiocb *req)
                goto add;
        }
 
-       req->sequence = ctx->cached_sq_head + count - 1;
-       data->seq_offset = count;
+       req->sequence = seq + count;
 
        /*
         * Insertion sort, ensuring the first entry in the list is always
@@ -4696,26 +4734,26 @@ static int io_timeout(struct io_kiocb *req)
        spin_lock_irq(&ctx->completion_lock);
        list_for_each_prev(entry, &ctx->timeout_list) {
                struct io_kiocb *nxt = list_entry(entry, struct io_kiocb, list);
-               unsigned nxt_sq_head;
+               unsigned nxt_seq;
                long long tmp, tmp_nxt;
-               u32 nxt_offset = nxt->io->timeout.seq_offset;
+               u32 nxt_offset = nxt->timeout.count;
 
                if (nxt->flags & REQ_F_TIMEOUT_NOSEQ)
                        continue;
 
                /*
-                * Since cached_sq_head + count - 1 can overflow, use type long
+                * Since seq + count can overflow, use type long
                 * long to store it.
                 */
-               tmp = (long long)ctx->cached_sq_head + count - 1;
-               nxt_sq_head = nxt->sequence - nxt_offset + 1;
-               tmp_nxt = (long long)nxt_sq_head + nxt_offset - 1;
+               tmp = (long long)seq + count;
+               nxt_seq = nxt->sequence - nxt_offset;
+               tmp_nxt = (long long)nxt_seq + nxt_offset;
 
                /*
                 * cached_sq_head may overflow, and it will never overflow twice
                 * once there is some timeout req still be valid.
                 */
-               if (ctx->cached_sq_head < nxt_sq_head)
+               if (seq < nxt_seq)
                        tmp += UINT_MAX;
 
                if (tmp > tmp_nxt)
@@ -4973,7 +5011,7 @@ static int io_req_defer(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        int ret;
 
        /* Still need defer if there is pending req in defer list. */
-       if (!req_need_defer(req) && list_empty(&ctx->defer_list))
+       if (!req_need_defer(req) && list_empty_careful(&ctx->defer_list))
                return 0;
 
        if (!req->io && io_alloc_async_ctx(req))
@@ -5322,15 +5360,6 @@ static void io_wq_submit_work(struct io_wq_work **workptr)
        io_steal_work(req, workptr);
 }
 
-static int io_req_needs_file(struct io_kiocb *req, int fd)
-{
-       if (!io_op_defs[req->opcode].needs_file)
-               return 0;
-       if ((fd == -1 || fd == AT_FDCWD) && io_op_defs[req->opcode].fd_non_neg)
-               return 0;
-       return 1;
-}
-
 static inline struct file *io_file_from_index(struct io_ring_ctx *ctx,
                                              int index)
 {
@@ -5368,14 +5397,11 @@ static int io_file_get(struct io_submit_state *state, struct io_kiocb *req,
 }
 
 static int io_req_set_file(struct io_submit_state *state, struct io_kiocb *req,
-                          int fd, unsigned int flags)
+                          int fd)
 {
        bool fixed;
 
-       if (!io_req_needs_file(req, fd))
-               return 0;
-
-       fixed = (flags & IOSQE_FIXED_FILE);
+       fixed = (req->flags & REQ_F_FIXED_FILE) != 0;
        if (unlikely(!fixed && req->needs_fixed_file))
                return -EBADF;
 
@@ -5387,7 +5413,7 @@ static int io_grab_files(struct io_kiocb *req)
        int ret = -EBADF;
        struct io_ring_ctx *ctx = req->ctx;
 
-       if (req->work.files)
+       if (req->work.files || (req->flags & REQ_F_NO_FILE_TABLE))
                return 0;
        if (!ctx->ring_file)
                return -EBADF;
@@ -5476,7 +5502,7 @@ static struct io_kiocb *io_prep_linked_timeout(struct io_kiocb *req)
 {
        struct io_kiocb *nxt;
 
-       if (!(req->flags & REQ_F_LINK))
+       if (!(req->flags & REQ_F_LINK_HEAD))
                return NULL;
        /* for polled retry, if flag is set, we already went through here */
        if (req->flags & REQ_F_POLLED)
@@ -5604,54 +5630,11 @@ static inline void io_queue_link_head(struct io_kiocb *req)
                io_queue_sqe(req, NULL);
 }
 
-#define SQE_VALID_FLAGS        (IOSQE_FIXED_FILE|IOSQE_IO_DRAIN|IOSQE_IO_LINK| \
-                               IOSQE_IO_HARDLINK | IOSQE_ASYNC | \
-                               IOSQE_BUFFER_SELECT)
-
-static bool io_submit_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe,
+static int io_submit_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe,
                          struct io_submit_state *state, struct io_kiocb **link)
 {
        struct io_ring_ctx *ctx = req->ctx;
-       unsigned int sqe_flags;
-       int ret, id, fd;
-
-       sqe_flags = READ_ONCE(sqe->flags);
-
-       /* enforce forwards compatibility on users */
-       if (unlikely(sqe_flags & ~SQE_VALID_FLAGS)) {
-               ret = -EINVAL;
-               goto err_req;
-       }
-
-       if ((sqe_flags & IOSQE_BUFFER_SELECT) &&
-           !io_op_defs[req->opcode].buffer_select) {
-               ret = -EOPNOTSUPP;
-               goto err_req;
-       }
-
-       id = READ_ONCE(sqe->personality);
-       if (id) {
-               req->work.creds = idr_find(&ctx->personality_idr, id);
-               if (unlikely(!req->work.creds)) {
-                       ret = -EINVAL;
-                       goto err_req;
-               }
-               get_cred(req->work.creds);
-       }
-
-       /* same numerical values with corresponding REQ_F_*, safe to copy */
-       req->flags |= sqe_flags & (IOSQE_IO_DRAIN | IOSQE_IO_HARDLINK |
-                                       IOSQE_ASYNC | IOSQE_FIXED_FILE |
-                                       IOSQE_BUFFER_SELECT);
-
-       fd = READ_ONCE(sqe->fd);
-       ret = io_req_set_file(state, req, fd, sqe_flags);
-       if (unlikely(ret)) {
-err_req:
-               io_cqring_add_event(req, ret);
-               io_double_put_req(req);
-               return false;
-       }
+       int ret;
 
        /*
         * If we already have a head request, queue this one for async
@@ -5670,42 +5653,39 @@ err_req:
                 * next after the link request. The last one is done via
                 * drain_next flag to persist the effect across calls.
                 */
-               if (sqe_flags & IOSQE_IO_DRAIN) {
+               if (req->flags & REQ_F_IO_DRAIN) {
                        head->flags |= REQ_F_IO_DRAIN;
                        ctx->drain_next = 1;
                }
-               if (io_alloc_async_ctx(req)) {
-                       ret = -EAGAIN;
-                       goto err_req;
-               }
+               if (io_alloc_async_ctx(req))
+                       return -EAGAIN;
 
                ret = io_req_defer_prep(req, sqe);
                if (ret) {
                        /* fail even hard links since we don't submit */
                        head->flags |= REQ_F_FAIL_LINK;
-                       goto err_req;
+                       return ret;
                }
                trace_io_uring_link(ctx, req, head);
                list_add_tail(&req->link_list, &head->link_list);
 
                /* last request of a link, enqueue the link */
-               if (!(sqe_flags & (IOSQE_IO_LINK|IOSQE_IO_HARDLINK))) {
+               if (!(req->flags & (REQ_F_LINK | REQ_F_HARDLINK))) {
                        io_queue_link_head(head);
                        *link = NULL;
                }
        } else {
                if (unlikely(ctx->drain_next)) {
                        req->flags |= REQ_F_IO_DRAIN;
-                       req->ctx->drain_next = 0;
+                       ctx->drain_next = 0;
                }
-               if (sqe_flags & (IOSQE_IO_LINK|IOSQE_IO_HARDLINK)) {
-                       req->flags |= REQ_F_LINK;
+               if (req->flags & (REQ_F_LINK | REQ_F_HARDLINK)) {
+                       req->flags |= REQ_F_LINK_HEAD;
                        INIT_LIST_HEAD(&req->link_list);
 
-                       if (io_alloc_async_ctx(req)) {
-                               ret = -EAGAIN;
-                               goto err_req;
-                       }
+                       if (io_alloc_async_ctx(req))
+                               return -EAGAIN;
+
                        ret = io_req_defer_prep(req, sqe);
                        if (ret)
                                req->flags |= REQ_F_FAIL_LINK;
@@ -5715,7 +5695,7 @@ err_req:
                }
        }
 
-       return true;
+       return 0;
 }
 
 /*
@@ -5789,15 +5769,23 @@ static inline void io_consume_sqe(struct io_ring_ctx *ctx)
        ctx->cached_sq_head++;
 }
 
-static void io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
-                       const struct io_uring_sqe *sqe)
+#define SQE_VALID_FLAGS        (IOSQE_FIXED_FILE|IOSQE_IO_DRAIN|IOSQE_IO_LINK| \
+                               IOSQE_IO_HARDLINK | IOSQE_ASYNC | \
+                               IOSQE_BUFFER_SELECT)
+
+static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
+                      const struct io_uring_sqe *sqe,
+                      struct io_submit_state *state, bool async)
 {
+       unsigned int sqe_flags;
+       int id;
+
        /*
         * All io need record the previous position, if LINK vs DARIN,
         * it can be used to mark the position of the first IO in the
         * link list.
         */
-       req->sequence = ctx->cached_sq_head;
+       req->sequence = ctx->cached_sq_head - ctx->cached_sq_dropped;
        req->opcode = READ_ONCE(sqe->opcode);
        req->user_data = READ_ONCE(sqe->user_data);
        req->io = NULL;
@@ -5808,17 +5796,52 @@ static void io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
        refcount_set(&req->refs, 2);
        req->task = NULL;
        req->result = 0;
+       req->needs_fixed_file = async;
        INIT_IO_WORK(&req->work, io_wq_submit_work);
+
+       if (unlikely(req->opcode >= IORING_OP_LAST))
+               return -EINVAL;
+
+       if (io_op_defs[req->opcode].needs_mm && !current->mm) {
+               if (unlikely(!mmget_not_zero(ctx->sqo_mm)))
+                       return -EFAULT;
+               use_mm(ctx->sqo_mm);
+       }
+
+       sqe_flags = READ_ONCE(sqe->flags);
+       /* enforce forwards compatibility on users */
+       if (unlikely(sqe_flags & ~SQE_VALID_FLAGS))
+               return -EINVAL;
+
+       if ((sqe_flags & IOSQE_BUFFER_SELECT) &&
+           !io_op_defs[req->opcode].buffer_select)
+               return -EOPNOTSUPP;
+
+       id = READ_ONCE(sqe->personality);
+       if (id) {
+               req->work.creds = idr_find(&ctx->personality_idr, id);
+               if (unlikely(!req->work.creds))
+                       return -EINVAL;
+               get_cred(req->work.creds);
+       }
+
+       /* same numerical values with corresponding REQ_F_*, safe to copy */
+       req->flags |= sqe_flags & (IOSQE_IO_DRAIN | IOSQE_IO_HARDLINK |
+                                       IOSQE_ASYNC | IOSQE_FIXED_FILE |
+                                       IOSQE_BUFFER_SELECT | IOSQE_IO_LINK);
+
+       if (!io_op_defs[req->opcode].needs_file)
+               return 0;
+
+       return io_req_set_file(state, req, READ_ONCE(sqe->fd));
 }
 
 static int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr,
-                         struct file *ring_file, int ring_fd,
-                         struct mm_struct **mm, bool async)
+                         struct file *ring_file, int ring_fd, bool async)
 {
        struct io_submit_state state, *statep = NULL;
        struct io_kiocb *link = NULL;
        int i, submitted = 0;
-       bool mm_fault = false;
 
        /* if we have a backlog and couldn't flush it all, return BUSY */
        if (test_bit(0, &ctx->sq_check_overflow)) {
@@ -5858,34 +5881,23 @@ static int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr,
                        break;
                }
 
-               io_init_req(ctx, req, sqe);
+               err = io_init_req(ctx, req, sqe, statep, async);
                io_consume_sqe(ctx);
                /* will complete beyond this point, count as submitted */
                submitted++;
 
-               if (unlikely(req->opcode >= IORING_OP_LAST)) {
-                       err = -EINVAL;
+               if (unlikely(err)) {
 fail_req:
                        io_cqring_add_event(req, err);
                        io_double_put_req(req);
                        break;
                }
 
-               if (io_op_defs[req->opcode].needs_mm && !*mm) {
-                       mm_fault = mm_fault || !mmget_not_zero(ctx->sqo_mm);
-                       if (unlikely(mm_fault)) {
-                               err = -EFAULT;
-                               goto fail_req;
-                       }
-                       use_mm(ctx->sqo_mm);
-                       *mm = ctx->sqo_mm;
-               }
-
-               req->needs_fixed_file = async;
                trace_io_uring_submit_sqe(ctx, req->opcode, req->user_data,
                                                true, async);
-               if (!io_submit_sqe(req, sqe, statep, &link))
-                       break;
+               err = io_submit_sqe(req, sqe, statep, &link);
+               if (err)
+                       goto fail_req;
        }
 
        if (unlikely(submitted != nr)) {
@@ -5904,10 +5916,19 @@ fail_req:
        return submitted;
 }
 
+static inline void io_sq_thread_drop_mm(struct io_ring_ctx *ctx)
+{
+       struct mm_struct *mm = current->mm;
+
+       if (mm) {
+               unuse_mm(mm);
+               mmput(mm);
+       }
+}
+
 static int io_sq_thread(void *data)
 {
        struct io_ring_ctx *ctx = data;
-       struct mm_struct *cur_mm = NULL;
        const struct cred *old_cred;
        mm_segment_t old_fs;
        DEFINE_WAIT(wait);
@@ -5948,11 +5969,7 @@ static int io_sq_thread(void *data)
                         * adding ourselves to the waitqueue, as the unuse/drop
                         * may sleep.
                         */
-                       if (cur_mm) {
-                               unuse_mm(cur_mm);
-                               mmput(cur_mm);
-                               cur_mm = NULL;
-                       }
+                       io_sq_thread_drop_mm(ctx);
 
                        /*
                         * We're polling. If we're within the defined idle
@@ -6016,7 +6033,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);
+               ret = io_submit_sqes(ctx, to_submit, NULL, -1, true);
                mutex_unlock(&ctx->uring_lock);
                timeout = jiffies + ctx->sq_thread_idle;
        }
@@ -6025,10 +6042,7 @@ static int io_sq_thread(void *data)
                task_work_run();
 
        set_fs(old_fs);
-       if (cur_mm) {
-               unuse_mm(cur_mm);
-               mmput(cur_mm);
-       }
+       io_sq_thread_drop_mm(ctx);
        revert_creds(old_cred);
 
        kthread_parkme();
@@ -7299,7 +7313,7 @@ static void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx)
         * it could cause shutdown to hang.
         */
        while (ctx->sqo_thread && !wq_has_sleeper(&ctx->sqo_wait))
-               cpu_relax();
+               cond_resched();
 
        io_kill_timeouts(ctx);
        io_poll_remove_all(ctx);
@@ -7328,11 +7342,9 @@ static int io_uring_release(struct inode *inode, struct file *file)
 static void io_uring_cancel_files(struct io_ring_ctx *ctx,
                                  struct files_struct *files)
 {
-       struct io_kiocb *req;
-       DEFINE_WAIT(wait);
-
        while (!list_empty_careful(&ctx->inflight_list)) {
-               struct io_kiocb *cancel_req = NULL;
+               struct io_kiocb *cancel_req = NULL, *req;
+               DEFINE_WAIT(wait);
 
                spin_lock_irq(&ctx->inflight_lock);
                list_for_each_entry(req, &ctx->inflight_list, inflight_entry) {
@@ -7372,6 +7384,7 @@ static void io_uring_cancel_files(struct io_ring_ctx *ctx,
                         */
                        if (refcount_sub_and_test(2, &cancel_req->refs)) {
                                io_put_req(cancel_req);
+                               finish_wait(&ctx->inflight_wait, &wait);
                                continue;
                        }
                }
@@ -7379,8 +7392,8 @@ static void io_uring_cancel_files(struct io_ring_ctx *ctx,
                io_wq_cancel_work(ctx->io_wq, &cancel_req->work);
                io_put_req(cancel_req);
                schedule();
+               finish_wait(&ctx->inflight_wait, &wait);
        }
-       finish_wait(&ctx->inflight_wait, &wait);
 }
 
 static int io_uring_flush(struct file *file, void *data)
@@ -7509,13 +7522,8 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
                        wake_up(&ctx->sqo_wait);
                submitted = to_submit;
        } else if (to_submit) {
-               struct mm_struct *cur_mm;
-
                mutex_lock(&ctx->uring_lock);
-               /* already have mm, so io_submit_sqes() won't try to grab it */
-               cur_mm = ctx->sqo_mm;
-               submitted = io_submit_sqes(ctx, to_submit, f.file, fd,
-                                          &cur_mm, false);
+               submitted = io_submit_sqes(ctx, to_submit, f.file, fd, false);
                mutex_unlock(&ctx->uring_lock);
 
                if (submitted != to_submit)
@@ -7734,7 +7742,8 @@ err:
        return ret;
 }
 
-static int io_uring_create(unsigned entries, struct io_uring_params *p)
+static int io_uring_create(unsigned entries, struct io_uring_params *p,
+                          struct io_uring_params __user *params)
 {
        struct user_struct *user = NULL;
        struct io_ring_ctx *ctx;
@@ -7826,6 +7835,14 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p)
        p->cq_off.overflow = offsetof(struct io_rings, cq_overflow);
        p->cq_off.cqes = offsetof(struct io_rings, cqes);
 
+       p->features = IORING_FEAT_SINGLE_MMAP | IORING_FEAT_NODROP |
+                       IORING_FEAT_SUBMIT_STABLE | IORING_FEAT_RW_CUR_POS |
+                       IORING_FEAT_CUR_PERSONALITY | IORING_FEAT_FAST_POLL;
+
+       if (copy_to_user(params, p, sizeof(*p))) {
+               ret = -EFAULT;
+               goto err;
+       }
        /*
         * Install ring fd as the very last thing, so we don't risk someone
         * having closed it before we finish setup
@@ -7834,9 +7851,6 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p)
        if (ret < 0)
                goto err;
 
-       p->features = IORING_FEAT_SINGLE_MMAP | IORING_FEAT_NODROP |
-                       IORING_FEAT_SUBMIT_STABLE | IORING_FEAT_RW_CUR_POS |
-                       IORING_FEAT_CUR_PERSONALITY | IORING_FEAT_FAST_POLL;
        trace_io_uring_create(ret, ctx, p->sq_entries, p->cq_entries, p->flags);
        return ret;
 err:
@@ -7852,7 +7866,6 @@ err:
 static long io_uring_setup(u32 entries, struct io_uring_params __user *params)
 {
        struct io_uring_params p;
-       long ret;
        int i;
 
        if (copy_from_user(&p, params, sizeof(p)))
@@ -7867,14 +7880,7 @@ static long io_uring_setup(u32 entries, struct io_uring_params __user *params)
                        IORING_SETUP_CLAMP | IORING_SETUP_ATTACH_WQ))
                return -EINVAL;
 
-       ret = io_uring_create(entries, &p);
-       if (ret < 0)
-               return ret;
-
-       if (copy_to_user(params, &p, sizeof(p)))
-               return -EFAULT;
-
-       return ret;
+       return  io_uring_create(entries, &p, params);
 }
 
 SYSCALL_DEFINE2(io_uring_setup, u32, entries,
index 282d45be6f453b0ad4ff084d00bc80864157dd25..5e80b40bc1b5cab63aa4472a2616aa06d6169a45 100644 (file)
@@ -55,6 +55,7 @@ EXPORT_SYMBOL(vfs_ioctl);
 static int ioctl_fibmap(struct file *filp, int __user *p)
 {
        struct inode *inode = file_inode(filp);
+       struct super_block *sb = inode->i_sb;
        int error, ur_block;
        sector_t block;
 
@@ -71,6 +72,13 @@ static int ioctl_fibmap(struct file *filp, int __user *p)
        block = ur_block;
        error = bmap(inode, &block);
 
+       if (block > INT_MAX) {
+               error = -ERANGE;
+               pr_warn_ratelimited("[%s/%d] FS: %s File: %pD4 would truncate fibmap result\n",
+                                   current->comm, task_pid_nr(current),
+                                   sb->s_id, filp);
+       }
+
        if (error)
                ur_block = 0;
        else
index bccf305ea9ce26d1f34ac9f10157af448c1f3174..d55e8f491a5e51d1d45c0053db38a41af883eb4f 100644 (file)
@@ -117,10 +117,7 @@ iomap_bmap_actor(struct inode *inode, loff_t pos, loff_t length,
 
        if (iomap->type == IOMAP_MAPPED) {
                addr = (pos - iomap->offset + iomap->addr) >> inode->i_blkbits;
-               if (addr > INT_MAX)
-                       WARN(1, "would truncate bmap result\n");
-               else
-                       *bno = addr;
+               *bno = addr;
        }
        return 0;
 }
index c5c3fc6e6c600b427c991d4be3a83879bbd2b48c..26c94b32d6f49e15f2c4e4a50d219f6a8592e034 100644 (file)
@@ -253,37 +253,45 @@ int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
 
 int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
-       struct posix_acl *alloc = NULL, *dfacl = NULL;
+       struct posix_acl *orig = acl, *dfacl = NULL, *alloc;
        int status;
 
        if (S_ISDIR(inode->i_mode)) {
                switch(type) {
                case ACL_TYPE_ACCESS:
-                       alloc = dfacl = get_acl(inode, ACL_TYPE_DEFAULT);
+                       alloc = get_acl(inode, ACL_TYPE_DEFAULT);
                        if (IS_ERR(alloc))
                                goto fail;
+                       dfacl = alloc;
                        break;
 
                case ACL_TYPE_DEFAULT:
-                       dfacl = acl;
-                       alloc = acl = get_acl(inode, ACL_TYPE_ACCESS);
+                       alloc = get_acl(inode, ACL_TYPE_ACCESS);
                        if (IS_ERR(alloc))
                                goto fail;
+                       dfacl = acl;
+                       acl = alloc;
                        break;
                }
        }
 
        if (acl == NULL) {
-               alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
+               alloc = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
                if (IS_ERR(alloc))
                        goto fail;
+               acl = alloc;
        }
        status = __nfs3_proc_setacls(inode, acl, dfacl);
-       posix_acl_release(alloc);
+out:
+       if (acl != orig)
+               posix_acl_release(acl);
+       if (dfacl != orig)
+               posix_acl_release(dfacl);
        return status;
 
 fail:
-       return PTR_ERR(alloc);
+       status = PTR_ERR(alloc);
+       goto out;
 }
 
 const struct xattr_handler *nfs3_xattr_handlers[] = {
index 512afb1c786773761691ed6820b0f2268113d4e2..a0c1e653a935875823cb255f80db3de20004ab07 100644 (file)
@@ -7891,6 +7891,7 @@ static void
 nfs4_bind_one_conn_to_session_done(struct rpc_task *task, void *calldata)
 {
        struct nfs41_bind_conn_to_session_args *args = task->tk_msg.rpc_argp;
+       struct nfs41_bind_conn_to_session_res *res = task->tk_msg.rpc_resp;
        struct nfs_client *clp = args->client;
 
        switch (task->tk_status) {
@@ -7899,6 +7900,12 @@ nfs4_bind_one_conn_to_session_done(struct rpc_task *task, void *calldata)
                nfs4_schedule_session_recovery(clp->cl_session,
                                task->tk_status);
        }
+       if (args->dir == NFS4_CDFC4_FORE_OR_BOTH &&
+                       res->dir != NFS4_CDFS4_BOTH) {
+               rpc_task_close_connection(task);
+               if (args->retries++ < MAX_BIND_CONN_TO_SESSION_RETRIES)
+                       rpc_restart_call(task);
+       }
 }
 
 static const struct rpc_call_ops nfs4_bind_one_conn_to_session_ops = {
@@ -7921,6 +7928,7 @@ int nfs4_proc_bind_one_conn_to_session(struct rpc_clnt *clnt,
        struct nfs41_bind_conn_to_session_args args = {
                .client = clp,
                .dir = NFS4_CDFC4_FORE_OR_BOTH,
+               .retries = 0,
        };
        struct nfs41_bind_conn_to_session_res res;
        struct rpc_message msg = {
@@ -9191,8 +9199,7 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout)
        nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0, 0);
 
        task = rpc_run_task(&task_setup_data);
-       if (IS_ERR(task))
-               return ERR_CAST(task);
+
        status = rpc_wait_for_completion_task(task);
        if (status != 0)
                goto out;
index f2dc35c22964c3da42da19c2ff954e7cdd7274f3..dd2e14f5875d852cefaf4dab5887b01b2f5cbbd9 100644 (file)
@@ -1332,13 +1332,15 @@ _pnfs_return_layout(struct inode *ino)
                        !valid_layout) {
                spin_unlock(&ino->i_lock);
                dprintk("NFS: %s no layout segments to return\n", __func__);
-               goto out_put_layout_hdr;
+               goto out_wait_layoutreturn;
        }
 
        send = pnfs_prepare_layoutreturn(lo, &stateid, &cred, NULL);
        spin_unlock(&ino->i_lock);
        if (send)
                status = pnfs_send_layoutreturn(lo, &stateid, &cred, IOMODE_ANY, true);
+out_wait_layoutreturn:
+       wait_on_bit(&lo->plh_flags, NFS_LAYOUT_RETURN, TASK_UNINTERRUPTIBLE);
 out_put_layout_hdr:
        pnfs_free_lseg_list(&tmp_list);
        pnfs_put_layout_hdr(lo);
@@ -1456,18 +1458,15 @@ retry:
        /* lo ref dropped in pnfs_roc_release() */
        layoutreturn = pnfs_prepare_layoutreturn(lo, &stateid, &lc_cred, &iomode);
        /* If the creds don't match, we can't compound the layoutreturn */
-       if (!layoutreturn)
+       if (!layoutreturn || cred_fscmp(cred, lc_cred) != 0)
                goto out_noroc;
-       if (cred_fscmp(cred, lc_cred) != 0)
-               goto out_noroc_put_cred;
 
        roc = layoutreturn;
        pnfs_init_layoutreturn_args(args, lo, &stateid, iomode);
        res->lrs_present = 0;
        layoutreturn = false;
-
-out_noroc_put_cred:
        put_cred(lc_cred);
+
 out_noroc:
        spin_unlock(&ino->i_lock);
        rcu_read_unlock();
@@ -2023,6 +2022,7 @@ lookup_again:
                        goto lookup_again;
                }
 
+               spin_unlock(&ino->i_lock);
                first = true;
                status = nfs4_select_rw_stateid(ctx->state,
                                        iomode == IOMODE_RW ? FMODE_WRITE : FMODE_READ,
@@ -2032,12 +2032,12 @@ lookup_again:
                        trace_pnfs_update_layout(ino, pos, count,
                                        iomode, lo, lseg,
                                        PNFS_UPDATE_LAYOUT_INVALID_OPEN);
-                       spin_unlock(&ino->i_lock);
                        nfs4_schedule_stateid_recovery(server, ctx->state);
                        pnfs_clear_first_layoutget(lo);
                        pnfs_put_layout_hdr(lo);
                        goto lookup_again;
                }
+               spin_lock(&ino->i_lock);
        } else {
                nfs4_stateid_copy(&stateid, &lo->plh_stateid);
        }
index 59ef3b13ccca2521a996c776aea55363ae05bbe1..bdb6d0c2e7550bd0d20c8ceb91918a54c849da3d 100644 (file)
@@ -185,7 +185,7 @@ static int __nfs_list_for_each_server(struct list_head *head,
 
        rcu_read_lock();
        list_for_each_entry_rcu(server, head, client_link) {
-               if (!nfs_sb_active(server->super))
+               if (!(server->super && nfs_sb_active(server->super)))
                        continue;
                rcu_read_unlock();
                if (last)
index c3b11a715082914c2bfee7be0d27a507be967fdd..5cf91322de0fc57f895d857d2c37ec436b6b862d 100644 (file)
@@ -1312,6 +1312,7 @@ nfsd4_run_cb_work(struct work_struct *work)
                container_of(work, struct nfsd4_callback, cb_work);
        struct nfs4_client *clp = cb->cb_clp;
        struct rpc_clnt *clnt;
+       int flags;
 
        if (cb->cb_need_restart) {
                cb->cb_need_restart = false;
@@ -1340,7 +1341,8 @@ nfsd4_run_cb_work(struct work_struct *work)
        }
 
        cb->cb_msg.rpc_cred = clp->cl_cb_cred;
-       rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
+       flags = clp->cl_minorversion ? RPC_TASK_NOCONNECT : RPC_TASK_SOFTCONN;
+       rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | flags,
                        cb->cb_ops ? &nfsd4_cb_ops : &nfsd4_cb_probe_ops, cb);
 }
 
index e32ecedece0feb808567c92c1137ddcb20537d85..c107caa5652544ebadfb746663a551b022c75eb6 100644 (file)
@@ -267,6 +267,8 @@ find_or_allocate_block(struct nfs4_lockowner *lo, struct knfsd_fh *fh,
        if (!nbl) {
                nbl= kmalloc(sizeof(*nbl), GFP_KERNEL);
                if (nbl) {
+                       INIT_LIST_HEAD(&nbl->nbl_list);
+                       INIT_LIST_HEAD(&nbl->nbl_lru);
                        fh_copy_shallow(&nbl->nbl_fh, fh);
                        locks_init_lock(&nbl->nbl_lock);
                        nfsd4_init_cb(&nbl->nbl_cb, lo->lo_owner.so_client,
index 8e4f1ace467c1a25db933e33bce9de47d6995a26..1de77f1a600b20eac9414fd2d4716396b97de101 100644 (file)
@@ -275,7 +275,6 @@ static ssize_t dlmfs_file_write(struct file *filp,
                                loff_t *ppos)
 {
        int bytes_left;
-       ssize_t writelen;
        char *lvb_buf;
        struct inode *inode = file_inode(filp);
 
@@ -285,32 +284,30 @@ static ssize_t dlmfs_file_write(struct file *filp,
        if (*ppos >= i_size_read(inode))
                return -ENOSPC;
 
+       /* don't write past the lvb */
+       if (count > i_size_read(inode) - *ppos)
+               count = i_size_read(inode) - *ppos;
+
        if (!count)
                return 0;
 
        if (!access_ok(buf, count))
                return -EFAULT;
 
-       /* don't write past the lvb */
-       if ((count + *ppos) > i_size_read(inode))
-               writelen = i_size_read(inode) - *ppos;
-       else
-               writelen = count - *ppos;
-
-       lvb_buf = kmalloc(writelen, GFP_NOFS);
+       lvb_buf = kmalloc(count, GFP_NOFS);
        if (!lvb_buf)
                return -ENOMEM;
 
-       bytes_left = copy_from_user(lvb_buf, buf, writelen);
-       writelen -= bytes_left;
-       if (writelen)
-               user_dlm_write_lvb(inode, lvb_buf, writelen);
+       bytes_left = copy_from_user(lvb_buf, buf, count);
+       count -= bytes_left;
+       if (count)
+               user_dlm_write_lvb(inode, lvb_buf, count);
 
        kfree(lvb_buf);
 
-       *ppos = *ppos + writelen;
-       mlog(0, "wrote %zd bytes\n", writelen);
-       return writelen;
+       *ppos = *ppos + count;
+       mlog(0, "wrote %zu bytes\n", count);
+       return count;
 }
 
 static void dlmfs_init_once(void *foo)
index 49f6d7ff21394f5e15e440ade00ba3363e27cf68..1106137c747a3aab8f8340751eb713d6d936797f 100644 (file)
@@ -261,14 +261,13 @@ static int propagate_one(struct mount *m)
        child = copy_tree(last_source, last_source->mnt.mnt_root, type);
        if (IS_ERR(child))
                return PTR_ERR(child);
+       read_seqlock_excl(&mount_lock);
        mnt_set_mountpoint(m, mp, child);
+       if (m->mnt_master != dest_master)
+               SET_MNT_MARK(m->mnt_master);
+       read_sequnlock_excl(&mount_lock);
        last_dest = m;
        last_source = child;
-       if (m->mnt_master != dest_master) {
-               read_seqlock_excl(&mount_lock);
-               SET_MNT_MARK(m->mnt_master);
-               read_sequnlock_excl(&mount_lock);
-       }
        hlist_add_head(&child->mnt_hash, list);
        return count_mounts(m->mnt_ns, child);
 }
index 6042b646ab2797acaa50ad0023e932300a7a42af..eb2255e95f62b799cd51fe5adc8a5169157a12cc 100644 (file)
@@ -1573,6 +1573,7 @@ static ssize_t timens_offsets_write(struct file *file, const char __user *buf,
        noffsets = 0;
        for (pos = kbuf; pos; pos = next_line) {
                struct proc_timens_offset *off = &offsets[noffsets];
+               char clock[10];
                int err;
 
                /* Find the end of line and ensure we don't look past it */
@@ -1584,10 +1585,21 @@ static ssize_t timens_offsets_write(struct file *file, const char __user *buf,
                                next_line = NULL;
                }
 
-               err = sscanf(pos, "%u %lld %lu", &off->clockid,
+               err = sscanf(pos, "%9s %lld %lu", clock,
                                &off->val.tv_sec, &off->val.tv_nsec);
                if (err != 3 || off->val.tv_nsec >= NSEC_PER_SEC)
                        goto out;
+
+               clock[sizeof(clock) - 1] = 0;
+               if (strcmp(clock, "monotonic") == 0 ||
+                   strcmp(clock, __stringify(CLOCK_MONOTONIC)) == 0)
+                       off->clockid = CLOCK_MONOTONIC;
+               else if (strcmp(clock, "boottime") == 0 ||
+                        strcmp(clock, __stringify(CLOCK_BOOTTIME)) == 0)
+                       off->clockid = CLOCK_BOOTTIME;
+               else
+                       goto out;
+
                noffsets++;
                if (noffsets == ARRAY_SIZE(offsets)) {
                        if (next_line)
@@ -3274,7 +3286,6 @@ static const struct inode_operations proc_tgid_base_inode_operations = {
 void proc_flush_pid(struct pid *pid)
 {
        proc_invalidate_siblings_dcache(&pid->inodes, &pid->lock);
-       put_pid(pid);
 }
 
 static struct dentry *proc_pid_instantiate(struct dentry * dentry,
index 2633f10446c3befc0710775a78fa340cb7224889..cdbe9293ea55148d284d8990a563702a9f6f7a55 100644 (file)
@@ -196,6 +196,13 @@ static void proc_kill_sb(struct super_block *sb)
        if (ns->proc_thread_self)
                dput(ns->proc_thread_self);
        kill_anon_super(sb);
+
+       /* Make the pid namespace safe for the next mount of proc */
+       ns->proc_self = NULL;
+       ns->proc_thread_self = NULL;
+       ns->pid_gid = GLOBAL_ROOT_GID;
+       ns->hide_pid = 0;
+
        put_pid_ns(ns);
 }
 
index 7dc800cce35430962d9cb12ac098801efe80ccdb..c663202da8de79d5e432321194a9551416ff66c1 100644 (file)
@@ -266,7 +266,8 @@ static int vmcoredd_mmap_dumps(struct vm_area_struct *vma, unsigned long dst,
                if (start < offset + dump->size) {
                        tsz = min(offset + (u64)dump->size - start, (u64)size);
                        buf = dump->buf + start - offset;
-                       if (remap_vmalloc_range_partial(vma, dst, buf, tsz)) {
+                       if (remap_vmalloc_range_partial(vma, dst, buf, 0,
+                                                       tsz)) {
                                ret = -EFAULT;
                                goto out_unlock;
                        }
@@ -624,7 +625,7 @@ static int mmap_vmcore(struct file *file, struct vm_area_struct *vma)
                tsz = min(elfcorebuf_sz + elfnotes_sz - (size_t)start, size);
                kaddr = elfnotes_buf + start - elfcorebuf_sz - vmcoredd_orig_sz;
                if (remap_vmalloc_range_partial(vma, vma->vm_start + len,
-                                               kaddr, tsz))
+                                               kaddr, 0, tsz))
                        goto fail;
 
                size -= tsz;
index 4735defc46ee6a9912d4632f5d041f4d76371a30..fd0a1e7e5959ad748e355b394e61240367b203e7 100644 (file)
@@ -1118,6 +1118,10 @@ long do_splice(struct file *in, loff_t __user *off_in,
        loff_t offset;
        long ret;
 
+       if (unlikely(!(in->f_mode & FMODE_READ) ||
+                    !(out->f_mode & FMODE_WRITE)))
+               return -EBADF;
+
        ipipe = get_pipe_info(in);
        opipe = get_pipe_info(out);
 
@@ -1125,12 +1129,6 @@ long do_splice(struct file *in, loff_t __user *off_in,
                if (off_in || off_out)
                        return -ESPIPE;
 
-               if (!(in->f_mode & FMODE_READ))
-                       return -EBADF;
-
-               if (!(out->f_mode & FMODE_WRITE))
-                       return -EBADF;
-
                /* Splicing to self would be fun, but... */
                if (ipipe == opipe)
                        return -EINVAL;
@@ -1153,9 +1151,6 @@ long do_splice(struct file *in, loff_t __user *off_in,
                        offset = out->f_pos;
                }
 
-               if (unlikely(!(out->f_mode & FMODE_WRITE)))
-                       return -EBADF;
-
                if (unlikely(out->f_flags & O_APPEND))
                        return -EINVAL;
 
@@ -1440,15 +1435,11 @@ SYSCALL_DEFINE6(splice, int, fd_in, loff_t __user *, off_in,
        error = -EBADF;
        in = fdget(fd_in);
        if (in.file) {
-               if (in.file->f_mode & FMODE_READ) {
-                       out = fdget(fd_out);
-                       if (out.file) {
-                               if (out.file->f_mode & FMODE_WRITE)
-                                       error = do_splice(in.file, off_in,
-                                                         out.file, off_out,
-                                                         len, flags);
-                               fdput(out);
-                       }
+               out = fdget(fd_out);
+               if (out.file) {
+                       error = do_splice(in.file, off_in, out.file, off_out,
+                                         len, flags);
+                       fdput(out);
                }
                fdput(in);
        }
@@ -1770,6 +1761,10 @@ static long do_tee(struct file *in, struct file *out, size_t len,
        struct pipe_inode_info *opipe = get_pipe_info(out);
        int ret = -EINVAL;
 
+       if (unlikely(!(in->f_mode & FMODE_READ) ||
+                    !(out->f_mode & FMODE_WRITE)))
+               return -EBADF;
+
        /*
         * Duplicate the contents of ipipe to opipe without actually
         * copying the data.
@@ -1795,7 +1790,7 @@ static long do_tee(struct file *in, struct file *out, size_t len,
 
 SYSCALL_DEFINE4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags)
 {
-       struct fd in;
+       struct fd in, out;
        int error;
 
        if (unlikely(flags & ~SPLICE_F_ALL))
@@ -1807,14 +1802,10 @@ SYSCALL_DEFINE4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags)
        error = -EBADF;
        in = fdget(fdin);
        if (in.file) {
-               if (in.file->f_mode & FMODE_READ) {
-                       struct fd out = fdget(fdout);
-                       if (out.file) {
-                               if (out.file->f_mode & FMODE_WRITE)
-                                       error = do_tee(in.file, out.file,
-                                                       len, flags);
-                               fdput(out);
-                       }
+               out = fdget(fdout);
+               if (out.file) {
+                       error = do_tee(in.file, out.file, len, flags);
+                       fdput(out);
                }
                fdput(in);
        }
index cd352530eca906eb64d722592c85e2fa3ef02886..a288cd60d2aed3f58f442a2a768c8ac785c015ec 100644 (file)
@@ -1302,8 +1302,8 @@ int get_tree_bdev(struct fs_context *fc,
        mutex_lock(&bdev->bd_fsfreeze_mutex);
        if (bdev->bd_fsfreeze_count > 0) {
                mutex_unlock(&bdev->bd_fsfreeze_mutex);
-               blkdev_put(bdev, mode);
                warnf(fc, "%pg: Can't mount, blockdev is frozen", bdev);
+               blkdev_put(bdev, mode);
                return -EBUSY;
        }
 
index 675e269893765a0d8060da04949144236ba48669..8fe03b4a0d2b038e99b4920e8539e1f5363e55d8 100644 (file)
@@ -164,7 +164,7 @@ static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc)
                goto fail_free;
        }
 
-       err = super_setup_bdi_name(sb, "vboxsf-%s.%d", fc->source, sbi->bdi_id);
+       err = super_setup_bdi_name(sb, "vboxsf-%d", sbi->bdi_id);
        if (err)
                goto fail_free;
 
index a7be7a9e5c1ae09ef9515ce04e6df550587dd32d..8bf1d15be3f6a047c0727668641016e64fa11360 100644 (file)
@@ -911,7 +911,12 @@ xfs_eofblocks_worker(
 {
        struct xfs_mount *mp = container_of(to_delayed_work(work),
                                struct xfs_mount, m_eofblocks_work);
+
+       if (!sb_start_write_trylock(mp->m_super))
+               return;
        xfs_icache_free_eofblocks(mp, NULL);
+       sb_end_write(mp->m_super);
+
        xfs_queue_eofblocks(mp);
 }
 
@@ -938,7 +943,12 @@ xfs_cowblocks_worker(
 {
        struct xfs_mount *mp = container_of(to_delayed_work(work),
                                struct xfs_mount, m_cowblocks_work);
+
+       if (!sb_start_write_trylock(mp->m_super))
+               return;
        xfs_icache_free_cowblocks(mp, NULL);
+       sb_end_write(mp->m_super);
+
        xfs_queue_cowblocks(mp);
 }
 
index cdfb3cd9a25bdc523bca574926d5d9da30b10180..309958186d338099cf52e7d9a8a3ce579c626a20 100644 (file)
@@ -2363,7 +2363,10 @@ xfs_file_ioctl(
                if (error)
                        return error;
 
-               return xfs_icache_free_eofblocks(mp, &keofb);
+               sb_start_write(mp->m_super);
+               error = xfs_icache_free_eofblocks(mp, &keofb);
+               sb_end_write(mp->m_super);
+               return error;
        }
 
        default:
index 50c43422fa170eb2e7c8b91dc5329b834750a2e0..b2e4598fdf7d3e17e1dba5ac4d48cb10f07ec05f 100644 (file)
@@ -167,8 +167,12 @@ typedef struct xfs_mount {
        struct xfs_kobj         m_error_meta_kobj;
        struct xfs_error_cfg    m_error_cfg[XFS_ERR_CLASS_MAX][XFS_ERR_ERRNO_MAX];
        struct xstats           m_stats;        /* per-fs stats */
-       struct ratelimit_state  m_flush_inodes_ratelimit;
 
+       /*
+        * Workqueue item so that we can coalesce multiple inode flush attempts
+        * into a single flush.
+        */
+       struct work_struct      m_flush_inodes_work;
        struct workqueue_struct *m_buf_workqueue;
        struct workqueue_struct *m_unwritten_workqueue;
        struct workqueue_struct *m_cil_workqueue;
index b0ce04ffd3cd2ddeebc6db96dce35d61cd6413da..107bf2a2f3448a075d66f67fdeed880e5dc6c004 100644 (file)
@@ -1051,6 +1051,7 @@ xfs_reflink_remap_extent(
                uirec.br_startblock = irec->br_startblock + rlen;
                uirec.br_startoff = irec->br_startoff + rlen;
                uirec.br_blockcount = unmap_len - rlen;
+               uirec.br_state = irec->br_state;
                unmap_len = rlen;
 
                /* If this isn't a real mapping, we're done. */
index abf06bf9c3f35021e4fb871c3819ace8716b8849..424bb9a2d53256b2d65ef3f6291ec6bbd53b642c 100644 (file)
@@ -516,6 +516,20 @@ xfs_destroy_mount_workqueues(
        destroy_workqueue(mp->m_buf_workqueue);
 }
 
+static void
+xfs_flush_inodes_worker(
+       struct work_struct      *work)
+{
+       struct xfs_mount        *mp = container_of(work, struct xfs_mount,
+                                                  m_flush_inodes_work);
+       struct super_block      *sb = mp->m_super;
+
+       if (down_read_trylock(&sb->s_umount)) {
+               sync_inodes_sb(sb);
+               up_read(&sb->s_umount);
+       }
+}
+
 /*
  * Flush all dirty data to disk. Must not be called while holding an XFS_ILOCK
  * or a page lock. We use sync_inodes_sb() here to ensure we block while waiting
@@ -526,15 +540,15 @@ void
 xfs_flush_inodes(
        struct xfs_mount        *mp)
 {
-       struct super_block      *sb = mp->m_super;
-
-       if (!__ratelimit(&mp->m_flush_inodes_ratelimit))
+       /*
+        * If flush_work() returns true then that means we waited for a flush
+        * which was already in progress.  Don't bother running another scan.
+        */
+       if (flush_work(&mp->m_flush_inodes_work))
                return;
 
-       if (down_read_trylock(&sb->s_umount)) {
-               sync_inodes_sb(sb);
-               up_read(&sb->s_umount);
-       }
+       queue_work(mp->m_sync_workqueue, &mp->m_flush_inodes_work);
+       flush_work(&mp->m_flush_inodes_work);
 }
 
 /* Catch misguided souls that try to use this interface on XFS */
@@ -1369,17 +1383,6 @@ xfs_fc_fill_super(
        if (error)
                goto out_free_names;
 
-       /*
-        * Cap the number of invocations of xfs_flush_inodes to 16 for every
-        * quarter of a second.  The magic numbers here were determined by
-        * observation neither to cause stalls in writeback when there are a
-        * lot of IO threads and the fs is near ENOSPC, nor cause any fstest
-        * regressions.  YMMV.
-        */
-       ratelimit_state_init(&mp->m_flush_inodes_ratelimit, HZ / 4, 16);
-       ratelimit_set_flags(&mp->m_flush_inodes_ratelimit,
-                       RATELIMIT_MSG_ON_RELEASE);
-
        error = xfs_init_mount_workqueues(mp);
        if (error)
                goto out_close_devices;
@@ -1752,6 +1755,7 @@ static int xfs_init_fs_context(
        spin_lock_init(&mp->m_perag_lock);
        mutex_init(&mp->m_growlock);
        atomic_set(&mp->m_active_trans, 0);
+       INIT_WORK(&mp->m_flush_inodes_work, xfs_flush_inodes_worker);
        INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);
        INIT_DELAYED_WORK(&mp->m_eofblocks_work, xfs_eofblocks_worker);
        INIT_DELAYED_WORK(&mp->m_cowblocks_work, xfs_cowblocks_worker);
index 36341dfded7096f6d2ad1ef2f1082ace267253be..44ec80e705183bbb85f1707fd25d9f8786b7122a 100644 (file)
@@ -56,6 +56,7 @@ mandatory-y += topology.h
 mandatory-y += trace_clock.h
 mandatory-y += uaccess.h
 mandatory-y += unaligned.h
+mandatory-y += vermagic.h
 mandatory-y += vga.h
 mandatory-y += word-at-a-time.h
 mandatory-y += xor.h
index b3f1082cc435c84efccaa11ec4a0bfc0260568dd..1c4fd950f09123d6802b0dd82be00757eb815992 100644 (file)
@@ -163,7 +163,7 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset,
        return nr_bank;
 }
 
-void hyperv_report_panic(struct pt_regs *regs, long err);
+void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die);
 void hyperv_report_panic_msg(phys_addr_t pa, size_t size);
 bool hv_is_hyperv_initialized(void);
 bool hv_is_hibernation_supported(void);
diff --git a/include/asm-generic/vermagic.h b/include/asm-generic/vermagic.h
new file mode 100644 (file)
index 0000000..084274a
--- /dev/null
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _ASM_GENERIC_VERMAGIC_H
+#define _ASM_GENERIC_VERMAGIC_H
+
+#define MODULE_ARCH_VERMAGIC ""
+
+#endif /* _ASM_GENERIC_VERMAGIC_H */
index 26f0ecf401eaa5787a5eba474dd62942e629ed11..0bbfd647f5c6dec3c12c52c621a94cf57975ebc5 100644 (file)
@@ -65,6 +65,7 @@ struct amba_device {
        struct device           dev;
        struct resource         res;
        struct clk              *pclk;
+       struct device_dma_parameters dma_parms;
        unsigned int            periphid;
        unsigned int            cid;
        struct amba_cs_uci_id   uci;
index 4fc87dee005ab13e8208c5d19c92700384edffbd..7367150f962a333b7f689c84e3ab2223a7281b16 100644 (file)
@@ -54,7 +54,6 @@ enum wb_reason {
        WB_REASON_SYNC,
        WB_REASON_PERIODIC,
        WB_REASON_LAPTOP_TIMER,
-       WB_REASON_FREE_MORE_MEM,
        WB_REASON_FS_FREE_SPACE,
        /*
         * There is no bdi forker thread any more and works are done
@@ -220,6 +219,7 @@ struct backing_dev_info {
        wait_queue_head_t wb_waitq;
 
        struct device *dev;
+       char dev_name[64];
        struct device *owner;
 
        struct timer_list laptop_mode_wb_timer;
index f88197c1ffc2db0fcdbc5b9ab0c9d8b0f95fec43..c9ad5c3b7b4b263dadc3a54d4e58cf09eaa2973d 100644 (file)
@@ -505,13 +505,6 @@ static inline int bdi_rw_congested(struct backing_dev_info *bdi)
                                  (1 << WB_async_congested));
 }
 
-extern const char *bdi_unknown_name;
-
-static inline const char *bdi_dev_name(struct backing_dev_info *bdi)
-{
-       if (!bdi || !bdi->dev)
-               return bdi_unknown_name;
-       return dev_name(bdi->dev);
-}
+const char *bdi_dev_name(struct backing_dev_info *bdi);
 
 #endif /* _LINUX_BACKING_DEV_H */
index c1c0f9ea4e63a9afa1403adb2dd2a9760feebd68..a0ee494a6329a8cc48760bceb81ea6ba9f56585e 100644 (file)
@@ -319,7 +319,7 @@ struct bio_integrity_payload {
        struct work_struct      bip_work;       /* I/O completion */
 
        struct bio_vec          *bip_vec;
-       struct bio_vec          bip_inline_vecs[0];/* embedded bvec array */
+       struct bio_vec          bip_inline_vecs[];/* embedded bvec array */
 };
 
 #if defined(CONFIG_BLK_DEV_INTEGRITY)
index f389d7c724bd2b25a8a6477060079282da7ff88e..b45148ba3291208fe83bcdd60d9c784ba725d4be 100644 (file)
@@ -173,7 +173,7 @@ struct blk_mq_hw_ctx {
         * blocking (BLK_MQ_F_BLOCKING). Must be the last member - see also
         * blk_mq_hw_ctx_size().
         */
-       struct srcu_struct      srcu[0];
+       struct srcu_struct      srcu[];
 };
 
 /**
index 70254ae117690c40fa40692bbf790c13cfcdacdf..31eb92876be7ccf2d48f6c453f312b371bcdda50 100644 (file)
@@ -198,7 +198,7 @@ struct bio {
         * double allocations for a small number of bio_vecs. This member
         * MUST obviously be kept at the very end of the bio.
         */
-       struct bio_vec          bi_inline_vecs[0];
+       struct bio_vec          bi_inline_vecs[];
 };
 
 #define BIO_RESET_BYTES                offsetof(struct bio, bi_max_vecs)
index e0b020eaf32e252ba7536958f5035747fe358d0a..15b765a181b8504f10ba7b827f9cbe3ddbbfae28 100644 (file)
@@ -189,6 +189,8 @@ struct buffer_head *__getblk_gfp(struct block_device *bdev, sector_t block,
 void __brelse(struct buffer_head *);
 void __bforget(struct buffer_head *);
 void __breadahead(struct block_device *, sector_t block, unsigned int size);
+void __breadahead_gfp(struct block_device *, sector_t block, unsigned int size,
+                 gfp_t gfp);
 struct buffer_head *__bread_gfp(struct block_device *,
                                sector_t block, unsigned size, gfp_t gfp);
 void invalidate_bh_lrus(void);
@@ -319,6 +321,12 @@ sb_breadahead(struct super_block *sb, sector_t block)
        __breadahead(sb->s_bdev, block, sb->s_blocksize);
 }
 
+static inline void
+sb_breadahead_unmovable(struct super_block *sb, sector_t block)
+{
+       __breadahead_gfp(sb->s_bdev, block, sb->s_blocksize, 0);
+}
+
 static inline struct buffer_head *
 sb_getblk(struct super_block *sb, sector_t block)
 {
index 511a37302fea6ff66f008586056a6768c0ef3e13..5fd627e9da19859f28c3de93446c3c4e367c269c 100644 (file)
@@ -189,7 +189,7 @@ struct __packed pucan_rx_msg {
        u8      client;
        __le16  flags;
        __le32  can_id;
-       u8      d[0];
+       u8      d[];
 };
 
 /* uCAN error types */
@@ -266,7 +266,7 @@ struct __packed pucan_tx_msg {
        u8      client;
        __le16  flags;
        __le32  can_id;
-       u8      d[0];
+       u8      d[];
 };
 
 /* build the cmd opcode_channel field with respect to the correct endianness */
index 02edeafcb2bf84af2354a9882b82a7ef6e57fa0f..be8aea04d0234d7578b78ca15b9a2d14815cd2bb 100644 (file)
@@ -28,7 +28,7 @@ struct cpu_rmap {
        struct {
                u16     index;
                u16     dist;
-       }               near[0];
+       }               near[];
 };
 #define CPU_RMAP_DIST_INF 0xffff
 
index a274d95fa66e4c9e9ef3ea12b478ac940e48e1f5..63cb3606dea7fde966de75791bf2225c5dea8674 100644 (file)
@@ -103,8 +103,8 @@ void debugfs_create_u8(const char *name, umode_t mode, struct dentry *parent,
                       u8 *value);
 void debugfs_create_u16(const char *name, umode_t mode, struct dentry *parent,
                        u16 *value);
-struct dentry *debugfs_create_u32(const char *name, umode_t mode,
-                                 struct dentry *parent, u32 *value);
+void debugfs_create_u32(const char *name, umode_t mode, struct dentry *parent,
+                       u32 *value);
 void debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent,
                        u64 *value);
 struct dentry *debugfs_create_ulong(const char *name, umode_t mode,
@@ -250,12 +250,8 @@ static inline void debugfs_create_u8(const char *name, umode_t mode,
 static inline void debugfs_create_u16(const char *name, umode_t mode,
                                      struct dentry *parent, u16 *value) { }
 
-static inline struct dentry *debugfs_create_u32(const char *name, umode_t mode,
-                                               struct dentry *parent,
-                                               u32 *value)
-{
-       return ERR_PTR(-ENODEV);
-}
+static inline void debugfs_create_u32(const char *name, umode_t mode,
+                                     struct dentry *parent, u32 *value) { }
 
 static inline void debugfs_create_u64(const char *name, umode_t mode,
                                      struct dentry *parent, u64 *value) { }
index 594fc66a395a7b6a42db741f43726e219cc13362..2ace69e4108850674030db3cf785f117d3391110 100644 (file)
@@ -29,7 +29,7 @@ struct pubkey_hdr {
        uint32_t        timestamp;      /* key made, always 0 for now */
        uint8_t         algo;
        uint8_t         nmpi;
-       char            mpi[0];
+       char            mpi[];
 } __packed;
 
 struct signature_hdr {
@@ -39,7 +39,7 @@ struct signature_hdr {
        uint8_t         hash;
        uint8_t         keyid[8];
        uint8_t         nmpi;
-       char            mpi[0];
+       char            mpi[];
 } __packed;
 
 #if defined(CONFIG_SIGNATURE) || defined(CONFIG_SIGNATURE_MODULE)
index fc61f3cff72f7b79f1ed0fe4a51b4e973e705901..99002220cd452646b924f76f3c37909d804a67d4 100644 (file)
@@ -7,7 +7,7 @@ struct linux_dirent64 {
        s64             d_off;
        unsigned short  d_reclen;
        unsigned char   d_type;
-       char            d_name[0];
+       char            d_name[];
 };
 
 #endif
index 1ade486fc2bbcf99580c82c531ece8622b2077aa..57bcef6f988a2d237f8e986bc9cefd01c639340d 100644 (file)
@@ -329,13 +329,12 @@ struct dma_buf {
 
 /**
  * struct dma_buf_attach_ops - importer operations for an attachment
- * @move_notify: [optional] notification that the DMA-buf is moving
  *
  * Attachment operations implemented by the importer.
  */
 struct dma_buf_attach_ops {
        /**
-        * @move_notify
+        * @move_notify: [optional] notification that the DMA-buf is moving
         *
         * If this callback is provided the framework can avoid pinning the
         * backing store while mappings exists.
index 21065c04c4ac3bb380398bc45a6a7f28cdaa1d00..e1c03339918f99b2d48ccf245ec177baec04599d 100644 (file)
@@ -83,9 +83,9 @@ enum dma_transfer_direction {
 /**
  * Interleaved Transfer Request
  * ----------------------------
- * A chunk is collection of contiguous bytes to be transfered.
+ * A chunk is collection of contiguous bytes to be transferred.
  * The gap(in bytes) between two chunks is called inter-chunk-gap(ICG).
- * ICGs may or maynot change between chunks.
+ * ICGs may or may not change between chunks.
  * A FRAME is the smallest series of contiguous {chunk,icg} pairs,
  *  that when repeated an integral number of times, specifies the transfer.
  * A transfer template is specification of a Frame, the number of times
@@ -341,13 +341,11 @@ struct dma_chan {
  * @chan: driver channel device
  * @device: sysfs device
  * @dev_id: parent dma_device dev_id
- * @idr_ref: reference count to gate release of dma_device dev_id
  */
 struct dma_chan_dev {
        struct dma_chan *chan;
        struct device device;
        int dev_id;
-       atomic_t *idr_ref;
 };
 
 /**
@@ -835,6 +833,8 @@ struct dma_device {
        int dev_id;
        struct device *dev;
        struct module *owner;
+       struct ida chan_ida;
+       struct mutex chan_mutex;        /* to protect chan_ida */
 
        u32 src_addr_widths;
        u32 dst_addr_widths;
@@ -1069,7 +1069,7 @@ static inline int dmaengine_terminate_all(struct dma_chan *chan)
  * dmaengine_synchronize() needs to be called before it is safe to free
  * any memory that is accessed by previously submitted descriptors or before
  * freeing any resources accessed from within the completion callback of any
- * perviously submitted descriptors.
+ * previously submitted descriptors.
  *
  * This function can be called from atomic context as well as from within a
  * complete callback of a descriptor submitted on the same channel.
@@ -1091,7 +1091,7 @@ static inline int dmaengine_terminate_async(struct dma_chan *chan)
  *
  * Synchronizes to the DMA channel termination to the current context. When this
  * function returns it is guaranteed that all transfers for previously issued
- * descriptors have stopped and and it is safe to free the memory assoicated
+ * descriptors have stopped and it is safe to free the memory associated
  * with them. Furthermore it is guaranteed that all complete callback functions
  * for a previously submitted descriptor have finished running and it is safe to
  * free resources accessed from within the complete callbacks.
index 564e96f625ff37198d2779720426f509536ee320..1c630e2c2756c5e5c6ce6c391c010333621f475e 100644 (file)
@@ -101,7 +101,7 @@ struct enclosure_device {
        struct device edev;
        struct enclosure_component_callbacks *cb;
        int components;
-       struct enclosure_component component[0];
+       struct enclosure_component component[];
 };
 
 static inline struct enclosure_device *
index d249b88a4d5a731e1bd2dd42e019a123909b9d48..ade6486a3382486752868509838da30da7134f68 100644 (file)
@@ -36,7 +36,7 @@ struct em_cap_state {
 struct em_perf_domain {
        struct em_cap_state *table;
        int nr_cap_states;
-       unsigned long cpus[0];
+       unsigned long cpus[];
 };
 
 #ifdef CONFIG_ENERGY_MODEL
index c1d379bf6ee1542eb420c83dc672a4c8f8ae3e77..a23b26eab479007408a90a2ebe4dfd823d8078a2 100644 (file)
@@ -35,7 +35,7 @@ struct compat_ethtool_rxnfc {
        compat_u64                      data;
        struct compat_ethtool_rx_flow_spec fs;
        u32                             rule_cnt;
-       u32                             rule_locs[0];
+       u32                             rule_locs[];
 };
 
 #endif /* CONFIG_COMPAT */
@@ -462,7 +462,7 @@ int ethtool_check_ops(const struct ethtool_ops *ops);
 
 struct ethtool_rx_flow_rule {
        struct flow_rule        *rule;
-       unsigned long           priv[0];
+       unsigned long           priv[];
 };
 
 struct ethtool_rx_flow_spec_input {
index 4f6f59b4f22a807e55e479468df1f1cb7068cfdc..45cc10cdf6ddd760aeadc92d255f65b132ed67cc 100644 (file)
@@ -983,7 +983,7 @@ struct file_handle {
        __u32 handle_bytes;
        int handle_type;
        /* file identifier */
-       unsigned char f_handle[0];
+       unsigned char f_handle[];
 };
 
 static inline struct file *get_file(struct file *f)
index 5b14a0f381241de51ac575d483847af8fb8b5b3b..0bd581003cd5dfa99dacce00f6b1fd554687f9cd 100644 (file)
@@ -76,7 +76,7 @@ struct gen_pool_chunk {
        void *owner;                    /* private data to retrieve at alloc time */
        unsigned long start_addr;       /* start address of memory chunk */
        unsigned long end_addr;         /* end address of memory chunk (inclusive) */
-       unsigned long bits[0];          /* bitmap for allocating memory chunk */
+       unsigned long bits[];           /* bitmap for allocating memory chunk */
 };
 
 /*
index 456fc17ecb1c3823731ca5768d3ba71ed70308a8..45d36ba4826bd8736b12375b3262f1f7980be50b 100644 (file)
@@ -461,12 +461,6 @@ i2c_new_scanned_device(struct i2c_adapter *adap,
                       unsigned short const *addr_list,
                       int (*probe)(struct i2c_adapter *adap, unsigned short addr));
 
-struct i2c_client *
-i2c_new_probed_device(struct i2c_adapter *adap,
-                      struct i2c_board_info *info,
-                      unsigned short const *addr_list,
-                      int (*probe)(struct i2c_adapter *adap, unsigned short addr));
-
 /* Common custom probe functions */
 int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr);
 
index 463047d0190bc4baa470fd7eb9217ad3ffa97ed3..faa6586a57838554cf02402d6659691f17bd458f 100644 (file)
@@ -38,7 +38,7 @@ struct ip_sf_socklist {
        unsigned int            sl_max;
        unsigned int            sl_count;
        struct rcu_head         rcu;
-       __be32                  sl_addr[0];
+       __be32                  sl_addr[];
 };
 
 #define IP_SFLSIZE(count)      (sizeof(struct ip_sf_socklist) + \
index 98cb5ce0b0a0839a56c9dfd0ee222d7ec0d8aff7..b824877e6d1b6c48ab221ee14c894d3aaef78686 100644 (file)
@@ -18,7 +18,7 @@
 struct ihex_binrec {
        __be32 addr;
        __be16 len;
-       uint8_t data[0];
+       uint8_t data[];
 } __attribute__((packed));
 
 static inline uint16_t ihex_binrec_size(const struct ihex_binrec *p)
index 17f56a070b205a1ebab8cea9ef1ae2c8960238bc..25c87507a1fa79e946f51677d748820b025a99a9 100644 (file)
@@ -600,7 +600,7 @@ void iio_device_unregister(struct iio_dev *indio_dev);
  * 0 on success, negative error number on failure.
  */
 #define devm_iio_device_register(dev, indio_dev) \
-       __devm_iio_device_register((dev), (indio_dev), THIS_MODULE);
+       __devm_iio_device_register((dev), (indio_dev), THIS_MODULE)
 int __devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev,
                               struct module *this_mod);
 void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev);
index 9315fbb87db37ff67413cf4c7ff0bc03f8c27fc4..8d5bc2c237d74a7f937a5b05072384117273a239 100644 (file)
@@ -573,8 +573,6 @@ enum {
 #define IRQ_DEFAULT_INIT_FLAGS ARCH_IRQ_INIT_FLAGS
 
 struct irqaction;
-extern int setup_irq(unsigned int irq, struct irqaction *new);
-extern void remove_irq(unsigned int irq, struct irqaction *act);
 extern int setup_percpu_irq(unsigned int irq, struct irqaction *new);
 extern void remove_percpu_irq(unsigned int irq, struct irqaction *act);
 
@@ -1043,7 +1041,7 @@ struct irq_chip_generic {
        unsigned long           unused;
        struct irq_domain       *domain;
        struct list_head        list;
-       struct irq_chip_type    chip_types[0];
+       struct irq_chip_type    chip_types[];
 };
 
 /**
@@ -1079,7 +1077,7 @@ struct irq_domain_chip_generic {
        unsigned int            irq_flags_to_clear;
        unsigned int            irq_flags_to_set;
        enum irq_gc_flags       gc_flags;
-       struct irq_chip_generic *gc[0];
+       struct irq_chip_generic *gc[];
 };
 
 /* Generic chip callback functions */
index 765d9b769b69504c0033197342d2e9c79f8316b7..6c36b6cc3edf6f46f9050fb3a90e13c8f4f32b25 100644 (file)
 
 #define GICR_TYPER_PLPIS               (1U << 0)
 #define GICR_TYPER_VLPIS               (1U << 1)
+#define GICR_TYPER_DIRTY               (1U << 2)
 #define GICR_TYPER_DirectLPIS          (1U << 3)
 #define GICR_TYPER_LAST                        (1U << 4)
 #define GICR_TYPER_RVPEID              (1U << 7)
@@ -686,6 +687,7 @@ struct rdists {
        bool                    has_vlpis;
        bool                    has_rvpeid;
        bool                    has_direct_lpi;
+       bool                    has_vpend_valid_dirty;
 };
 
 struct irq_domain;
index 6d58beb65454f7d126c65630c7aef4183e3c76ad..01276e3d01b920702642d789a830cd5d441319cb 100644 (file)
@@ -1048,7 +1048,7 @@ search_memslots(struct kvm_memslots *slots, gfn_t gfn)
                        start = slot + 1;
        }
 
-       if (gfn >= memslots[start].base_gfn &&
+       if (start < slots->used_slots && gfn >= memslots[start].base_gfn &&
            gfn < memslots[start].base_gfn + memslots[start].npages) {
                atomic_set(&slots->lru_slot, start);
                return &memslots[start];
index d5ceb2839a2ded8ccf49524d76a5eedd666b1cd1..9dcaa3e582c90915a1af58a58ef099d88323a5a2 100644 (file)
@@ -34,7 +34,7 @@ struct list_lru_one {
 struct list_lru_memcg {
        struct rcu_head         rcu;
        /* array of per cgroup lists, indexed by memcg_cache_id */
-       struct list_lru_one     *lru[0];
+       struct list_lru_one     *lru[];
 };
 
 struct list_lru_node {
index 9cd4455528e507c9e5b05cf5c63e7e7a1e7ec25b..1bdd027766d4b5864cf2a7d0f40867bab435ee91 100644 (file)
@@ -55,7 +55,7 @@ LSM_HOOK(void, LSM_RET_VOID, bprm_committing_creds, struct linux_binprm *bprm)
 LSM_HOOK(void, LSM_RET_VOID, bprm_committed_creds, struct linux_binprm *bprm)
 LSM_HOOK(int, 0, fs_context_dup, struct fs_context *fc,
         struct fs_context *src_sc)
-LSM_HOOK(int, 0, fs_context_parse_param, struct fs_context *fc,
+LSM_HOOK(int, -ENOPARAM, fs_context_parse_param, struct fs_context *fc,
         struct fs_parameter *param)
 LSM_HOOK(int, 0, sb_alloc_security, struct super_block *sb)
 LSM_HOOK(void, LSM_RET_VOID, sb_free_security, struct super_block *sb)
index 1b4150ff64be53ce4bb7a514968dd3bf1e3c7e93..d275c72c4f8efd09b9b3ccf8a8dffc6344d1a642 100644 (file)
@@ -106,7 +106,7 @@ struct lruvec_stat {
  */
 struct memcg_shrinker_map {
        struct rcu_head rcu;
-       unsigned long map[0];
+       unsigned long map[];
 };
 
 /*
@@ -148,7 +148,7 @@ struct mem_cgroup_threshold_ary {
        /* Size of entries[] */
        unsigned int size;
        /* Array of thresholds */
-       struct mem_cgroup_threshold entries[0];
+       struct mem_cgroup_threshold entries[];
 };
 
 struct mem_cgroup_thresholds {
index ad19960019653fceb12a220f291483246586f3f2..3d7c3c26eeb9a829b0e289746c77a980242ef82d 100644 (file)
@@ -53,9 +53,9 @@ enum mhi_callback {
  * @MHI_CHAIN: Linked transfer
  */
 enum mhi_flags {
-       MHI_EOB,
-       MHI_EOT,
-       MHI_CHAIN,
+       MHI_EOB = BIT(0),
+       MHI_EOT = BIT(1),
+       MHI_CHAIN = BIT(2),
 };
 
 /**
@@ -335,14 +335,15 @@ struct mhi_controller_config {
  * @syserr_worker: System error worker
  * @state_event: State change event
  * @status_cb: CB function to notify power states of the device (required)
- * @link_status: CB function to query link status of the device (required)
  * @wake_get: CB function to assert device wake (optional)
  * @wake_put: CB function to de-assert device wake (optional)
  * @wake_toggle: CB function to assert and de-assert device wake (optional)
  * @runtime_get: CB function to controller runtime resume (required)
- * @runtimet_put: CB function to decrement pm usage (required)
+ * @runtime_put: CB function to decrement pm usage (required)
  * @map_single: CB function to create TRE buffer
  * @unmap_single: CB function to destroy TRE buffer
+ * @read_reg: Read a MHI register via the physical link (required)
+ * @write_reg: Write a MHI register via the physical link (required)
  * @buffer_len: Bounce buffer length
  * @bounce_buf: Use of bounce buffer
  * @fbc_download: MHI host needs to do complete image transfer (optional)
@@ -417,7 +418,6 @@ struct mhi_controller {
 
        void (*status_cb)(struct mhi_controller *mhi_cntrl,
                          enum mhi_callback cb);
-       int (*link_status)(struct mhi_controller *mhi_cntrl);
        void (*wake_get)(struct mhi_controller *mhi_cntrl, bool override);
        void (*wake_put)(struct mhi_controller *mhi_cntrl, bool override);
        void (*wake_toggle)(struct mhi_controller *mhi_cntrl);
@@ -427,6 +427,10 @@ struct mhi_controller {
                          struct mhi_buf_info *buf);
        void (*unmap_single)(struct mhi_controller *mhi_cntrl,
                             struct mhi_buf_info *buf);
+       int (*read_reg)(struct mhi_controller *mhi_cntrl, void __iomem *addr,
+                       u32 *out);
+       void (*write_reg)(struct mhi_controller *mhi_cntrl, void __iomem *addr,
+                         u32 val);
 
        size_t buffer_len;
        bool bounce_buf;
index 440230488025199340c11cd06d8f76974b431a45..e5f3e7d8d3d59a4e4e558f82338f2de08f18c4de 100644 (file)
@@ -1317,11 +1317,13 @@ struct nfs41_impl_id {
        struct nfstime4                 date;
 };
 
+#define MAX_BIND_CONN_TO_SESSION_RETRIES 3
 struct nfs41_bind_conn_to_session_args {
        struct nfs_client               *client;
        struct nfs4_sessionid           sessionid;
        u32                             dir;
        bool                            use_conn_in_rdma_mode;
+       int                             retries;
 };
 
 struct nfs41_bind_conn_to_session_res {
index c588be843f61ba2c37a763253a7b4bba5077b729..0ecce6aa69d5e3a1ade4ef14b12b1141b5e4be69 100644 (file)
@@ -185,6 +185,7 @@ int cros_ec_sensorhub_register_push_data(struct cros_ec_sensorhub *sensorhub,
 void cros_ec_sensorhub_unregister_push_data(struct cros_ec_sensorhub *sensorhub,
                                            u8 sensor_num);
 
+int cros_ec_sensorhub_ring_allocate(struct cros_ec_sensorhub *sensorhub);
 int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub);
 void cros_ec_sensorhub_ring_remove(void *arg);
 int cros_ec_sensorhub_ring_fifo_enable(struct cros_ec_sensorhub *sensorhub,
index 25f46a939637f2513c6bd6537b417bb8dffc51a0..3e268e636b5bcd005e839c6b213dc44f57a0d743 100644 (file)
@@ -83,7 +83,7 @@ struct wilco_ec_response {
        u16 result;
        u16 data_size;
        u8 reserved[2];
-       u8 data[0];
+       u8 data[];
 } __packed;
 
 /**
index bdc35753ef7c1cf8488ef1b3079114a600fa8da1..77a2aada106dcb016833d77cc3b0842c35a4db4b 100644 (file)
@@ -25,6 +25,7 @@ struct platform_device {
        bool            id_auto;
        struct device   dev;
        u64             platform_dma_mask;
+       struct device_dma_parameters dma_parms;
        u32             num_resources;
        struct resource *resource;
 
index b18dca67253d662b42a68d2d5cb336cd069f9352..c2a7cfbca7131f4be57971a464475fd5faf183c4 100644 (file)
@@ -220,10 +220,8 @@ struct pnp_card {
 #define global_to_pnp_card(n) list_entry(n, struct pnp_card, global_list)
 #define protocol_to_pnp_card(n) list_entry(n, struct pnp_card, protocol_list)
 #define to_pnp_card(n) container_of(n, struct pnp_card, dev)
-#define pnp_for_each_card(card) \
-       for((card) = global_to_pnp_card(pnp_cards.next); \
-       (card) != global_to_pnp_card(&pnp_cards); \
-       (card) = global_to_pnp_card((card)->global_list.next))
+#define pnp_for_each_card(card)        \
+       list_for_each_entry(card, &pnp_cards, global_list)
 
 struct pnp_card_link {
        struct pnp_card *card;
@@ -276,14 +274,9 @@ struct pnp_dev {
 #define card_to_pnp_dev(n) list_entry(n, struct pnp_dev, card_list)
 #define protocol_to_pnp_dev(n) list_entry(n, struct pnp_dev, protocol_list)
 #define        to_pnp_dev(n) container_of(n, struct pnp_dev, dev)
-#define pnp_for_each_dev(dev) \
-       for((dev) = global_to_pnp_dev(pnp_global.next); \
-       (dev) != global_to_pnp_dev(&pnp_global); \
-       (dev) = global_to_pnp_dev((dev)->global_list.next))
-#define card_for_each_dev(card,dev) \
-       for((dev) = card_to_pnp_dev((card)->devices.next); \
-       (dev) != card_to_pnp_dev(&(card)->devices); \
-       (dev) = card_to_pnp_dev((dev)->card_list.next))
+#define pnp_for_each_dev(dev) list_for_each_entry(dev, &pnp_global, global_list)
+#define card_for_each_dev(card, dev)   \
+       list_for_each_entry(dev, &(card)->devices, card_list)
 #define pnp_dev_name(dev) (dev)->name
 
 static inline void *pnp_get_drvdata(struct pnp_dev *pdev)
@@ -437,14 +430,10 @@ struct pnp_protocol {
 };
 
 #define to_pnp_protocol(n) list_entry(n, struct pnp_protocol, protocol_list)
-#define protocol_for_each_card(protocol,card) \
-       for((card) = protocol_to_pnp_card((protocol)->cards.next); \
-       (card) != protocol_to_pnp_card(&(protocol)->cards); \
-       (card) = protocol_to_pnp_card((card)->protocol_list.next))
-#define protocol_for_each_dev(protocol,dev) \
-       for((dev) = protocol_to_pnp_dev((protocol)->devices.next); \
-       (dev) != protocol_to_pnp_dev(&(protocol)->devices); \
-       (dev) = protocol_to_pnp_dev((dev)->protocol_list.next))
+#define protocol_for_each_card(protocol, card) \
+       list_for_each_entry(card, &(protocol)->cards, protocol_list)
+#define protocol_for_each_dev(protocol, dev)   \
+       list_for_each_entry(dev, &(protocol)->devices, protocol_list)
 
 extern struct bus_type pnp_bus_type;
 
index 540595a321a762d305bea8bb1ffa6586a6df0585..90797f1b421d8fec87325268aeae3181fb933978 100644 (file)
@@ -28,7 +28,7 @@ struct posix_acl {
        refcount_t              a_refcount;
        struct rcu_head         a_rcu;
        unsigned int            a_count;
-       struct posix_acl_entry  a_entries[0];
+       struct posix_acl_entry  a_entries[];
 };
 
 #define FOREACH_ACL_ENTRY(pa, acl, pe) \
index 317bace5ac641db4ac34df344b835c6aca3b43f8..2cd637268b4f9254a5751cefa3d84726457f6df8 100644 (file)
@@ -100,7 +100,7 @@ struct rio_switch {
        u32 port_ok;
        struct rio_switch_ops *ops;
        spinlock_t lock;
-       struct rio_dev *nextdev[0];
+       struct rio_dev *nextdev[];
 };
 
 /**
@@ -201,7 +201,7 @@ struct rio_dev {
        u8 hopcount;
        struct rio_dev *prev;
        atomic_t state;
-       struct rio_switch rswitch[0];   /* RIO switch info */
+       struct rio_switch rswitch[];    /* RIO switch info */
 };
 
 #define rio_dev_g(n) list_entry(n, struct rio_dev, global_list)
index 5974cedd008c345a3261229e30ca7e290d388d76..238bb85243d3653fee5170c58ea2112da6289154 100644 (file)
@@ -54,7 +54,7 @@ struct rs_codec {
  */
 struct rs_control {
        struct rs_codec *codec;
-       uint16_t        buffers[0];
+       uint16_t        buffers[];
 };
 
 /* General purpose RS codec, 8-bit data width, symbol width 1-15 bit  */
index af9319e4cfb967c98a3a151bbe5829675308fea5..95253ad792b0c85ab020b026507b8283a08a09fb 100644 (file)
@@ -142,7 +142,7 @@ struct sched_domain {
         * by attaching extra space to the end of the structure,
         * depending on how many CPUs the kernel has booted up with)
         */
-       unsigned long span[0];
+       unsigned long span[];
 };
 
 static inline struct cpumask *sched_domain_span(struct sched_domain *sd)
index 3a2ac7072dbba12c396e17c106b821f04747c219..3000c526f5526c06edadc598bead4cc5fd954f79 100644 (file)
@@ -4162,7 +4162,7 @@ struct skb_ext {
        refcount_t refcnt;
        u8 offset[SKB_EXT_NUM]; /* in chunks of 8 bytes */
        u8 chunks;              /* same */
-       char data[0] __aligned(8);
+       char data[] __aligned(8);
 };
 
 struct skb_ext *__skb_ext_alloc(void);
index fbafb353e9be586c6b87ee39088fdb87ceba33c3..bd964c31d333551871af461a0082227008c31993 100644 (file)
@@ -177,6 +177,8 @@ struct plat_stmmacenet_data {
        struct stmmac_rxq_cfg rx_queues_cfg[MTL_MAX_RX_QUEUES];
        struct stmmac_txq_cfg tx_queues_cfg[MTL_MAX_TX_QUEUES];
        void (*fix_mac_speed)(void *priv, unsigned int speed);
+       int (*serdes_powerup)(struct net_device *ndev, void *priv);
+       void (*serdes_powerdown)(struct net_device *ndev, void *priv);
        int (*init)(struct platform_device *pdev, void *priv);
        void (*exit)(struct platform_device *pdev, void *priv);
        struct mac_device_info *(*setup)(void *priv);
index ca7e108248e211208c0d2317b3b28cbd8394660f..02e7a5863d289c7492a042367daac28730597cd8 100644 (file)
@@ -71,7 +71,13 @@ struct rpc_clnt {
 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
        struct dentry           *cl_debugfs;    /* debugfs directory */
 #endif
-       struct rpc_xprt_iter    cl_xpi;
+       /* cl_work is only needed after cl_xpi is no longer used,
+        * and that are of similar size
+        */
+       union {
+               struct rpc_xprt_iter    cl_xpi;
+               struct work_struct      cl_work;
+       };
        const struct cred       *cl_cred;
 };
 
@@ -236,4 +242,9 @@ static inline int rpc_reply_expected(struct rpc_task *task)
                (task->tk_msg.rpc_proc->p_decode != NULL);
 }
 
+static inline void rpc_task_close_connection(struct rpc_task *task)
+{
+       if (task->tk_xprt)
+               xprt_force_disconnect(task->tk_xprt);
+}
 #endif /* _LINUX_SUNRPC_CLNT_H */
index 78fe2ac6dc6c5d7b3c477b42cecf04920622425c..cbcfbd0521e374254e90fea0562e29c716e62727 100644 (file)
@@ -170,6 +170,7 @@ extern bool svc_rdma_post_recvs(struct svcxprt_rdma *rdma);
 extern void svc_rdma_recv_ctxt_put(struct svcxprt_rdma *rdma,
                                   struct svc_rdma_recv_ctxt *ctxt);
 extern void svc_rdma_flush_recv_queues(struct svcxprt_rdma *rdma);
+extern void svc_rdma_release_rqst(struct svc_rqst *rqstp);
 extern int svc_rdma_recvfrom(struct svc_rqst *);
 
 /* svc_rdma_rw.c */
index b835d8dbea0e3d95ef552ba2540939ced3358cb5..e1bbf7a16b2767ab08d53f9b297d5c1c87cc992f 100644 (file)
@@ -275,7 +275,7 @@ struct swap_info_struct {
                                         */
        struct work_struct discard_work; /* discard worker */
        struct swap_cluster_list discard_clusters; /* discard clusters list */
-       struct plist_node avail_lists[0]; /*
+       struct plist_node avail_lists[]; /*
                                           * entries in swap_avail_heads, one
                                           * entry per node.
                                           * Must be last as the number of the
index 421c99c12291994ce9f023fbedbc9089c8a5690d..4f8159e90ce1783475bfe7ec4fa5e99ac42b11be 100644 (file)
@@ -78,47 +78,6 @@ struct tcp_sack_block {
 #define TCP_SACK_SEEN     (1 << 0)   /*1 = peer is SACK capable, */
 #define TCP_DSACK_SEEN    (1 << 2)   /*1 = DSACK was received from peer*/
 
-#if IS_ENABLED(CONFIG_MPTCP)
-struct mptcp_options_received {
-       u64     sndr_key;
-       u64     rcvr_key;
-       u64     data_ack;
-       u64     data_seq;
-       u32     subflow_seq;
-       u16     data_len;
-       u16     mp_capable : 1,
-               mp_join : 1,
-               dss : 1,
-               add_addr : 1,
-               rm_addr : 1,
-               family : 4,
-               echo : 1,
-               backup : 1;
-       u32     token;
-       u32     nonce;
-       u64     thmac;
-       u8      hmac[20];
-       u8      join_id;
-       u8      use_map:1,
-               dsn64:1,
-               data_fin:1,
-               use_ack:1,
-               ack64:1,
-               mpc_map:1,
-               __unused:2;
-       u8      addr_id;
-       u8      rm_id;
-       union {
-               struct in_addr  addr;
-#if IS_ENABLED(CONFIG_MPTCP_IPV6)
-               struct in6_addr addr6;
-#endif
-       };
-       u64     ahmac;
-       u16     port;
-};
-#endif
-
 struct tcp_options_received {
 /*     PAWS/RTTM data  */
        int     ts_recent_stamp;/* Time we stored ts_recent (for aging) */
@@ -136,9 +95,6 @@ struct tcp_options_received {
        u8      num_sacks;      /* Number of SACK blocks                */
        u16     user_mss;       /* mss requested by user in ioctl       */
        u16     mss_clamp;      /* Maximal mss, negotiated at connection setup */
-#if IS_ENABLED(CONFIG_MPTCP)
-       struct mptcp_options_received   mptcp;
-#endif
 };
 
 static inline void tcp_clear_options(struct tcp_options_received *rx_opt)
@@ -148,13 +104,6 @@ static inline void tcp_clear_options(struct tcp_options_received *rx_opt)
 #if IS_ENABLED(CONFIG_SMC)
        rx_opt->smc_ok = 0;
 #endif
-#if IS_ENABLED(CONFIG_MPTCP)
-       rx_opt->mptcp.mp_capable = 0;
-       rx_opt->mptcp.mp_join = 0;
-       rx_opt->mptcp.add_addr = 0;
-       rx_opt->mptcp.rm_addr = 0;
-       rx_opt->mptcp.dss = 0;
-#endif
 }
 
 /* This is the max number of SACKS that we'll generate and process. It's safe
index eb6cbdf10e5087e942ba678791469a4087e4228e..44a7f9169ac67a0b81da41792fa7a588deb4f784 100644 (file)
@@ -295,7 +295,7 @@ struct bts_header {
        u32 magic;
        u32 version;
        u8 future[24];
-       u8 actions[0];
+       u8 actions[];
 } __attribute__ ((packed));
 
 /**
@@ -305,7 +305,7 @@ struct bts_header {
 struct bts_action {
        u16 type;
        u16 size;
-       u8 data[0];
+       u8 data[];
 } __attribute__ ((packed));
 
 struct bts_action_send {
@@ -315,7 +315,7 @@ struct bts_action_send {
 struct bts_action_wait {
        u32 msec;
        u32 size;
-       u8 data[0];
+       u8 data[];
 } __attribute__ ((packed));
 
 struct bts_action_delay {
index 131ea1bad458bee37bb418d05c1504f90c2abc16..c253461b1c4e662fd5754d4c23d015acec667ad9 100644 (file)
@@ -28,7 +28,7 @@ struct tcpa_event {
        u32 event_type;
        u8 pcr_value[20];       /* SHA1 */
        u32 event_size;
-       u8 event_data[0];
+       u8 event_data[];
 };
 
 enum tcpa_event_types {
@@ -55,7 +55,7 @@ enum tcpa_event_types {
 struct tcpa_pc_event {
        u32 event_id;
        u32 event_size;
-       u8 event_data[0];
+       u8 event_data[];
 };
 
 enum tcpa_pc_event_ids {
@@ -102,7 +102,7 @@ struct tcg_pcr_event {
 
 struct tcg_event_field {
        u32 event_size;
-       u8 event[0];
+       u8 event[];
 } __packed;
 
 struct tcg_pcr_event2_head {
index 1fb11daa5c5334c6ecbbd5a77a3c0a6c152e3f84..a1fecf31162174036352198afee3260cdbab3670 100644 (file)
@@ -156,8 +156,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
  * Note, the proto and args passed in includes "__data" as the first parameter.
  * The reason for this is to handle the "void" prototype. If a tracepoint
  * has a "void" prototype, then it is invalid to declare a function
- * as "(void *, void)". The DECLARE_TRACE_NOARGS() will pass in just
- * "void *data", where as the DECLARE_TRACE() will pass in "void *data, proto".
+ * as "(void *, void)".
  */
 #define __DO_TRACE(tp, proto, args, cond, rcuidle)                     \
        do {                                                            \
@@ -373,25 +372,6 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
 # define __tracepoint_string
 #endif
 
-/*
- * The need for the DECLARE_TRACE_NOARGS() is to handle the prototype
- * (void). "void" is a special value in a function prototype and can
- * not be combined with other arguments. Since the DECLARE_TRACE()
- * macro adds a data element at the beginning of the prototype,
- * we need a way to differentiate "(void *data, proto)" from
- * "(void *data, void)". The second prototype is invalid.
- *
- * DECLARE_TRACE_NOARGS() passes "void" as the tracepoint prototype
- * and "void *__data" as the callback prototype.
- *
- * DECLARE_TRACE() passes "proto" as the tracepoint protoype and
- * "void *__data, proto" as the callback prototype.
- */
-#define DECLARE_TRACE_NOARGS(name)                                     \
-       __DECLARE_TRACE(name, void, ,                                   \
-                       cpu_online(raw_smp_processor_id()),             \
-                       void *__data, __data)
-
 #define DECLARE_TRACE(name, proto, args)                               \
        __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),              \
                        cpu_online(raw_smp_processor_id()),             \
index bd5fe0e907e8c1c219a496120d49a0fa42b8c736..a99e9b8e4e316b715d2f7b7cd28d8cf5fb4395b3 100644 (file)
@@ -66,7 +66,7 @@ struct tty_buffer {
        int read;
        int flags;
        /* Data points here */
-       unsigned long data[0];
+       unsigned long data[];
 };
 
 /* Values for .flags field of tty_buffer */
index 733acfb7ef84a8e39d75000e4a589d148d17b973..5453af87a33ee4588e287e03e3561638d03f8637 100644 (file)
@@ -164,7 +164,7 @@ struct vdpa_config_ops {
        u64 (*get_vq_state)(struct vdpa_device *vdev, u16 idx);
 
        /* Device ops */
-       u16 (*get_vq_align)(struct vdpa_device *vdev);
+       u32 (*get_vq_align)(struct vdpa_device *vdev);
        u64 (*get_features)(struct vdpa_device *vdev);
        int (*set_features)(struct vdpa_device *vdev, u64 features);
        void (*set_config_cb)(struct vdpa_device *vdev,
index 9aced11e90000c45926045e5e0c6ea2e2c35f36c..dc236577b92f0959a76a797cc3421be99925b391 100644 (file)
@@ -1,5 +1,9 @@
 /* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_VERMAGIC_H
+#define _LINUX_VERMAGIC_H
+
 #include <generated/utsrelease.h>
+#include <asm/vermagic.h>
 
 /* Simply sanity version stamp for modules. */
 #ifdef CONFIG_SMP
@@ -24,9 +28,6 @@
 #else
 #define MODULE_VERMAGIC_MODVERSIONS ""
 #endif
-#ifndef MODULE_ARCH_VERMAGIC
-#define MODULE_ARCH_VERMAGIC ""
-#endif
 #ifdef RANDSTRUCT_PLUGIN
 #include <generated/randomize_layout_hash.h>
 #define MODULE_RANDSTRUCT_PLUGIN "RANDSTRUCT_PLUGIN_" RANDSTRUCT_HASHED_SEED
@@ -41,3 +42,4 @@
        MODULE_ARCH_VERMAGIC                                            \
        MODULE_RANDSTRUCT_PLUGIN
 
+#endif /* _LINUX_VERMAGIC_H */
index 15f906e4a748f7495c36ef1ee189bd1c883c9e39..a493eac083933ff5f2b0a152f6439182646b9c00 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
 #include <linux/gfp.h>
-#include <linux/vringh.h>
 
 /**
  * virtqueue - a queue to register buffers for sending or receiving.
index 0d1fe9297ac67ad1043e6f3094aad9610a893d75..6f6ade63b04cd9af7ac329bf4c2f64499cfc7336 100644 (file)
@@ -3,6 +3,8 @@
 #define _LINUX_VIRTIO_NET_H
 
 #include <linux/if_vlan.h>
+#include <uapi/linux/tcp.h>
+#include <uapi/linux/udp.h>
 #include <uapi/linux/virtio_net.h>
 
 static inline int virtio_net_hdr_set_proto(struct sk_buff *skb,
@@ -28,17 +30,25 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
                                        bool little_endian)
 {
        unsigned int gso_type = 0;
+       unsigned int thlen = 0;
+       unsigned int ip_proto;
 
        if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
                switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
                case VIRTIO_NET_HDR_GSO_TCPV4:
                        gso_type = SKB_GSO_TCPV4;
+                       ip_proto = IPPROTO_TCP;
+                       thlen = sizeof(struct tcphdr);
                        break;
                case VIRTIO_NET_HDR_GSO_TCPV6:
                        gso_type = SKB_GSO_TCPV6;
+                       ip_proto = IPPROTO_TCP;
+                       thlen = sizeof(struct tcphdr);
                        break;
                case VIRTIO_NET_HDR_GSO_UDP:
                        gso_type = SKB_GSO_UDP;
+                       ip_proto = IPPROTO_UDP;
+                       thlen = sizeof(struct udphdr);
                        break;
                default:
                        return -EINVAL;
@@ -57,16 +67,22 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
 
                if (!skb_partial_csum_set(skb, start, off))
                        return -EINVAL;
+
+               if (skb_transport_offset(skb) + thlen > skb_headlen(skb))
+                       return -EINVAL;
        } else {
                /* gso packets without NEEDS_CSUM do not set transport_offset.
                 * probe and drop if does not match one of the above types.
                 */
                if (gso_type && skb->network_header) {
+                       struct flow_keys_basic keys;
+
                        if (!skb->protocol)
                                virtio_net_hdr_set_proto(skb, hdr);
 retry:
-                       skb_probe_transport_header(skb);
-                       if (!skb_transport_header_was_set(skb)) {
+                       if (!skb_flow_dissect_flow_keys_basic(NULL, skb, &keys,
+                                                             NULL, 0, 0, 0,
+                                                             0)) {
                                /* UFO does not specify ipv4 or 6: try both */
                                if (gso_type & SKB_GSO_UDP &&
                                    skb->protocol == htons(ETH_P_IP)) {
@@ -75,6 +91,12 @@ retry:
                                }
                                return -EINVAL;
                        }
+
+                       if (keys.control.thoff + thlen > skb_headlen(skb) ||
+                           keys.basic.ip_proto != ip_proto)
+                               return -EINVAL;
+
+                       skb_set_transport_header(skb, keys.control.thoff);
                }
        }
 
index 71c81e0dc8f28c06f134f25279b01aa5d230f982..dc636b7271791eeab5eaa2e390684c9b23ff51bb 100644 (file)
@@ -48,6 +48,7 @@ struct virtio_vsock_pkt {
        u32 len;
        u32 off;
        bool reply;
+       bool tap_delivered;
 };
 
 struct virtio_vsock_pkt_info {
index 0507a162ccd0e7ba4edf007654084effe3b5579a..a95d3cc74d79ba468a06502f8cb8acf808ab55a1 100644 (file)
@@ -137,7 +137,7 @@ extern void vunmap(const void *addr);
 
 extern int remap_vmalloc_range_partial(struct vm_area_struct *vma,
                                       unsigned long uaddr, void *kaddr,
-                                      unsigned long size);
+                                      unsigned long pgoff, unsigned long size);
 
 extern int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
                                                        unsigned long pgoff);
index bd0503ca6f8fc509aa7cc02e110e561b885b07be..9e2763d7c15912e0a77f7ca2e90e2ae836347c08 100644 (file)
 #include <linux/virtio_byteorder.h>
 #include <linux/uio.h>
 #include <linux/slab.h>
+#if IS_REACHABLE(CONFIG_VHOST_IOTLB)
 #include <linux/dma-direction.h>
 #include <linux/vhost_iotlb.h>
+#endif
 #include <asm/barrier.h>
 
 /* virtio_ring with information needed for host access. */
@@ -254,6 +256,8 @@ static inline __virtio64 cpu_to_vringh64(const struct vringh *vrh, u64 val)
        return __cpu_to_virtio64(vringh_is_little_endian(vrh), val);
 }
 
+#if IS_REACHABLE(CONFIG_VHOST_IOTLB)
+
 void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb);
 
 int vringh_init_iotlb(struct vringh *vrh, u64 features,
@@ -284,4 +288,6 @@ void vringh_notify_disable_iotlb(struct vringh *vrh);
 
 int vringh_need_notify_iotlb(struct vringh *vrh);
 
+#endif /* CONFIG_VHOST_IOTLB */
+
 #endif /* _LINUX_VRINGH_H */
index 4cf6e11f4a3cb5537f3c1650c234c47457a5a782..47eaa34f87619c11b150590f6bbb1f252d806eea 100644 (file)
@@ -73,7 +73,7 @@ struct simple_xattr {
        struct list_head list;
        char *name;
        size_t size;
-       char value[0];
+       char value[];
 };
 
 /*
index c78bd4ff9e3378d4158e389ce3fb4c49acb296b2..70e48f66dac8ef5d3f608de65653af2f86728ede 100644 (file)
@@ -905,6 +905,8 @@ struct survey_info {
  *     protocol frames.
  * @control_port_over_nl80211: TRUE if userspace expects to exchange control
  *     port frames over NL80211 instead of the network interface.
+ * @control_port_no_preauth: disables pre-auth rx over the nl80211 control
+ *     port for mac80211
  * @wep_keys: static WEP keys, if not NULL points to an array of
  *     CFG80211_MAX_WEP_KEYS WEP keys
  * @wep_tx_key: key index (0..3) of the default TX static WEP key
@@ -1222,6 +1224,7 @@ struct sta_txpwr {
  * @he_capa: HE capabilities of station
  * @he_capa_len: the length of the HE capabilities
  * @airtime_weight: airtime scheduler weight for this station
+ * @txpwr: transmit power for an associated station
  */
 struct station_parameters {
        const u8 *supported_rates;
@@ -4666,6 +4669,9 @@ struct wiphy_iftype_akm_suites {
  * @txq_memory_limit: configuration internal TX queue memory limit
  * @txq_quantum: configuration of internal TX queue scheduler quantum
  *
+ * @tx_queue_len: allow setting transmit queue len for drivers not using
+ *     wake_tx_queue
+ *
  * @support_mbssid: can HW support association with nontransmitted AP
  * @support_only_he_mbssid: don't parse MBSSID elements if it is not
  *     HE AP, in order to avoid compatibility issues.
@@ -4681,6 +4687,10 @@ struct wiphy_iftype_akm_suites {
  *     supported by the driver for each peer
  * @tid_config_support.max_retry: maximum supported retry count for
  *     long/short retry configuration
+ *
+ * @max_data_retry_count: maximum supported per TID retry count for
+ *     configuration through the %NL80211_TID_CONFIG_ATTR_RETRY_SHORT and
+ *     %NL80211_TID_CONFIG_ATTR_RETRY_LONG attributes
  */
 struct wiphy {
        /* assign these fields before you register the wiphy */
index 3619c6acf60fa563f7915f6a03647b975eaa1ac8..efc8350b42fb30f9146e4f5df235214b2d4c84d3 100644 (file)
@@ -166,15 +166,18 @@ enum flow_action_mangle_base {
 enum flow_action_hw_stats_bit {
        FLOW_ACTION_HW_STATS_IMMEDIATE_BIT,
        FLOW_ACTION_HW_STATS_DELAYED_BIT,
+       FLOW_ACTION_HW_STATS_DISABLED_BIT,
 };
 
 enum flow_action_hw_stats {
-       FLOW_ACTION_HW_STATS_DISABLED = 0,
+       FLOW_ACTION_HW_STATS_DONT_CARE = 0,
        FLOW_ACTION_HW_STATS_IMMEDIATE =
                BIT(FLOW_ACTION_HW_STATS_IMMEDIATE_BIT),
        FLOW_ACTION_HW_STATS_DELAYED = BIT(FLOW_ACTION_HW_STATS_DELAYED_BIT),
        FLOW_ACTION_HW_STATS_ANY = FLOW_ACTION_HW_STATS_IMMEDIATE |
                                   FLOW_ACTION_HW_STATS_DELAYED,
+       FLOW_ACTION_HW_STATS_DISABLED =
+               BIT(FLOW_ACTION_HW_STATS_DISABLED_BIT),
 };
 
 typedef void (*action_destr)(void *priv);
@@ -325,7 +328,11 @@ __flow_action_hw_stats_check(const struct flow_action *action,
                return true;
        if (!flow_action_mixed_hw_stats_check(action, extack))
                return false;
+
        action_entry = flow_action_first_entry_get(action);
+       if (action_entry->hw_stats == FLOW_ACTION_HW_STATS_DONT_CARE)
+               return true;
+
        if (!check_allow_bit &&
            action_entry->hw_stats != FLOW_ACTION_HW_STATS_ANY) {
                NL_SET_ERR_MSG_MOD(extack, "Driver supports only default HW stats type \"any\"");
index c8e2bebd8d934a5560927509ecb81e5536e2f8e8..0f0d1efe06ddcd1bcd67000bde1d7b88f0c74153 100644 (file)
@@ -99,6 +99,20 @@ static inline int IP_ECN_set_ce(struct iphdr *iph)
        return 1;
 }
 
+static inline int IP_ECN_set_ect1(struct iphdr *iph)
+{
+       u32 check = (__force u32)iph->check;
+
+       if ((iph->tos & INET_ECN_MASK) != INET_ECN_ECT_0)
+               return 0;
+
+       check += (__force u16)htons(0x100);
+
+       iph->check = (__force __sum16)(check + (check>=0xFFFF));
+       iph->tos ^= INET_ECN_MASK;
+       return 1;
+}
+
 static inline void IP_ECN_clear(struct iphdr *iph)
 {
        iph->tos &= ~INET_ECN_MASK;
@@ -134,6 +148,22 @@ static inline int IP6_ECN_set_ce(struct sk_buff *skb, struct ipv6hdr *iph)
        return 1;
 }
 
+static inline int IP6_ECN_set_ect1(struct sk_buff *skb, struct ipv6hdr *iph)
+{
+       __be32 from, to;
+
+       if ((ipv6_get_dsfield(iph) & INET_ECN_MASK) != INET_ECN_ECT_0)
+               return 0;
+
+       from = *(__be32 *)iph;
+       to = from ^ htonl(INET_ECN_MASK << 20);
+       *(__be32 *)iph = to;
+       if (skb->ip_summed == CHECKSUM_COMPLETE)
+               skb->csum = csum_add(csum_sub(skb->csum, (__force __wsum)from),
+                                    (__force __wsum)to);
+       return 1;
+}
+
 static inline void ipv6_copy_dscp(unsigned int dscp, struct ipv6hdr *inner)
 {
        dscp &= ~INET_ECN_MASK;
@@ -159,6 +189,25 @@ static inline int INET_ECN_set_ce(struct sk_buff *skb)
        return 0;
 }
 
+static inline int INET_ECN_set_ect1(struct sk_buff *skb)
+{
+       switch (skb->protocol) {
+       case cpu_to_be16(ETH_P_IP):
+               if (skb_network_header(skb) + sizeof(struct iphdr) <=
+                   skb_tail_pointer(skb))
+                       return IP_ECN_set_ect1(ip_hdr(skb));
+               break;
+
+       case cpu_to_be16(ETH_P_IPV6):
+               if (skb_network_header(skb) + sizeof(struct ipv6hdr) <=
+                   skb_tail_pointer(skb))
+                       return IP6_ECN_set_ect1(skb, ipv6_hdr(skb));
+               break;
+       }
+
+       return 0;
+}
+
 /*
  * RFC 6040 4.2
  *  To decapsulate the inner header at the tunnel egress, a compliant
@@ -208,8 +257,12 @@ static inline int INET_ECN_decapsulate(struct sk_buff *skb,
        int rc;
 
        rc = __INET_ECN_decapsulate(outer, inner, &set_ce);
-       if (!rc && set_ce)
-               INET_ECN_set_ce(skb);
+       if (!rc) {
+               if (set_ce)
+                       INET_ECN_set_ce(skb);
+               else if ((outer & INET_ECN_MASK) == INET_ECN_ECT_1)
+                       INET_ECN_set_ect1(skb);
+       }
 
        return rc;
 }
index 80262d2980f5d8e24b93f573ce9858b126031ea4..1d98828c6649bfa137f86bea4c827d9e3be857e8 100644 (file)
@@ -203,6 +203,7 @@ struct fib6_info {
 struct rt6_info {
        struct dst_entry                dst;
        struct fib6_info __rcu          *from;
+       int                             sernum;
 
        struct rt6key                   rt6i_dst;
        struct rt6key                   rt6i_src;
@@ -291,6 +292,9 @@ static inline u32 rt6_get_cookie(const struct rt6_info *rt)
        struct fib6_info *from;
        u32 cookie = 0;
 
+       if (rt->sernum)
+               return rt->sernum;
+
        rcu_read_lock();
 
        from = rcu_dereference(rt->from);
index f7543c095b33d854bd70451698c44fcf9a69be98..9947eb1e9eb67ebacd567616c29c767df407524b 100644 (file)
@@ -254,6 +254,7 @@ static inline bool ipv6_anycast_destination(const struct dst_entry *dst,
 
        return rt->rt6i_flags & RTF_ANYCAST ||
                (rt->rt6i_dst.plen < 127 &&
+                !(rt->rt6i_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) &&
                 ipv6_addr_equal(&rt->rt6i_dst.addr, daddr));
 }
 
index b6b4de0e4b5ede87ae1ac8c85be5dc034312ac04..97fec4d310acfd82e0bbf91b66ea11b9a5d1d4ac 100644 (file)
@@ -6007,7 +6007,9 @@ enum rate_control_capabilities {
 struct rate_control_ops {
        unsigned long capa;
        const char *name;
-       void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir);
+       void *(*alloc)(struct ieee80211_hw *hw);
+       void (*add_debugfs)(struct ieee80211_hw *hw, void *priv,
+                           struct dentry *debugfsdir);
        void (*free)(void *priv);
 
        void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp);
index 0e7c5471010bda14c7a17f096036cdf425b63fc3..3bce2019e4da97bde5581e0da049abd64c8ca739 100644 (file)
@@ -68,11 +68,8 @@ static inline bool rsk_is_mptcp(const struct request_sock *req)
        return tcp_rsk(req)->is_mptcp;
 }
 
-void mptcp_parse_option(const struct sk_buff *skb, const unsigned char *ptr,
-                       int opsize, struct tcp_options_received *opt_rx);
 bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
                       unsigned int *size, struct mptcp_out_options *opts);
-void mptcp_rcv_synsent(struct sock *sk);
 bool mptcp_synack_options(const struct request_sock *req, unsigned int *size,
                          struct mptcp_out_options *opts);
 bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
index 7d107113f988a6a169b06ee2622d89bdacf2580a..9205a76d967a03e4162bad03f2f4e53d6e976506 100644 (file)
@@ -41,7 +41,7 @@ enum {
        ND_OPT_DNSSL = 31,              /* RFC6106 */
        ND_OPT_6CO = 34,                /* RFC6775 */
        ND_OPT_CAPTIVE_PORTAL = 37,     /* RFC7710 */
-       ND_OPT_PREF64 = 38,             /* RFC-ietf-6man-ra-pref64-09 */
+       ND_OPT_PREF64 = 38,             /* RFC8781 */
        __ND_OPT_MAX
 };
 
index ab96fb59131c148d5595350c9fad3e7594b28a68..8e001e049497f45e0b12807e24e0f330319bfb4a 100644 (file)
@@ -437,6 +437,13 @@ static inline int rt_genid_ipv4(const struct net *net)
        return atomic_read(&net->ipv4.rt_genid);
 }
 
+#if IS_ENABLED(CONFIG_IPV6)
+static inline int rt_genid_ipv6(const struct net *net)
+{
+       return atomic_read(&net->ipv6.fib6_sernum);
+}
+#endif
+
 static inline void rt_genid_bump_ipv4(struct net *net)
 {
        atomic_inc(&net->ipv4.rt_genid);
index 6eb627b3c99b6f8cbd10a2af131489a26e83e579..4ff7c81e6717b6f12eeca46d6e0d7df110958dfe 100644 (file)
@@ -901,7 +901,7 @@ static inline void nft_set_elem_update_expr(const struct nft_set_ext *ext,
 {
        struct nft_expr *expr;
 
-       if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR)) {
+       if (__nft_set_ext_exists(ext, NFT_SET_EXT_EXPR)) {
                expr = nft_set_ext_expr(ext);
                expr->ops->eval(expr, regs, pkt);
        }
index 25d2ec4c8f00495cb8b25b0e7a24d1f808e50c90..8428aa6142655666715743e60bc74855f9f8d008 100644 (file)
@@ -407,6 +407,7 @@ struct tcf_block {
        struct mutex lock;
        struct list_head chain_list;
        u32 index; /* block index for shared blocks */
+       u32 classid; /* which class this block belongs to */
        refcount_t refcnt;
        struct net *net;
        struct Qdisc *q;
index 6d84784d33fa007d91836dc9c51532a23048cf08..3e8c6d4b4b59ff00a0cb8fbcbb256f55b5ac895a 100644 (file)
@@ -2553,9 +2553,9 @@ sk_is_refcounted(struct sock *sk)
 }
 
 /**
- * skb_steal_sock
- * @skb to steal the socket from
- * @refcounted is set to true if the socket is reference-counted
+ * skb_steal_sock - steal a socket from an sk_buff
+ * @skb: sk_buff to steal the socket from
+ * @refcounted: is set to true if the socket is reference-counted
  */
 static inline struct sock *
 skb_steal_sock(struct sk_buff *skb, bool *refcounted)
index 5fa9eacd965a4abd6a4dd5262fa0d439aa9fe64e..dcf9a72eeaa6912202e8a1ca6cf800f7401bf517 100644 (file)
@@ -51,7 +51,7 @@ extern struct inet_hashinfo tcp_hashinfo;
 extern struct percpu_counter tcp_orphan_count;
 void tcp_time_wait(struct sock *sk, int state, int timeo);
 
-#define MAX_TCP_HEADER (128 + MAX_HEADER)
+#define MAX_TCP_HEADER L1_CACHE_ALIGN(128 + MAX_HEADER)
 #define MAX_TCP_OPTION_SPACE 40
 #define TCP_MIN_SND_MSS                48
 #define TCP_MIN_GSO_SIZE       (TCP_MIN_SND_MSS - MAX_TCP_OPTION_SPACE)
index ebffcb36a7e342a437d4641aa00e5e15673c1564..efc8b613d486dc2bf460b3f0437d5f06a07dbf09 100644 (file)
@@ -476,6 +476,8 @@ struct ocelot_port {
 
        void __iomem                    *regs;
 
+       bool                            vlan_aware;
+
        /* Ingress default VLAN (pvid) */
        u16                             pvid;
 
@@ -500,6 +502,7 @@ struct ocelot {
        unsigned int                    num_stats;
 
        int                             shared_queue_sz;
+       int                             num_mact_rows;
 
        struct net_device               *hw_bridge_dev;
        u16                             bridge_mask;
@@ -610,7 +613,7 @@ int ocelot_port_bridge_leave(struct ocelot *ocelot, int port,
 int ocelot_fdb_dump(struct ocelot *ocelot, int port,
                    dsa_fdb_dump_cb_t *cb, void *data);
 int ocelot_fdb_add(struct ocelot *ocelot, int port,
-                  const unsigned char *addr, u16 vid, bool vlan_aware);
+                  const unsigned char *addr, u16 vid);
 int ocelot_fdb_del(struct ocelot *ocelot, int port,
                   const unsigned char *addr, u16 vid);
 int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid,
index 0dd52b0a5c1bf3ebe9364ecc4670e5a6ad212d7b..361cb64246f74087165f16493e942eaf690671c9 100644 (file)
@@ -168,7 +168,6 @@ int tegra_io_pad_power_disable(enum tegra_io_pad id);
 int tegra_io_rail_power_on(unsigned int id);
 int tegra_io_rail_power_off(unsigned int id);
 
-enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
 void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode);
 void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode);
 
@@ -220,11 +219,6 @@ static inline int tegra_io_rail_power_off(unsigned int id)
        return -ENOSYS;
 }
 
-static inline enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
-{
-       return TEGRA_SUSPEND_NONE;
-}
-
 static inline void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode)
 {
 }
@@ -235,4 +229,13 @@ static inline void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode)
 
 #endif /* CONFIG_SOC_TEGRA_PMC */
 
+#if defined(CONFIG_SOC_TEGRA_PMC) && defined(CONFIG_PM_SLEEP)
+enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
+#else
+static inline enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
+{
+       return TEGRA_SUSPEND_NONE;
+}
+#endif
+
 #endif /* __SOC_TEGRA_PMC_H__ */
index 3ee8036f5436d31912bb60b8ed68821b468ad338..225154a4f2ed01f262d81c8a70d762d4bddf1458 100644 (file)
@@ -494,6 +494,11 @@ void snd_hda_update_power_acct(struct hda_codec *codec);
 static inline void snd_hda_set_power_save(struct hda_bus *bus, int delay) {}
 #endif
 
+static inline bool hda_codec_need_resume(struct hda_codec *codec)
+{
+       return !codec->relaxed_resume && codec->jacktbl.used;
+}
+
 #ifdef CONFIG_SND_HDA_PATCH_LOADER
 /*
  * patch firmware
index d4825b82c7a3b08f5e880501a1a771d2406ca7f5..b33abe93b905953f5d0faa7bebb678bd4d36c587 100644 (file)
@@ -351,7 +351,6 @@ struct snd_soc_dai {
 
        /* bit field */
        unsigned int probed:1;
-       unsigned int started[SNDRV_PCM_STREAM_LAST + 1];
 };
 
 static inline struct snd_soc_pcm_stream *
index 13458e4fbb132ed3a0fef16af7cd6317973e54fa..946f88a6c63d119ff71e5916615320d8dac2b273 100644 (file)
@@ -790,6 +790,9 @@ struct snd_soc_dai_link {
        const struct snd_soc_pcm_stream *params;
        unsigned int num_params;
 
+       struct snd_soc_dapm_widget *playback_widget;
+       struct snd_soc_dapm_widget *capture_widget;
+
        unsigned int dai_fmt;           /* format to set on init */
 
        enum snd_soc_dpcm_trigger trigger[2]; /* trigger type for DPCM */
index 1897822a9150659127631d4220702bd639beef5f..26d871f96e9407f9a0b96a58bdf317593ddeb6ca 100644 (file)
@@ -24,7 +24,7 @@
  *
  * @pid: Put 0 for global total, while positive pid for process total.
  *
- * @size: Virtual size of the allocation in bytes.
+ * @size: Size of the allocation in bytes.
  *
  */
 TRACE_EVENT(gpu_mem_total,
index 7ecaa65b7106eb67a4400d16fd86f5cc620d7a8c..c2f580fd371b11e117be68238c8530bd88a84d1f 100644 (file)
@@ -130,7 +130,7 @@ DEFINE_EVENT(iocg_inuse_update, iocost_inuse_reset,
 
 TRACE_EVENT(iocost_ioc_vrate_adj,
 
-       TP_PROTO(struct ioc *ioc, u64 new_vrate, u32 (*missed_ppm)[2],
+       TP_PROTO(struct ioc *ioc, u64 new_vrate, u32 *missed_ppm,
                u32 rq_wait_pct, int nr_lagging, int nr_shortages,
                int nr_surpluses),
 
@@ -155,8 +155,8 @@ TRACE_EVENT(iocost_ioc_vrate_adj,
                __entry->old_vrate = atomic64_read(&ioc->vtime_rate);;
                __entry->new_vrate = new_vrate;
                __entry->busy_level = ioc->busy_level;
-               __entry->read_missed_ppm = (*missed_ppm)[READ];
-               __entry->write_missed_ppm = (*missed_ppm)[WRITE];
+               __entry->read_missed_ppm = missed_ppm[READ];
+               __entry->write_missed_ppm = missed_ppm[WRITE];
                __entry->rq_wait_pct = rq_wait_pct;
                __entry->nr_lagging = nr_lagging;
                __entry->nr_shortages = nr_shortages;
index 051f26fedc4db847214028eed03d54759f1e1413..132c3c778a43260745a75f3dc36e4eb3c706b61f 100644 (file)
@@ -692,11 +692,10 @@ TRACE_EVENT(xprtrdma_prepsend_failed,
 
 TRACE_EVENT(xprtrdma_post_send,
        TP_PROTO(
-               const struct rpcrdma_req *req,
-               int status
+               const struct rpcrdma_req *req
        ),
 
-       TP_ARGS(req, status),
+       TP_ARGS(req),
 
        TP_STRUCT__entry(
                __field(const void *, req)
@@ -705,7 +704,6 @@ TRACE_EVENT(xprtrdma_post_send,
                __field(unsigned int, client_id)
                __field(int, num_sge)
                __field(int, signaled)
-               __field(int, status)
        ),
 
        TP_fast_assign(
@@ -718,15 +716,13 @@ TRACE_EVENT(xprtrdma_post_send,
                __entry->sc = req->rl_sendctx;
                __entry->num_sge = req->rl_wr.num_sge;
                __entry->signaled = req->rl_wr.send_flags & IB_SEND_SIGNALED;
-               __entry->status = status;
        ),
 
-       TP_printk("task:%u@%u req=%p sc=%p (%d SGE%s) %sstatus=%d",
+       TP_printk("task:%u@%u req=%p sc=%p (%d SGE%s) %s",
                __entry->task_id, __entry->client_id,
                __entry->req, __entry->sc, __entry->num_sge,
                (__entry->num_sge == 1 ? "" : "s"),
-               (__entry->signaled ? "signaled " : ""),
-               __entry->status
+               (__entry->signaled ? "signaled" : "")
        )
 );
 
@@ -1695,17 +1691,15 @@ DECLARE_EVENT_CLASS(svcrdma_sendcomp_event,
 
 TRACE_EVENT(svcrdma_post_send,
        TP_PROTO(
-               const struct ib_send_wr *wr,
-               int status
+               const struct ib_send_wr *wr
        ),
 
-       TP_ARGS(wr, status),
+       TP_ARGS(wr),
 
        TP_STRUCT__entry(
                __field(const void *, cqe)
                __field(unsigned int, num_sge)
                __field(u32, inv_rkey)
-               __field(int, status)
        ),
 
        TP_fast_assign(
@@ -1713,12 +1707,11 @@ TRACE_EVENT(svcrdma_post_send,
                __entry->num_sge = wr->num_sge;
                __entry->inv_rkey = (wr->opcode == IB_WR_SEND_WITH_INV) ?
                                        wr->ex.invalidate_rkey : 0;
-               __entry->status = status;
        ),
 
-       TP_printk("cqe=%p num_sge=%u inv_rkey=0x%08x status=%d",
+       TP_printk("cqe=%p num_sge=%u inv_rkey=0x%08x",
                __entry->cqe, __entry->num_sge,
-               __entry->inv_rkey, __entry->status
+               __entry->inv_rkey
        )
 );
 
@@ -1783,26 +1776,23 @@ TRACE_EVENT(svcrdma_wc_receive,
 TRACE_EVENT(svcrdma_post_rw,
        TP_PROTO(
                const void *cqe,
-               int sqecount,
-               int status
+               int sqecount
        ),
 
-       TP_ARGS(cqe, sqecount, status),
+       TP_ARGS(cqe, sqecount),
 
        TP_STRUCT__entry(
                __field(const void *, cqe)
                __field(int, sqecount)
-               __field(int, status)
        ),
 
        TP_fast_assign(
                __entry->cqe = cqe;
                __entry->sqecount = sqecount;
-               __entry->status = status;
        ),
 
-       TP_printk("cqe=%p sqecount=%d status=%d",
-               __entry->cqe, __entry->sqecount, __entry->status
+       TP_printk("cqe=%p sqecount=%d",
+               __entry->cqe, __entry->sqecount
        )
 );
 
@@ -1870,6 +1860,34 @@ DECLARE_EVENT_CLASS(svcrdma_sendqueue_event,
 DEFINE_SQ_EVENT(full);
 DEFINE_SQ_EVENT(retry);
 
+TRACE_EVENT(svcrdma_sq_post_err,
+       TP_PROTO(
+               const struct svcxprt_rdma *rdma,
+               int status
+       ),
+
+       TP_ARGS(rdma, status),
+
+       TP_STRUCT__entry(
+               __field(int, avail)
+               __field(int, depth)
+               __field(int, status)
+               __string(addr, rdma->sc_xprt.xpt_remotebuf)
+       ),
+
+       TP_fast_assign(
+               __entry->avail = atomic_read(&rdma->sc_sq_avail);
+               __entry->depth = rdma->sc_sq_depth;
+               __entry->status = status;
+               __assign_str(addr, rdma->sc_xprt.xpt_remotebuf);
+       ),
+
+       TP_printk("addr=%s sc_sq_avail=%d/%d status=%d",
+               __get_str(addr), __entry->avail, __entry->depth,
+               __entry->status
+       )
+);
+
 #endif /* _TRACE_RPCRDMA_H */
 
 #include <trace/define_trace.h>
index 37342a13c9cb9372f849f2e3d3d5c75bf7c7eb6b..9c66e59d859cb3559d32f0e87d75bf498c916b2c 100644 (file)
@@ -33,7 +33,7 @@ TRACE_EVENT(wbt_stat,
        ),
 
        TP_fast_assign(
-               strlcpy(__entry->name, dev_name(bdi->dev),
+               strlcpy(__entry->name, bdi_dev_name(bdi),
                        ARRAY_SIZE(__entry->name));
                __entry->rmean          = stat[0].mean;
                __entry->rmin           = stat[0].min;
@@ -46,7 +46,7 @@ TRACE_EVENT(wbt_stat,
        ),
 
        TP_printk("%s: rmean=%llu, rmin=%llu, rmax=%llu, rsamples=%llu, "
-                 "wmean=%llu, wmin=%llu, wmax=%llu, wsamples=%llu\n",
+                 "wmean=%llu, wmin=%llu, wmax=%llu, wsamples=%llu",
                  __entry->name, __entry->rmean, __entry->rmin, __entry->rmax,
                  __entry->rnr_samples, __entry->wmean, __entry->wmin,
                  __entry->wmax, __entry->wnr_samples)
@@ -68,12 +68,12 @@ TRACE_EVENT(wbt_lat,
        ),
 
        TP_fast_assign(
-               strlcpy(__entry->name, dev_name(bdi->dev),
+               strlcpy(__entry->name, bdi_dev_name(bdi),
                        ARRAY_SIZE(__entry->name));
                __entry->lat = div_u64(lat, 1000);
        ),
 
-       TP_printk("%s: latency %lluus\n", __entry->name,
+       TP_printk("%s: latency %lluus", __entry->name,
                        (unsigned long long) __entry->lat)
 );
 
@@ -105,7 +105,7 @@ TRACE_EVENT(wbt_step,
        ),
 
        TP_fast_assign(
-               strlcpy(__entry->name, dev_name(bdi->dev),
+               strlcpy(__entry->name, bdi_dev_name(bdi),
                        ARRAY_SIZE(__entry->name));
                __entry->msg    = msg;
                __entry->step   = step;
@@ -115,7 +115,7 @@ TRACE_EVENT(wbt_step,
                __entry->max    = max;
        ),
 
-       TP_printk("%s: %s: step=%d, window=%luus, background=%u, normal=%u, max=%u\n",
+       TP_printk("%s: %s: step=%d, window=%luus, background=%u, normal=%u, max=%u",
                  __entry->name, __entry->msg, __entry->step, __entry->window,
                  __entry->bg, __entry->normal, __entry->max)
 );
@@ -141,14 +141,14 @@ TRACE_EVENT(wbt_timer,
        ),
 
        TP_fast_assign(
-               strlcpy(__entry->name, dev_name(bdi->dev),
+               strlcpy(__entry->name, bdi_dev_name(bdi),
                        ARRAY_SIZE(__entry->name));
                __entry->status         = status;
                __entry->step           = step;
                __entry->inflight       = inflight;
        ),
 
-       TP_printk("%s: status=%u, step=%d, inflight=%u\n", __entry->name,
+       TP_printk("%s: status=%u, step=%d, inflight=%u", __entry->name,
                  __entry->status, __entry->step, __entry->inflight)
 );
 
index d94def25e4dc94098648cf9a2568f75f0e2865b3..85a33bea76f1a776584ca36927e2481d88052daa 100644 (file)
@@ -36,7 +36,6 @@
        EM( WB_REASON_SYNC,                     "sync")                 \
        EM( WB_REASON_PERIODIC,                 "periodic")             \
        EM( WB_REASON_LAPTOP_TIMER,             "laptop_timer")         \
-       EM( WB_REASON_FREE_MORE_MEM,            "free_more_memory")     \
        EM( WB_REASON_FS_FREE_SPACE,            "fs_free_space")        \
        EMe(WB_REASON_FORKER_THREAD,            "forker_thread")
 
index 65f69723cbdc1cce661115352b098de49381783c..d28b4ce744d59579a8ef5e9e004a9210c3bfdab6 100644 (file)
@@ -346,6 +346,10 @@ struct drm_amdgpu_gem_userptr {
 #define AMDGPU_TILING_DCC_PITCH_MAX_MASK               0x3FFF
 #define AMDGPU_TILING_DCC_INDEPENDENT_64B_SHIFT                43
 #define AMDGPU_TILING_DCC_INDEPENDENT_64B_MASK         0x1
+#define AMDGPU_TILING_DCC_INDEPENDENT_128B_SHIFT       44
+#define AMDGPU_TILING_DCC_INDEPENDENT_128B_MASK                0x1
+#define AMDGPU_TILING_SCANOUT_SHIFT                    63
+#define AMDGPU_TILING_SCANOUT_MASK                     0x1
 
 /* Set/Get helpers for tiling flags. */
 #define AMDGPU_TILING_SET(field, value) \
index 2e29a671d67eb96a3139c893158aa0fc69466213..f9b7fdd951e487e8075cbebfb7a587ecb7df3334 100644 (file)
@@ -73,7 +73,7 @@ struct bpf_insn {
 /* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */
 struct bpf_lpm_trie_key {
        __u32   prefixlen;      /* up to 32 for AF_INET, 128 for AF_INET6 */
-       __u8    data[]; /* Arbitrary size */
+       __u8    data[0];        /* Arbitrary size */
 };
 
 struct bpf_cgroup_storage_key {
@@ -1642,7 +1642,7 @@ union bpf_attr {
  *             ifindex, but doesn't require a map to do so.
  *     Return
  *             **XDP_REDIRECT** on success, or the value of the two lower bits
- *             of the **flags* argument on error.
+ *             of the *flags* argument on error.
  *
  * int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags)
  *     Description
index 8134924cfc1746afe0db2b3f465874a5d5532501..e6b6cb0f8bc6a9e56ccd27c14f89202ae5cd3e5d 100644 (file)
@@ -36,12 +36,10 @@ struct btrfs_ioctl_vol_args {
 #define BTRFS_DEVICE_PATH_NAME_MAX     1024
 #define BTRFS_SUBVOL_NAME_MAX          4039
 
-/*
- * Deprecated since 5.7:
- *
- * BTRFS_SUBVOL_CREATE_ASYNC   (1ULL << 0)
- */
-
+#ifndef __KERNEL__
+/* Deprecated since 5.7 */
+# define BTRFS_SUBVOL_CREATE_ASYNC     (1ULL << 0)
+#endif
 #define BTRFS_SUBVOL_RDONLY            (1ULL << 1)
 #define BTRFS_SUBVOL_QGROUP_INHERIT    (1ULL << 2)
 
index dbc7092e04b5a46afa54a80b45e227d5a20dfc05..7f30393b92c3b4f26486964997f91ac8bca5ec4e 100644 (file)
@@ -39,6 +39,12 @@ struct dma_buf_sync {
 
 #define DMA_BUF_BASE           'b'
 #define DMA_BUF_IOCTL_SYNC     _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync)
+
+/* 32/64bitness of this uapi was botched in android, there's no difference
+ * between them in actual uapi, they're just different numbers.
+ */
 #define DMA_BUF_SET_NAME       _IOW(DMA_BUF_BASE, 1, const char *)
+#define DMA_BUF_SET_NAME_A     _IOW(DMA_BUF_BASE, 1, u32)
+#define DMA_BUF_SET_NAME_B     _IOW(DMA_BUF_BASE, 1, u64)
 
 #endif
index 991b2b7ada7a3cd88b4b44723e0b5757e4f3c4eb..8f24404ad04f14516af24523f32b9d07b5346c98 100644 (file)
@@ -119,8 +119,8 @@ enum hv_fcopy_op {
 
 struct hv_fcopy_hdr {
        __u32 operation;
-       uuid_le service_id0; /* currently unused */
-       uuid_le service_id1; /* currently unused */
+       __u8 service_id0[16]; /* currently unused */
+       __u8 service_id1[16]; /* currently unused */
 } __attribute__((packed));
 
 #define OVER_WRITE     0x1
index b122cfac71288c35e8c18c60744a7ff54d5c8b90..683878036d76d7ccdd6fe7a6e907a7977a40067b 100644 (file)
@@ -60,7 +60,7 @@ struct arc_rfc1201 {
        __u8  proto;            /* protocol ID field - varies           */
        __u8  split_flag;       /* for use with split packets           */
        __be16   sequence;      /* sequence number                      */
-       __u8  payload[];        /* space remaining in packet (504 bytes)*/
+       __u8  payload[0];       /* space remaining in packet (504 bytes)*/
 };
 #define RFC1201_HDR_SIZE 4
 
@@ -69,7 +69,7 @@ struct arc_rfc1201 {
  */
 struct arc_rfc1051 {
        __u8 proto;             /* ARC_P_RFC1051_ARP/RFC1051_IP */
-       __u8 payload[]; /* 507 bytes                    */
+       __u8 payload[0];        /* 507 bytes                    */
 };
 #define RFC1051_HDR_SIZE 1
 
@@ -80,7 +80,7 @@ struct arc_rfc1051 {
 struct arc_eth_encap {
        __u8 proto;             /* Always ARC_P_ETHER                   */
        struct ethhdr eth;      /* standard ethernet header (yuck!)     */
-       __u8 payload[]; /* 493 bytes                            */
+       __u8 payload[0];        /* 493 bytes                            */
 };
 #define ETH_ENCAP_HDR_SIZE 14
 
index 98e29e7f54ace2f7ca13b1dfd5c337976b2192d9..00c08120f3ba60c2719458fd8903dd953744a1df 100644 (file)
@@ -57,7 +57,7 @@ struct mmc_ioc_cmd {
  */
 struct mmc_ioc_multi_cmd {
        __u64 num_of_cmds;
-       struct mmc_ioc_cmd cmds[];
+       struct mmc_ioc_cmd cmds[0];
 };
 
 #define MMC_IOC_CMD _IOWR(MMC_BLOCK_MAJOR, 0, struct mmc_ioc_cmd)
index 67e31f3291904199f12e48a4a6f2e0925cc33d81..66048cc5d7b361da368d006688c614df440ea51f 100644 (file)
@@ -29,12 +29,12 @@ struct net_dm_config_entry {
 
 struct net_dm_config_msg {
        __u32 entries;
-       struct net_dm_config_entry options[];
+       struct net_dm_config_entry options[0];
 };
 
 struct net_dm_alert_msg {
        __u32 entries;
-       struct net_dm_drop_point points[];
+       struct net_dm_drop_point points[0];
 };
 
 struct net_dm_user_msg {
index 30f2a87270dc5622cf616084d542cdc765193a44..4565456c0ef447e44e59791b23be2e702b828054 100644 (file)
@@ -276,6 +276,7 @@ enum nft_rule_compat_attributes {
  * @NFT_SET_TIMEOUT: set uses timeouts
  * @NFT_SET_EVAL: set can be updated from the evaluation path
  * @NFT_SET_OBJECT: set contains stateful objects
+ * @NFT_SET_CONCAT: set contains a concatenation
  */
 enum nft_set_flags {
        NFT_SET_ANONYMOUS               = 0x1,
@@ -285,6 +286,7 @@ enum nft_set_flags {
        NFT_SET_TIMEOUT                 = 0x10,
        NFT_SET_EVAL                    = 0x20,
        NFT_SET_OBJECT                  = 0x40,
+       NFT_SET_CONCAT                  = 0x80,
 };
 
 /**
index 434e6506abaa4b24dab815e8dbfeea6efecee4fd..49ddcdc61c09499909c00c0bd2f5cd91b14c0fed 100644 (file)
@@ -48,6 +48,7 @@ struct idletimer_tg_info_v1 {
 
        char label[MAX_IDLETIMER_LABEL_SIZE];
 
+       __u8 send_nl_msg;   /* unused: for compatibility with Android */
        __u8 timer_type;
 
        /* for kernel module internal use only */
index 73b26a280c4fd7e3db4bfde98b4daee70d699a7c..9acf757bc1f79328c8693b1edac37d1b36b8d225 100644 (file)
@@ -40,7 +40,7 @@ struct ebt_mac_wormhash_tuple {
 struct ebt_mac_wormhash {
        int table[257];
        int poolsize;
-       struct ebt_mac_wormhash_tuple pool[];
+       struct ebt_mac_wormhash_tuple pool[0];
 };
 
 #define ebt_mac_wormhash_size(x) ((x) ? sizeof(struct ebt_mac_wormhash) \
index 19974392d3240fad6265dd7a7a6e045636268b17..dc3e656470dd589102771c2046c8de42fe5d670d 100644 (file)
@@ -48,8 +48,15 @@ struct virtio_balloon_config {
        __u32 num_pages;
        /* Number of pages we've actually got in balloon. */
        __u32 actual;
-       /* Free page report command id, readonly by guest */
-       __u32 free_page_report_cmd_id;
+       /*
+        * Free page hint command id, readonly by guest.
+        * Was previously named free_page_report_cmd_id so we
+        * need to carry that name for legacy support.
+        */
+       union {
+               __u32 free_page_hint_cmd_id;
+               __u32 free_page_report_cmd_id;  /* deprecated */
+       };
        /* Stores PAGE_POISON if page poisoning is in use */
        __u32 poison_val;
 };
index 7f5930801f722164013fc143dff0fcb3568dfbdd..3ae65e93235cf77ffbae4a37fff9bbe35e600933 100644 (file)
@@ -209,7 +209,7 @@ struct fc_bsg_host_vendor {
        __u64 vendor_id;
 
        /* start of vendor command area */
-       __u32 vendor_cmd[];
+       __u32 vendor_cmd[0];
 };
 
 /* Response:
index 5cbc9fcbfd45c1d03464acee3cf706a7f9ec528d..7955c56d6b3c331abf9652a0796f9ca39e984d8e 100644 (file)
@@ -73,8 +73,8 @@ struct vdso_timestamp {
  *
  * @offset is used by the special time namespace VVAR pages which are
  * installed instead of the real VVAR page. These namespace pages must set
- * @seq to 1 and @clock_mode to VLOCK_TIMENS to force the code into the
- * time namespace slow path. The namespace aware functions retrieve the
+ * @seq to 1 and @clock_mode to VDSO_CLOCKMODE_TIMENS to force the code into
+ * the time namespace slow path. The namespace aware functions retrieve the
  * real system wide VVAR page, read host time and add the per clock offset.
  * For clocks which are not affected by time namespace adjustment the
  * offset must be zero.
index 9e22ee8fbd75e2dbe2d80fa0952e0393e4ee01dd..9278a603d39934a411f1a9ccddecce925484ffe0 100644 (file)
@@ -39,22 +39,6 @@ config TOOLS_SUPPORT_RELR
 config CC_HAS_ASM_INLINE
        def_bool $(success,echo 'void foo(void) { asm inline (""); }' | $(CC) -x c - -c -o /dev/null)
 
-config CC_HAS_WARN_MAYBE_UNINITIALIZED
-       def_bool $(cc-option,-Wmaybe-uninitialized)
-       help
-         GCC >= 4.7 supports this option.
-
-config CC_DISABLE_WARN_MAYBE_UNINITIALIZED
-       bool
-       depends on CC_HAS_WARN_MAYBE_UNINITIALIZED
-       default CC_IS_GCC && GCC_VERSION < 40900  # unreliable for GCC < 4.9
-       help
-         GCC's -Wmaybe-uninitialized is not reliable by definition.
-         Lots of false positive warnings are produced in some cases.
-
-         If this option is enabled, -Wno-maybe-uninitialzed is passed
-         to the compiler to suppress maybe-uninitialized warnings.
-
 config CONSTRUCTORS
        bool
        depends on !UML
@@ -1257,14 +1241,12 @@ config CC_OPTIMIZE_FOR_PERFORMANCE
 config CC_OPTIMIZE_FOR_PERFORMANCE_O3
        bool "Optimize more for performance (-O3)"
        depends on ARC
-       imply CC_DISABLE_WARN_MAYBE_UNINITIALIZED  # avoid false positives
        help
          Choosing this option will pass "-O3" to your compiler to optimize
          the kernel yet more for performance.
 
 config CC_OPTIMIZE_FOR_SIZE
        bool "Optimize for size (-Os)"
-       imply CC_DISABLE_WARN_MAYBE_UNINITIALIZED  # avoid false positives
        help
          Choosing this option will pass "-Os" to your compiler resulting
          in a smaller kernel.
index 8ec1be4d7d5121498e606ef522a7c4eeeef3e52b..7a38012e1af742124298ca2b299886076631f3df 100644 (file)
@@ -542,7 +542,7 @@ void __weak free_initrd_mem(unsigned long start, unsigned long end)
 }
 
 #ifdef CONFIG_KEXEC_CORE
-static bool kexec_free_initrd(void)
+static bool __init kexec_free_initrd(void)
 {
        unsigned long crashk_start = (unsigned long)__va(crashk_res.start);
        unsigned long crashk_end   = (unsigned long)__va(crashk_res.end);
index a48617f2e5e5bcf789998415c7ea37c8e97de55d..1a5da2c2660c8816dc34982cbb4db99df5132308 100644 (file)
@@ -257,6 +257,47 @@ static int __init loglevel(char *str)
 
 early_param("loglevel", loglevel);
 
+#ifdef CONFIG_BLK_DEV_INITRD
+static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum)
+{
+       u32 size, csum;
+       char *data;
+       u32 *hdr;
+
+       if (!initrd_end)
+               return NULL;
+
+       data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN;
+       if (memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN))
+               return NULL;
+
+       hdr = (u32 *)(data - 8);
+       size = hdr[0];
+       csum = hdr[1];
+
+       data = ((void *)hdr) - size;
+       if ((unsigned long)data < initrd_start) {
+               pr_err("bootconfig size %d is greater than initrd size %ld\n",
+                       size, initrd_end - initrd_start);
+               return NULL;
+       }
+
+       /* Remove bootconfig from initramfs/initrd */
+       initrd_end = (unsigned long)data;
+       if (_size)
+               *_size = size;
+       if (_csum)
+               *_csum = csum;
+
+       return data;
+}
+#else
+static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum)
+{
+       return NULL;
+}
+#endif
+
 #ifdef CONFIG_BOOT_CONFIG
 
 char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
@@ -357,9 +398,12 @@ static void __init setup_boot_config(const char *cmdline)
        int pos;
        u32 size, csum;
        char *data, *copy;
-       u32 *hdr;
        int ret;
 
+       data = get_boot_config_from_initrd(&size, &csum);
+       if (!data)
+               goto not_found;
+
        strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
        parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
                   bootconfig_params);
@@ -367,27 +411,12 @@ static void __init setup_boot_config(const char *cmdline)
        if (!bootconfig_found)
                return;
 
-       if (!initrd_end)
-               goto not_found;
-
-       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];
-
        if (size >= XBC_DATA_MAX) {
                pr_err("bootconfig size %d greater than max size %d\n",
                        size, XBC_DATA_MAX);
                return;
        }
 
-       data = ((void *)hdr) - size;
-       if ((unsigned long)data < initrd_start)
-               goto not_found;
-
        if (boot_config_checksum((unsigned char *)data, size) != csum) {
                pr_err("bootconfig checksum failed\n");
                return;
@@ -420,8 +449,14 @@ static void __init setup_boot_config(const char *cmdline)
 not_found:
        pr_err("'bootconfig' found on command line, but no bootconfig found\n");
 }
+
 #else
-#define setup_boot_config(cmdline)     do { } while (0)
+
+static void __init setup_boot_config(const char *cmdline)
+{
+       /* Remove bootconfig data from initrd */
+       get_boot_config_from_initrd(NULL, NULL);
+}
 
 static int __init warn_bootconfig(char *str)
 {
index dc8307bf2d74d3b550d2fac210dae09920ef0bcf..beff0cfcd1e874dd3cb03fd23c1a28fb67b373c2 100644 (file)
@@ -142,6 +142,7 @@ struct mqueue_inode_info {
 
        struct sigevent notify;
        struct pid *notify_owner;
+       u32 notify_self_exec_id;
        struct user_namespace *notify_user_ns;
        struct user_struct *user;       /* user who created, for accounting */
        struct sock *notify_sock;
@@ -773,28 +774,44 @@ static void __do_notify(struct mqueue_inode_info *info)
         * synchronously. */
        if (info->notify_owner &&
            info->attr.mq_curmsgs == 1) {
-               struct kernel_siginfo sig_i;
                switch (info->notify.sigev_notify) {
                case SIGEV_NONE:
                        break;
-               case SIGEV_SIGNAL:
-                       /* sends signal */
+               case SIGEV_SIGNAL: {
+                       struct kernel_siginfo sig_i;
+                       struct task_struct *task;
+
+                       /* do_mq_notify() accepts sigev_signo == 0, why?? */
+                       if (!info->notify.sigev_signo)
+                               break;
 
                        clear_siginfo(&sig_i);
                        sig_i.si_signo = info->notify.sigev_signo;
                        sig_i.si_errno = 0;
                        sig_i.si_code = SI_MESGQ;
                        sig_i.si_value = info->notify.sigev_value;
-                       /* map current pid/uid into info->owner's namespaces */
                        rcu_read_lock();
+                       /* map current pid/uid into info->owner's namespaces */
                        sig_i.si_pid = task_tgid_nr_ns(current,
                                                ns_of_pid(info->notify_owner));
-                       sig_i.si_uid = from_kuid_munged(info->notify_user_ns, current_uid());
+                       sig_i.si_uid = from_kuid_munged(info->notify_user_ns,
+                                               current_uid());
+                       /*
+                        * We can't use kill_pid_info(), this signal should
+                        * bypass check_kill_permission(). It is from kernel
+                        * but si_fromuser() can't know this.
+                        * We do check the self_exec_id, to avoid sending
+                        * signals to programs that don't expect them.
+                        */
+                       task = pid_task(info->notify_owner, PIDTYPE_TGID);
+                       if (task && task->self_exec_id ==
+                                               info->notify_self_exec_id) {
+                               do_send_sig_info(info->notify.sigev_signo,
+                                               &sig_i, task, PIDTYPE_TGID);
+                       }
                        rcu_read_unlock();
-
-                       kill_pid_info(info->notify.sigev_signo,
-                                     &sig_i, info->notify_owner);
                        break;
+               }
                case SIGEV_THREAD:
                        set_cookie(info->notify_cookie, NOTIFY_WOKENUP);
                        netlink_sendskb(info->notify_sock, info->notify_cookie);
@@ -1383,6 +1400,7 @@ retry:
                        info->notify.sigev_signo = notification->sigev_signo;
                        info->notify.sigev_value = notification->sigev_value;
                        info->notify.sigev_notify = SIGEV_SIGNAL;
+                       info->notify_self_exec_id = current->self_exec_id;
                        break;
                }
 
index b69c8b460341f5698ec518d8539df7f0904d22c6..87f31bf1f0a0c80304a6ff82cc4207aee1194ca7 100644 (file)
@@ -1326,6 +1326,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2:
                if (!audit_enabled && msg_type != AUDIT_USER_AVC)
                        return 0;
+               /* exit early if there isn't at least one character to print */
+               if (data_len < 2)
+                       return -EINVAL;
 
                err = audit_filter(msg_type, AUDIT_FILTER_USER);
                if (err == 1) { /* match or error */
index f02504640e1851e2fc0199042fbac7fe11ba596d..6b12f06ee18c3d7de63b10ec1a76bcefb1121111 100644 (file)
@@ -30,7 +30,7 @@ struct bpf_lru_node {
 struct bpf_lru_list {
        struct list_head lists[NR_BPF_LRU_LIST_T];
        unsigned int counts[NR_BPF_LRU_LIST_COUNT];
-       /* The next inacitve list rotation starts from here */
+       /* The next inactive list rotation starts from here */
        struct list_head *next_inactive_rotation;
 
        raw_spinlock_t lock ____cacheline_aligned_in_smp;
index 70f71b154fa578e1d5d1ae7a4065af0223f64113..3fe0b006d2d2ef93887c34153940f27ad014b374 100644 (file)
@@ -469,7 +469,7 @@ static int cpu_map_update_elem(struct bpf_map *map, void *key, void *value,
                return -EOVERFLOW;
 
        /* Make sure CPU is a valid possible cpu */
-       if (!cpu_possible(key_cpu))
+       if (key_cpu >= nr_cpumask_bits || !cpu_possible(key_cpu))
                return -ENODEV;
 
        if (qsize == 0) {
index 64783da342020212f12a1a57212b16e330786b5f..7626b802447128f4fc5ec789e24d9bb6d8e96a27 100644 (file)
@@ -586,9 +586,7 @@ static void bpf_map_mmap_open(struct vm_area_struct *vma)
 {
        struct bpf_map *map = vma->vm_file->private_data;
 
-       bpf_map_inc_with_uref(map);
-
-       if (vma->vm_flags & VM_WRITE) {
+       if (vma->vm_flags & VM_MAYWRITE) {
                mutex_lock(&map->freeze_mutex);
                map->writecnt++;
                mutex_unlock(&map->freeze_mutex);
@@ -600,13 +598,11 @@ static void bpf_map_mmap_close(struct vm_area_struct *vma)
 {
        struct bpf_map *map = vma->vm_file->private_data;
 
-       if (vma->vm_flags & VM_WRITE) {
+       if (vma->vm_flags & VM_MAYWRITE) {
                mutex_lock(&map->freeze_mutex);
                map->writecnt--;
                mutex_unlock(&map->freeze_mutex);
        }
-
-       bpf_map_put_with_uref(map);
 }
 
 static const struct vm_operations_struct bpf_map_default_vmops = {
@@ -635,14 +631,16 @@ static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma)
        /* set default open/close callbacks */
        vma->vm_ops = &bpf_map_default_vmops;
        vma->vm_private_data = map;
+       vma->vm_flags &= ~VM_MAYEXEC;
+       if (!(vma->vm_flags & VM_WRITE))
+               /* disallow re-mapping with PROT_WRITE */
+               vma->vm_flags &= ~VM_MAYWRITE;
 
        err = map->ops->map_mmap(map, vma);
        if (err)
                goto out;
 
-       bpf_map_inc_with_uref(map);
-
-       if (vma->vm_flags & VM_WRITE)
+       if (vma->vm_flags & VM_MAYWRITE)
                map->writecnt++;
 out:
        mutex_unlock(&map->freeze_mutex);
@@ -2285,7 +2283,7 @@ static void bpf_link_show_fdinfo(struct seq_file *m, struct file *filp)
 }
 #endif
 
-const struct file_operations bpf_link_fops = {
+static const struct file_operations bpf_link_fops = {
 #ifdef CONFIG_PROC_FS
        .show_fdinfo    = bpf_link_show_fdinfo,
 #endif
@@ -3630,8 +3628,10 @@ static int link_update(union bpf_attr *attr)
                return PTR_ERR(link);
 
        new_prog = bpf_prog_get(attr->link_update.new_prog_fd);
-       if (IS_ERR(new_prog))
-               return PTR_ERR(new_prog);
+       if (IS_ERR(new_prog)) {
+               ret = PTR_ERR(new_prog);
+               goto out_put_link;
+       }
 
        if (flags & BPF_F_REPLACE) {
                old_prog = bpf_prog_get(attr->link_update.old_prog_fd);
@@ -3640,6 +3640,9 @@ static int link_update(union bpf_attr *attr)
                        old_prog = NULL;
                        goto out_put_progs;
                }
+       } else if (attr->link_update.old_prog_fd) {
+               ret = -EINVAL;
+               goto out_put_progs;
        }
 
 #ifdef CONFIG_CGROUP_BPF
@@ -3655,6 +3658,8 @@ out_put_progs:
                bpf_prog_put(old_prog);
        if (ret)
                bpf_prog_put(new_prog);
+out_put_link:
+       bpf_link_put(link);
        return ret;
 }
 
index 04c6630cc18f97b53e2d7a39cd9fbc87435f1bef..fa1d8245b9257fe6f0f40dfca35702ebe7662000 100644 (file)
@@ -1255,8 +1255,7 @@ static void __mark_reg_unknown(const struct bpf_verifier_env *env,
        reg->type = SCALAR_VALUE;
        reg->var_off = tnum_unknown;
        reg->frameno = 0;
-       reg->precise = env->subprog_cnt > 1 || !env->allow_ptr_leaks ?
-                      true : false;
+       reg->precise = env->subprog_cnt > 1 || !env->allow_ptr_leaks;
        __mark_reg_unbounded(reg);
 }
 
@@ -2119,6 +2118,15 @@ static bool register_is_const(struct bpf_reg_state *reg)
        return reg->type == SCALAR_VALUE && tnum_is_const(reg->var_off);
 }
 
+static bool __is_pointer_value(bool allow_ptr_leaks,
+                              const struct bpf_reg_state *reg)
+{
+       if (allow_ptr_leaks)
+               return false;
+
+       return reg->type != SCALAR_VALUE;
+}
+
 static void save_register_state(struct bpf_func_state *state,
                                int spi, struct bpf_reg_state *reg)
 {
@@ -2309,6 +2317,16 @@ static int check_stack_read(struct bpf_verifier_env *env,
                         * which resets stack/reg liveness for state transitions
                         */
                        state->regs[value_regno].live |= REG_LIVE_WRITTEN;
+               } else if (__is_pointer_value(env->allow_ptr_leaks, reg)) {
+                       /* If value_regno==-1, the caller is asking us whether
+                        * it is acceptable to use this value as a SCALAR_VALUE
+                        * (e.g. for XADD).
+                        * We must not allow unprivileged callers to do that
+                        * with spilled pointers.
+                        */
+                       verbose(env, "leaking pointer from stack off %d\n",
+                               off);
+                       return -EACCES;
                }
                mark_reg_read(env, reg, reg->parent, REG_LIVE_READ64);
        } else {
@@ -2674,15 +2692,6 @@ static int check_sock_access(struct bpf_verifier_env *env, int insn_idx,
        return -EACCES;
 }
 
-static bool __is_pointer_value(bool allow_ptr_leaks,
-                              const struct bpf_reg_state *reg)
-{
-       if (allow_ptr_leaks)
-               return false;
-
-       return reg->type != SCALAR_VALUE;
-}
-
 static struct bpf_reg_state *reg_state(struct bpf_verifier_env *env, int regno)
 {
        return cur_regs(env) + regno;
@@ -3090,7 +3099,7 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env,
        if (ret < 0)
                return ret;
 
-       if (atype == BPF_READ) {
+       if (atype == BPF_READ && value_regno >= 0) {
                if (ret == SCALAR_VALUE) {
                        mark_reg_unknown(env, regs, value_regno);
                        return 0;
@@ -10488,6 +10497,7 @@ static int check_attach_btf_id(struct bpf_verifier_env *env)
                                return -EINVAL;
                        }
                        env->ops = bpf_verifier_ops[tgt_prog->type];
+                       prog->expected_attach_type = tgt_prog->expected_attach_type;
                }
                if (!tgt_prog->jited) {
                        verbose(env, "Can attach to only JITed progs\n");
@@ -10832,6 +10842,13 @@ err_release_maps:
                 * them now. Otherwise free_used_maps() will release them.
                 */
                release_maps(env);
+
+       /* extension progs temporarily inherit the attach_type of their targets
+          for verification purposes, so set it back to zero before returning
+        */
+       if (env->prog->type == BPF_PROG_TYPE_EXT)
+               env->prog->expected_attach_type = 0;
+
        *prog = env->prog;
 err_unlock:
        if (!is_priv)
index bc9b98a9af9ac18b84b157612e3f73c067097d94..633b4ae72ed598449f3ba2bb0da24eb92e86b17e 100644 (file)
@@ -7491,10 +7491,17 @@ static void perf_event_task_output(struct perf_event *event,
                goto out;
 
        task_event->event_id.pid = perf_event_pid(event, task);
-       task_event->event_id.ppid = perf_event_pid(event, current);
-
        task_event->event_id.tid = perf_event_tid(event, task);
-       task_event->event_id.ptid = perf_event_tid(event, current);
+
+       if (task_event->event_id.header.type == PERF_RECORD_EXIT) {
+               task_event->event_id.ppid = perf_event_pid(event,
+                                                       task->real_parent);
+               task_event->event_id.ptid = perf_event_pid(event,
+                                                       task->real_parent);
+       } else {  /* PERF_RECORD_FORK */
+               task_event->event_id.ppid = perf_event_pid(event, current);
+               task_event->event_id.ptid = perf_event_tid(event, current);
+       }
 
        task_event->event_id.time = perf_event_clock(event);
 
index 389a88cb308192babd68abfb4f2022803c3346c1..ce2a75bc0adeb2bc7edd19e4df6680b272f62d99 100644 (file)
@@ -219,6 +219,7 @@ repeat:
 
        write_unlock_irq(&tasklist_lock);
        proc_flush_pid(thread_pid);
+       put_pid(thread_pid);
        release_thread(p);
        put_task_struct_rcu_user(p);
 
index 4385f3d639f23c2347d31061ede5081cc51616cf..8c700f881d920dfccaf531b7df23314f7bbf4120 100644 (file)
@@ -2605,6 +2605,14 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
        struct clone_args args;
        pid_t *kset_tid = kargs->set_tid;
 
+       BUILD_BUG_ON(offsetofend(struct clone_args, tls) !=
+                    CLONE_ARGS_SIZE_VER0);
+       BUILD_BUG_ON(offsetofend(struct clone_args, set_tid_size) !=
+                    CLONE_ARGS_SIZE_VER1);
+       BUILD_BUG_ON(offsetofend(struct clone_args, cgroup) !=
+                    CLONE_ARGS_SIZE_VER2);
+       BUILD_BUG_ON(sizeof(struct clone_args) != CLONE_ARGS_SIZE_VER2);
+
        if (unlikely(usize > PAGE_SIZE))
                return -E2BIG;
        if (unlikely(usize < CLONE_ARGS_SIZE_VER0))
@@ -2631,7 +2639,8 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
                     !valid_signal(args.exit_signal)))
                return -EINVAL;
 
-       if ((args.flags & CLONE_INTO_CGROUP) && args.cgroup < 0)
+       if ((args.flags & CLONE_INTO_CGROUP) &&
+           (args.cgroup > INT_MAX || usize < CLONE_ARGS_SIZE_VER2))
                return -EINVAL;
 
        *kargs = (struct kernel_clone_args){
index fe40c658f86f851bb175ff1c374e7c808007b04f..453a8a0f48046d090d1ff88b15b28c32ee53cd8c 100644 (file)
@@ -1690,34 +1690,6 @@ out_mput:
        return ret;
 }
 
-/**
- *     setup_irq - setup an interrupt
- *     @irq: Interrupt line to setup
- *     @act: irqaction for the interrupt
- *
- * Used to statically setup interrupts in the early boot process.
- */
-int setup_irq(unsigned int irq, struct irqaction *act)
-{
-       int retval;
-       struct irq_desc *desc = irq_to_desc(irq);
-
-       if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
-               return -EINVAL;
-
-       retval = irq_chip_pm_get(&desc->irq_data);
-       if (retval < 0)
-               return retval;
-
-       retval = __setup_irq(irq, desc, act);
-
-       if (retval)
-               irq_chip_pm_put(&desc->irq_data);
-
-       return retval;
-}
-EXPORT_SYMBOL_GPL(setup_irq);
-
 /*
  * Internal function to unregister an irqaction - used to free
  * regular and special interrupts that are part of the architecture.
@@ -1858,22 +1830,6 @@ static struct irqaction *__free_irq(struct irq_desc *desc, void *dev_id)
        return action;
 }
 
-/**
- *     remove_irq - free an interrupt
- *     @irq: Interrupt line to free
- *     @act: irqaction for the interrupt
- *
- * Used to remove interrupts statically setup by the early boot process.
- */
-void remove_irq(unsigned int irq, struct irqaction *act)
-{
-       struct irq_desc *desc = irq_to_desc(irq);
-
-       if (desc && !WARN_ON(irq_settings_is_per_cpu_devid(desc)))
-               __free_irq(desc, act->dev_id);
-}
-EXPORT_SYMBOL_GPL(remove_irq);
-
 /**
  *     free_irq - free an interrupt allocated with request_irq
  *     @irq: Interrupt line to free
index f50354202dbe52ca0652f7c20151b45894fd8840..8accc9722a815bf88d301d86a98d90bc80f92b7d 100644 (file)
@@ -740,8 +740,8 @@ static const struct file_operations kcov_fops = {
  * kcov_remote_handle() with KCOV_SUBSYSTEM_COMMON as the subsystem id and an
  * arbitrary 4-byte non-zero number as the instance id). This common handle
  * then gets saved into the task_struct of the process that issued the
- * KCOV_REMOTE_ENABLE ioctl. When this proccess issues system calls that spawn
- * kernel threads, the common handle must be retrived via kcov_common_handle()
+ * KCOV_REMOTE_ENABLE ioctl. When this process issues system calls that spawn
+ * kernel threads, the common handle must be retrieved via kcov_common_handle()
  * and passed to the spawned threads via custom annotations. Those kernel
  * threads must in turn be annotated with kcov_remote_start(common_handle) and
  * kcov_remote_stop(). All of the threads that are spawned by the same process
index 86aba8706b1654b83162fb2888916f2de013f6b0..30bd28d1d418cce6d785d1b65e68f429a253845d 100644 (file)
@@ -898,6 +898,13 @@ static int software_resume(void)
        error = freeze_processes();
        if (error)
                goto Close_Finish;
+
+       error = freeze_kernel_threads();
+       if (error) {
+               thaw_processes();
+               goto Close_Finish;
+       }
+
        error = load_image_and_restore();
        thaw_processes();
  Finish:
index 06548e2ebb72e4928fb483cd7faf692dd86a29a1..d9a49cd6065a20936edbda1b334136ab597cde52 100644 (file)
@@ -825,7 +825,7 @@ static __always_inline void rcu_nmi_enter_common(bool irq)
                        rcu_cleanup_after_idle();
 
                incby = 1;
-       } else if (tick_nohz_full_cpu(rdp->cpu) &&
+       } else if (irq && tick_nohz_full_cpu(rdp->cpu) &&
                   rdp->dynticks_nmi_nesting == DYNTICK_IRQ_NONIDLE &&
                   READ_ONCE(rdp->rcu_urgent_qs) &&
                   !READ_ONCE(rdp->rcu_forced_tick)) {
index 3a61a3b8eaa9e137d29106dd6ab0fffbbd826f02..9a2fbf98fd6fa2ea3c420d02ac4cb20d2ba73958 100644 (file)
@@ -1232,13 +1232,8 @@ static void uclamp_fork(struct task_struct *p)
                return;
 
        for_each_clamp_id(clamp_id) {
-               unsigned int clamp_value = uclamp_none(clamp_id);
-
-               /* By default, RT tasks always get 100% boost */
-               if (unlikely(rt_task(p) && clamp_id == UCLAMP_MIN))
-                       clamp_value = uclamp_none(UCLAMP_MAX);
-
-               uclamp_se_set(&p->uclamp_req[clamp_id], clamp_value, false);
+               uclamp_se_set(&p->uclamp_req[clamp_id],
+                             uclamp_none(clamp_id), false);
        }
 }
 
index dac9104d126f7d4483a64a46c965bb48fcbdc811..ff9435dee1df218a96d05ac4fc1130f0bca204e1 100644 (file)
@@ -1003,12 +1003,12 @@ u64 kcpustat_field(struct kernel_cpustat *kcpustat,
                   enum cpu_usage_stat usage, int cpu)
 {
        u64 *cpustat = kcpustat->cpustat;
+       u64 val = cpustat[usage];
        struct rq *rq;
-       u64 val;
        int err;
 
        if (!vtime_accounting_enabled_cpu(cpu))
-               return cpustat[usage];
+               return val;
 
        rq = cpu_rq(cpu);
 
index 008d6ac2342b7536fff293b2ce7054cf9d9cfc98..808244f3ddd9842d684503a493cd8a69092cff74 100644 (file)
@@ -149,6 +149,9 @@ __setup("nohz_full=", housekeeping_nohz_full_setup);
 static int __init housekeeping_isolcpus_setup(char *str)
 {
        unsigned int flags = 0;
+       bool illegal = false;
+       char *par;
+       int len;
 
        while (isalpha(*str)) {
                if (!strncmp(str, "nohz,", 5)) {
@@ -169,8 +172,22 @@ static int __init housekeeping_isolcpus_setup(char *str)
                        continue;
                }
 
-               pr_warn("isolcpus: Error, unknown flag\n");
-               return 0;
+               /*
+                * Skip unknown sub-parameter and validate that it is not
+                * containing an invalid character.
+                */
+               for (par = str, len = 0; *str && *str != ','; str++, len++) {
+                       if (!isalpha(*str) && *str != '_')
+                               illegal = true;
+               }
+
+               if (illegal) {
+                       pr_warn("isolcpus: Invalid flag %.*s\n", len, par);
+                       return 0;
+               }
+
+               pr_info("isolcpus: Skipped unknown flag %.*s\n", len, par);
+               str++;
        }
 
        /* Default behaviour for isolcpus without flags */
index e58a6c619824fd5067825c588de5ab7b9749700f..284fc1600063bd082c897c125ef4cc20c0612e39 100644 (file)
@@ -1510,15 +1510,15 @@ int kill_pid_usb_asyncio(int sig, int errno, sigval_t addr,
        unsigned long flags;
        int ret = -EINVAL;
 
+       if (!valid_signal(sig))
+               return ret;
+
        clear_siginfo(&info);
        info.si_signo = sig;
        info.si_errno = errno;
        info.si_code = SI_ASYNCIO;
        *((sigval_t *)&info.si_pid) = addr;
 
-       if (!valid_signal(sig))
-               return ret;
-
        rcu_read_lock();
        p = pid_task(pid, PIDTYPE_PID);
        if (!p) {
@@ -1557,12 +1557,8 @@ static int kill_something_info(int sig, struct kernel_siginfo *info, pid_t pid)
 {
        int ret;
 
-       if (pid > 0) {
-               rcu_read_lock();
-               ret = kill_pid_info(sig, info, find_vpid(pid));
-               rcu_read_unlock();
-               return ret;
-       }
+       if (pid > 0)
+               return kill_proc_info(sig, info, pid);
 
        /* -INT_MIN is undefined.  Exclude this case to avoid a UBSAN warning */
        if (pid == INT_MIN)
@@ -1993,8 +1989,12 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
                if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN)
                        sig = 0;
        }
+       /*
+        * Send with __send_signal as si_pid and si_uid are in the
+        * parent's namespaces.
+        */
        if (valid_signal(sig) && sig)
-               __group_send_sig_info(sig, &info, tsk->parent);
+               __send_signal(sig, &info, tsk->parent, PIDTYPE_TGID, false);
        __wake_up_parent(tsk, tsk->parent);
        spin_unlock_irqrestore(&psig->siglock, flags);
 
index 3b30288793fe72504c029413304000d91daa82ac..53bce347cd50bc24b1fbebd8fc5c26cc97e6742a 100644 (file)
@@ -338,7 +338,20 @@ static struct user_namespace *timens_owner(struct ns_common *ns)
 
 static void show_offset(struct seq_file *m, int clockid, struct timespec64 *ts)
 {
-       seq_printf(m, "%d %lld %ld\n", clockid, ts->tv_sec, ts->tv_nsec);
+       char *clock;
+
+       switch (clockid) {
+       case CLOCK_BOOTTIME:
+               clock = "boottime";
+               break;
+       case CLOCK_MONOTONIC:
+               clock = "monotonic";
+               break;
+       default:
+               clock = "unknown";
+               break;
+       }
+       seq_printf(m, "%-10s %10lld %9ld\n", clock, ts->tv_sec, ts->tv_nsec);
 }
 
 void proc_timens_show_offsets(struct task_struct *p, struct seq_file *m)
index 402eef84c859ac0b7356ca89f22446b00e0b757e..743647005f64e6aea6946f01e98c25b6851338c7 100644 (file)
@@ -466,7 +466,6 @@ config PROFILE_ANNOTATED_BRANCHES
 config PROFILE_ALL_BRANCHES
        bool "Profile all if conditionals" if !FORTIFY_SOURCE
        select TRACE_BRANCH_PROFILING
-       imply CC_DISABLE_WARN_MAYBE_UNINITIALIZED  # avoid false positives
        help
          This tracer profiles all branch conditions. Every if ()
          taken in the kernel is recorded whether it hit or miss.
index 041694a1eb74d88d8b0fb44d26f13d06a7a29d82..bd030b1b9514857cce1e0b38f0f9e2bcce7fa78f 100644 (file)
@@ -5165,6 +5165,7 @@ int unregister_ftrace_direct(unsigned long ip, unsigned long addr)
                        list_del_rcu(&direct->next);
                        synchronize_rcu_tasks();
                        kfree(direct);
+                       kfree(entry);
                        ftrace_direct_func_count--;
                }
        }
index 31c0fad4cb9e18910cd318abb4d76c4db09d592e..c4c86de63cf911388d5b6f22809c0acf49ff1b9c 100644 (file)
@@ -113,22 +113,42 @@ static int preemptirq_delay_run(void *data)
 
        for (i = 0; i < s; i++)
                (testfuncs[i])(i);
+
+       set_current_state(TASK_INTERRUPTIBLE);
+       while (!kthread_should_stop()) {
+               schedule();
+               set_current_state(TASK_INTERRUPTIBLE);
+       }
+
+       __set_current_state(TASK_RUNNING);
+
        return 0;
 }
 
-static struct task_struct *preemptirq_start_test(void)
+static int preemptirq_run_test(void)
 {
+       struct task_struct *task;
+
        char task_name[50];
 
        snprintf(task_name, sizeof(task_name), "%s_test", test_mode);
-       return kthread_run(preemptirq_delay_run, NULL, task_name);
+       task =  kthread_run(preemptirq_delay_run, NULL, task_name);
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+       if (task)
+               kthread_stop(task);
+       return 0;
 }
 
 
 static ssize_t trigger_store(struct kobject *kobj, struct kobj_attribute *attr,
                         const char *buf, size_t count)
 {
-       preemptirq_start_test();
+       ssize_t ret;
+
+       ret = preemptirq_run_test();
+       if (ret)
+               return ret;
        return count;
 }
 
@@ -148,11 +168,9 @@ static struct kobject *preemptirq_delay_kobj;
 
 static int __init preemptirq_delay_init(void)
 {
-       struct task_struct *test_task;
        int retval;
 
-       test_task = preemptirq_start_test();
-       retval = PTR_ERR_OR_ZERO(test_task);
+       retval = preemptirq_run_test();
        if (retval != 0)
                return retval;
 
index 8d2b988126250da9078230ffe31d6b77c493f2dc..29615f15a820b2f67d66af8084bfcd13936ed9c3 100644 (file)
@@ -947,7 +947,8 @@ int __trace_bputs(unsigned long ip, const char *str)
 EXPORT_SYMBOL_GPL(__trace_bputs);
 
 #ifdef CONFIG_TRACER_SNAPSHOT
-void tracing_snapshot_instance_cond(struct trace_array *tr, void *cond_data)
+static void tracing_snapshot_instance_cond(struct trace_array *tr,
+                                          void *cond_data)
 {
        struct tracer *tracer = tr->current_trace;
        unsigned long flags;
@@ -8525,6 +8526,19 @@ static int allocate_trace_buffers(struct trace_array *tr, int size)
         */
        allocate_snapshot = false;
 #endif
+
+       /*
+        * Because of some magic with the way alloc_percpu() works on
+        * x86_64, we need to synchronize the pgd of all the tables,
+        * otherwise the trace events that happen in x86_64 page fault
+        * handlers can't cope with accessing the chance that a
+        * alloc_percpu()'d memory might be touched in the page fault trace
+        * event. Oh, and we need to audit all other alloc_percpu() and vmalloc()
+        * calls in tracing, because something might get triggered within a
+        * page fault trace event!
+        */
+       vmalloc_sync_mappings();
+
        return 0;
 }
 
index 06d7feb5255f88d51e80ed144ee3ef41ccb8a783..9de29bb45a27f1aae98479ff60660db2b807b4f6 100644 (file)
@@ -95,24 +95,20 @@ trace_boot_add_kprobe_event(struct xbc_node *node, const char *event)
        struct xbc_node *anode;
        char buf[MAX_BUF_LEN];
        const char *val;
-       int ret;
+       int ret = 0;
 
-       kprobe_event_cmd_init(&cmd, buf, MAX_BUF_LEN);
+       xbc_node_for_each_array_value(node, "probes", anode, val) {
+               kprobe_event_cmd_init(&cmd, buf, MAX_BUF_LEN);
 
-       ret = kprobe_event_gen_cmd_start(&cmd, event, NULL);
-       if (ret)
-               return ret;
+               ret = kprobe_event_gen_cmd_start(&cmd, event, val);
+               if (ret)
+                       break;
 
-       xbc_node_for_each_array_value(node, "probes", anode, val) {
-               ret = kprobe_event_add_field(&cmd, val);
+               ret = kprobe_event_gen_cmd_end(&cmd);
                if (ret)
-                       return ret;
+                       pr_err("Failed to add probe: %s\n", buf);
        }
 
-       ret = kprobe_event_gen_cmd_end(&cmd);
-       if (ret)
-               pr_err("Failed to add probe: %s\n", buf);
-
        return ret;
 }
 #else
index 5f6834a2bf4119ef4a30879cac479e0cbc0e5bdf..fcab11cc6833b2ccb74a169ee184584de64f5205 100644 (file)
@@ -3320,6 +3320,9 @@ static void __destroy_hist_field(struct hist_field *hist_field)
        kfree(hist_field->name);
        kfree(hist_field->type);
 
+       kfree(hist_field->system);
+       kfree(hist_field->event_name);
+
        kfree(hist_field);
 }
 
@@ -4382,6 +4385,7 @@ static struct hist_field *create_var(struct hist_trigger_data *hist_data,
                goto out;
        }
 
+       var->ref = 1;
        var->flags = HIST_FIELD_FL_VAR;
        var->var.idx = idx;
        var->var.hist_data = var->hist_data = hist_data;
@@ -5011,6 +5015,9 @@ static void destroy_field_vars(struct hist_trigger_data *hist_data)
 
        for (i = 0; i < hist_data->n_field_vars; i++)
                destroy_field_var(hist_data->field_vars[i]);
+
+       for (i = 0; i < hist_data->n_save_vars; i++)
+               destroy_field_var(hist_data->save_vars[i]);
 }
 
 static void save_field_var(struct hist_trigger_data *hist_data,
index dd34a1b46a867d22cd50385af8a175dee03f8d35..3a74736da363ae972358ad4e94018c262516c5ce 100644 (file)
@@ -1088,14 +1088,10 @@ register_snapshot_trigger(char *glob, struct event_trigger_ops *ops,
                          struct event_trigger_data *data,
                          struct trace_event_file *file)
 {
-       int ret = register_trigger(glob, ops, data, file);
-
-       if (ret > 0 && tracing_alloc_snapshot_instance(file->tr) != 0) {
-               unregister_trigger(glob, ops, data, file);
-               ret = 0;
-       }
+       if (tracing_alloc_snapshot_instance(file->tr) != 0)
+               return 0;
 
-       return ret;
+       return register_trigger(glob, ops, data, file);
 }
 
 static int
index d0568af4a0ef62001372988ba539058551934741..35989383ae1131e11e45a39e0a5333a57f4493e0 100644 (file)
@@ -453,7 +453,7 @@ static bool __within_notrace_func(unsigned long addr)
 
 static bool within_notrace_func(struct trace_kprobe *tk)
 {
-       unsigned long addr = addr = trace_kprobe_address(tk);
+       unsigned long addr = trace_kprobe_address(tk);
        char symname[KSYM_NAME_LEN], *p;
 
        if (!__within_notrace_func(addr))
@@ -940,6 +940,9 @@ EXPORT_SYMBOL_GPL(kprobe_event_cmd_init);
  * complete command or only the first part of it; in the latter case,
  * kprobe_event_add_fields() can be used to add more fields following this.
  *
+ * Unlikely the synth_event_gen_cmd_start(), @loc must be specified. This
+ * returns -EINVAL if @loc == NULL.
+ *
  * Return: 0 if successful, error otherwise.
  */
 int __kprobe_event_gen_cmd_start(struct dynevent_cmd *cmd, bool kretprobe,
@@ -953,6 +956,9 @@ int __kprobe_event_gen_cmd_start(struct dynevent_cmd *cmd, bool kretprobe,
        if (cmd->type != DYNEVENT_TYPE_KPROBE)
                return -EINVAL;
 
+       if (!loc)
+               return -EINVAL;
+
        if (kretprobe)
                snprintf(buf, MAX_EVENT_NAME_LEN, "r:kprobes/%s", name);
        else
index 9e31bfc818ff821dae0f82e4f5c1048a149a9f20..74738c9856f164af0f7ed08cbaaf4d9b4041aff0 100644 (file)
@@ -283,7 +283,7 @@ int tracing_map_add_key_field(struct tracing_map *map,
        return idx;
 }
 
-void tracing_map_array_clear(struct tracing_map_array *a)
+static void tracing_map_array_clear(struct tracing_map_array *a)
 {
        unsigned int i;
 
@@ -294,7 +294,7 @@ void tracing_map_array_clear(struct tracing_map_array *a)
                memset(a->pages[i], 0, PAGE_SIZE);
 }
 
-void tracing_map_array_free(struct tracing_map_array *a)
+static void tracing_map_array_free(struct tracing_map_array *a)
 {
        unsigned int i;
 
@@ -316,7 +316,7 @@ void tracing_map_array_free(struct tracing_map_array *a)
        kfree(a);
 }
 
-struct tracing_map_array *tracing_map_array_alloc(unsigned int n_elts,
+static struct tracing_map_array *tracing_map_array_alloc(unsigned int n_elts,
                                                  unsigned int entry_size)
 {
        struct tracing_map_array *a;
index 7f255b5a8845aef24b048dfabaf07462b04c9fca..11bf5eea474c5c9b2450da07de4b443a74eab431 100644 (file)
@@ -544,6 +544,11 @@ EXPORT_SYMBOL_GPL(fork_usermode_blob);
  * Runs a user-space application.  The application is started
  * asynchronously if wait is not set, and runs as a child of system workqueues.
  * (ie. it runs with full root capabilities and optimized affinity).
+ *
+ * Note: successful return value does not guarantee the helper was called at
+ * all. You can't rely on sub_info->{init,cleanup} being called even for
+ * UMH_WAIT_* wait modes as STATIC_USERMODEHELPER_PATH="" turns all helpers
+ * into a successful no-op.
  */
 int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)
 {
index 50c1f5f08e6f17952295dd561e519299776423ae..21d9c5f6e7ec7552be6f46fa352a29394465e3cc 100644 (file)
@@ -242,6 +242,8 @@ config DEBUG_INFO_DWARF4
 config DEBUG_INFO_BTF
        bool "Generate BTF typeinfo"
        depends on DEBUG_INFO
+       depends on !DEBUG_INFO_SPLIT && !DEBUG_INFO_REDUCED
+       depends on !GCC_PLUGIN_RANDSTRUCT || COMPILE_TEST
        help
          Generate deduplicated BTF type information from DWARF debug info.
          Turning this on expects presence of pahole tool, which will convert
index 48469c95d78e6da6c0656502c6d11b1216cef3c9..929211039bacd0c0d4ccd2aa7af0a9c69744132f 100644 (file)
@@ -60,18 +60,15 @@ config UBSAN_SANITIZE_ALL
          Enabling this option will get kernel image size increased
          significantly.
 
-config UBSAN_NO_ALIGNMENT
-       bool "Disable checking of pointers alignment"
-       default y if HAVE_EFFICIENT_UNALIGNED_ACCESS
+config UBSAN_ALIGNMENT
+       bool "Enable checks for pointers alignment"
+       default !HAVE_EFFICIENT_UNALIGNED_ACCESS
+       depends on !X86 || !COMPILE_TEST
        help
-         This option disables the check of unaligned memory accesses.
-         This option should be used when building allmodconfig.
-         Disabling this option on architectures that support unaligned
+         This option enables the check of unaligned memory accesses.
+         Enabling this option on architectures that support unaligned
          accesses may produce a lot of false positives.
 
-config UBSAN_ALIGNMENT
-       def_bool !UBSAN_NO_ALIGNMENT
-
 config TEST_UBSAN
        tristate "Module for testing for undefined behavior detection"
        depends on m
index 7a6430a7fca0070e0aa5e305eeb662fc6425e683..ccb2ffad8dcfab9beef23f4f2345390c0edd6de1 100644 (file)
@@ -93,7 +93,7 @@ static void kunit_print_ok_not_ok(void *test_or_suite,
         * representation.
         */
        if (suite)
-               pr_info("%s %zd - %s",
+               pr_info("%s %zd - %s\n",
                        kunit_status_to_string(is_ok),
                        test_number, description);
        else
index 2dceaca27489c0666abf928b4f829bfbd38fc9fa..891e1c3549c465a6d18e86e79437b5bdb3aca824 100644 (file)
@@ -722,22 +722,22 @@ do {                                                                      \
 do { \
        if (__builtin_constant_p(bh) && (bh) == 0) \
                __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \
-               : "=r" ((USItype)(sh)), \
-               "=&r" ((USItype)(sl)) \
+               : "=r" (sh), \
+               "=&r" (sl) \
                : "%r" ((USItype)(ah)), \
                "%r" ((USItype)(al)), \
                "rI" ((USItype)(bl))); \
        else if (__builtin_constant_p(bh) && (bh) == ~(USItype) 0) \
                __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \
-               : "=r" ((USItype)(sh)), \
-               "=&r" ((USItype)(sl)) \
+               : "=r" (sh), \
+               "=&r" (sl) \
                : "%r" ((USItype)(ah)), \
                "%r" ((USItype)(al)), \
                "rI" ((USItype)(bl))); \
        else \
                __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \
-               : "=r" ((USItype)(sh)), \
-               "=&r" ((USItype)(sl)) \
+               : "=r" (sh), \
+               "=&r" (sl) \
                : "%r" ((USItype)(ah)), \
                "r" ((USItype)(bh)), \
                "%r" ((USItype)(al)), \
@@ -747,36 +747,36 @@ do { \
 do { \
        if (__builtin_constant_p(ah) && (ah) == 0) \
                __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
-               : "=r" ((USItype)(sh)), \
-               "=&r" ((USItype)(sl)) \
+               : "=r" (sh), \
+               "=&r" (sl) \
                : "r" ((USItype)(bh)), \
                "rI" ((USItype)(al)), \
                "r" ((USItype)(bl))); \
        else if (__builtin_constant_p(ah) && (ah) == ~(USItype) 0) \
                __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
-               : "=r" ((USItype)(sh)), \
-               "=&r" ((USItype)(sl)) \
+               : "=r" (sh), \
+               "=&r" (sl) \
                : "r" ((USItype)(bh)), \
                "rI" ((USItype)(al)), \
                "r" ((USItype)(bl))); \
        else if (__builtin_constant_p(bh) && (bh) == 0) \
                __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
-               : "=r" ((USItype)(sh)), \
-               "=&r" ((USItype)(sl)) \
+               : "=r" (sh), \
+               "=&r" (sl) \
                : "r" ((USItype)(ah)), \
                "rI" ((USItype)(al)), \
                "r" ((USItype)(bl))); \
        else if (__builtin_constant_p(bh) && (bh) == ~(USItype) 0) \
                __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
-               : "=r" ((USItype)(sh)), \
-               "=&r" ((USItype)(sl)) \
+               : "=r" (sh), \
+               "=&r" (sl) \
                : "r" ((USItype)(ah)), \
                "rI" ((USItype)(al)), \
                "r" ((USItype)(bl))); \
        else \
                __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
-               : "=r" ((USItype)(sh)), \
-               "=&r" ((USItype)(sl)) \
+               : "=r" (sh), \
+               "=&r" (sl) \
                : "r" ((USItype)(ah)), \
                "r" ((USItype)(bh)), \
                "rI" ((USItype)(al)), \
@@ -787,7 +787,7 @@ do { \
 do { \
        USItype __m0 = (m0), __m1 = (m1); \
        __asm__ ("mulhwu %0,%1,%2" \
-       : "=r" ((USItype) ph) \
+       : "=r" (ph) \
        : "%r" (__m0), \
        "r" (__m1)); \
        (pl) = __m0 * __m1; \
index c81b4f3a7268458335635a6a01d93f09ba5469f4..efc5b83acd2df59499f80c450e2db3b6f2c176a5 100644 (file)
@@ -21,7 +21,7 @@ struct backing_dev_info noop_backing_dev_info = {
 EXPORT_SYMBOL_GPL(noop_backing_dev_info);
 
 static struct class *bdi_class;
-const char *bdi_unknown_name = "(unknown)";
+static const char *bdi_unknown_name = "(unknown)";
 
 /*
  * bdi_lock protects bdi_tree and updates to bdi_list. bdi_list has RCU
@@ -938,7 +938,8 @@ int bdi_register_va(struct backing_dev_info *bdi, const char *fmt, va_list args)
        if (bdi->dev)   /* The driver needs to use separate queues per device */
                return 0;
 
-       dev = device_create_vargs(bdi_class, NULL, MKDEV(0, 0), bdi, fmt, args);
+       vsnprintf(bdi->dev_name, sizeof(bdi->dev_name), fmt, args);
+       dev = device_create(bdi_class, NULL, MKDEV(0, 0), bdi, bdi->dev_name);
        if (IS_ERR(dev))
                return PTR_ERR(dev);
 
@@ -1043,6 +1044,14 @@ void bdi_put(struct backing_dev_info *bdi)
 }
 EXPORT_SYMBOL(bdi_put);
 
+const char *bdi_dev_name(struct backing_dev_info *bdi)
+{
+       if (!bdi || !bdi->dev)
+               return bdi_unknown_name;
+       return bdi->dev_name;
+}
+EXPORT_SYMBOL_GPL(bdi_dev_name);
+
 static wait_queue_head_t congestion_wqh[2] = {
                __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]),
                __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1])
index 6076df8e04a4e74dbb1405aa0e28ec9c72b59c4b..50681f0286ded05c26c0dc98660e4df5cd1ebecc 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1088,7 +1088,7 @@ retry:
                 * potentially allocating memory.
                 */
                if (fatal_signal_pending(current)) {
-                       ret = -ERESTARTSYS;
+                       ret = -EINTR;
                        goto out;
                }
                cond_resched();
index cd459155d28a7ac1b8a7517ffd53c1992a329f68..bcabbe02192b1c8471b789adb77f333babc85110 100644 (file)
@@ -5365,8 +5365,8 @@ pte_t *huge_pte_offset(struct mm_struct *mm,
 {
        pgd_t *pgd;
        p4d_t *p4d;
-       pud_t *pud;
-       pmd_t *pmd;
+       pud_t *pud, pud_entry;
+       pmd_t *pmd, pmd_entry;
 
        pgd = pgd_offset(mm, addr);
        if (!pgd_present(*pgd))
@@ -5376,17 +5376,19 @@ pte_t *huge_pte_offset(struct mm_struct *mm,
                return NULL;
 
        pud = pud_offset(p4d, addr);
-       if (sz != PUD_SIZE && pud_none(*pud))
+       pud_entry = READ_ONCE(*pud);
+       if (sz != PUD_SIZE && pud_none(pud_entry))
                return NULL;
        /* hugepage or swap? */
-       if (pud_huge(*pud) || !pud_present(*pud))
+       if (pud_huge(pud_entry) || !pud_present(pud_entry))
                return (pte_t *)pud;
 
        pmd = pmd_offset(pud, addr);
-       if (sz != PMD_SIZE && pmd_none(*pmd))
+       pmd_entry = READ_ONCE(*pmd);
+       if (sz != PMD_SIZE && pmd_none(pmd_entry))
                return NULL;
        /* hugepage or swap? */
-       if (pmd_huge(*pmd) || !pmd_present(*pmd))
+       if (pmd_huge(pmd_entry) || !pmd_present(pmd_entry))
                return (pte_t *)pmd;
 
        return NULL;
index a558da9e717709e60cb31ab62a2ce9deebcb095c..281c00129a2ea7487b87d5e2642b8fdc4b82c929 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -2112,8 +2112,16 @@ static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item)
 
                down_read(&mm->mmap_sem);
                vma = find_mergeable_vma(mm, rmap_item->address);
-               err = try_to_merge_one_page(vma, page,
-                                           ZERO_PAGE(rmap_item->address));
+               if (vma) {
+                       err = try_to_merge_one_page(vma, page,
+                                       ZERO_PAGE(rmap_item->address));
+               } else {
+                       /*
+                        * If the vma is out of date, we do not need to
+                        * continue.
+                        */
+                       err = 0;
+               }
                up_read(&mm->mmap_sem);
                /*
                 * In case of failure, the page was not really empty, so we
index 4bb30ed6c8d216cdc6bff02ef2b89d0331479f09..8cbd8c1bfe159e1c8df447660f5c6edfa1366d6d 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/swapops.h>
 #include <linux/shmem_fs.h>
 #include <linux/mmu_notifier.h>
+#include <linux/sched/mm.h>
 
 #include <asm/tlb.h>
 
@@ -1090,6 +1091,23 @@ int do_madvise(unsigned long start, size_t len_in, int behavior)
        if (write) {
                if (down_write_killable(&current->mm->mmap_sem))
                        return -EINTR;
+
+               /*
+                * We may have stolen the mm from another process
+                * that is undergoing core dumping.
+                *
+                * Right now that's io_ring, in the future it may
+                * be remote process management and not "current"
+                * at all.
+                *
+                * We need to fix core dumping to not do this,
+                * but for now we have the mmget_still_valid()
+                * model.
+                */
+               if (!mmget_still_valid(current->mm)) {
+                       up_write(&current->mm->mmap_sem);
+                       return -EINTR;
+               }
        } else {
                down_read(&current->mm->mmap_sem);
        }
index 5beea03dd58ad872d679376ee2b9f82cbe68f0fb..a3b97f10396654b18faa4642dafc4975507da45b 100644 (file)
@@ -4990,19 +4990,22 @@ static struct mem_cgroup *mem_cgroup_alloc(void)
        unsigned int size;
        int node;
        int __maybe_unused i;
+       long error = -ENOMEM;
 
        size = sizeof(struct mem_cgroup);
        size += nr_node_ids * sizeof(struct mem_cgroup_per_node *);
 
        memcg = kzalloc(size, GFP_KERNEL);
        if (!memcg)
-               return NULL;
+               return ERR_PTR(error);
 
        memcg->id.id = idr_alloc(&mem_cgroup_idr, NULL,
                                 1, MEM_CGROUP_ID_MAX,
                                 GFP_KERNEL);
-       if (memcg->id.id < 0)
+       if (memcg->id.id < 0) {
+               error = memcg->id.id;
                goto fail;
+       }
 
        memcg->vmstats_local = alloc_percpu(struct memcg_vmstats_percpu);
        if (!memcg->vmstats_local)
@@ -5046,7 +5049,7 @@ static struct mem_cgroup *mem_cgroup_alloc(void)
 fail:
        mem_cgroup_id_remove(memcg);
        __mem_cgroup_free(memcg);
-       return NULL;
+       return ERR_PTR(error);
 }
 
 static struct cgroup_subsys_state * __ref
@@ -5057,8 +5060,8 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
        long error = -ENOMEM;
 
        memcg = mem_cgroup_alloc();
-       if (!memcg)
-               return ERR_PTR(error);
+       if (IS_ERR(memcg))
+               return ERR_CAST(memcg);
 
        WRITE_ONCE(memcg->high, PAGE_COUNTER_MAX);
        memcg->soft_limit = PAGE_COUNTER_MAX;
@@ -5108,7 +5111,7 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
 fail:
        mem_cgroup_id_remove(memcg);
        mem_cgroup_free(memcg);
-       return ERR_PTR(-ENOMEM);
+       return ERR_PTR(error);
 }
 
 static int mem_cgroup_css_online(struct cgroup_subsys_state *css)
index a7e282ead43800031af363affaf39ac65ff0b307..c881abeba0bf2429fbb7bdbd990b46dbcd9b4531 100644 (file)
@@ -413,9 +413,20 @@ static unsigned long move_vma(struct vm_area_struct *vma,
                        /* Always put back VM_ACCOUNT since we won't unmap */
                        vma->vm_flags |= VM_ACCOUNT;
 
-                       vm_acct_memory(vma_pages(new_vma));
+                       vm_acct_memory(new_len >> PAGE_SHIFT);
                }
 
+               /*
+                * VMAs can actually be merged back together in copy_vma
+                * calling merge_vma. This can happen with anonymous vmas
+                * which have not yet been faulted, so if we were to consider
+                * this VMA split we'll end up adding VM_ACCOUNT on the
+                * next VMA, which is completely unrelated if this VMA
+                * was re-merged.
+                */
+               if (split && new_vma == vma)
+                       split = 0;
+
                /* We always clear VM_LOCKED[ONFAULT] on the old vma */
                vma->vm_flags &= VM_LOCKED_CLEAR_MASK;
 
index 69827d4fa0527dc1dbacdc1b0af711df0929d89f..13cc653122b73278afaeb6054539c619b164d11a 100644 (file)
@@ -1607,6 +1607,7 @@ void set_zone_contiguous(struct zone *zone)
                if (!__pageblock_pfn_to_page(block_start_pfn,
                                             block_end_pfn, zone))
                        return;
+               cond_resched();
        }
 
        /* We confirm that there is no hole */
@@ -2400,6 +2401,14 @@ static inline void boost_watermark(struct zone *zone)
 
        if (!watermark_boost_factor)
                return;
+       /*
+        * Don't bother in zones that are unlikely to produce results.
+        * On small machines, including kdump capture kernels running
+        * in a small area, boosting the watermark can cause an out of
+        * memory situation immediately.
+        */
+       if ((pageblock_nr_pages * 4) > zone_managed_pages(zone))
+               return;
 
        max_boost = mult_frac(zone->_watermark[WMARK_HIGH],
                        watermark_boost_factor, 10000);
index d7e3bc649f4eb8e784c3406e22c6bf237d79ebde..7da7d7737dab3ddcdb14ee55e61b934c28bf8291 100644 (file)
@@ -80,6 +80,7 @@
 #include <linux/workqueue.h>
 #include <linux/kmemleak.h>
 #include <linux/sched.h>
+#include <linux/sched/mm.h>
 
 #include <asm/cacheflush.h>
 #include <asm/sections.h>
@@ -1557,10 +1558,9 @@ static struct pcpu_chunk *pcpu_chunk_addr_search(void *addr)
 static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved,
                                 gfp_t gfp)
 {
-       /* whitelisted flags that can be passed to the backing allocators */
-       gfp_t pcpu_gfp = gfp & (GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
-       bool is_atomic = (gfp & GFP_KERNEL) != GFP_KERNEL;
-       bool do_warn = !(gfp & __GFP_NOWARN);
+       gfp_t pcpu_gfp;
+       bool is_atomic;
+       bool do_warn;
        static int warn_limit = 10;
        struct pcpu_chunk *chunk, *next;
        const char *err;
@@ -1569,6 +1569,12 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved,
        void __percpu *ptr;
        size_t bits, bit_align;
 
+       gfp = current_gfp_context(gfp);
+       /* whitelisted flags that can be passed to the backing allocators */
+       pcpu_gfp = gfp & (GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
+       is_atomic = (gfp & GFP_KERNEL) != GFP_KERNEL;
+       do_warn = !(gfp & __GFP_NOWARN);
+
        /*
         * There is now a minimum allocation size of PCPU_MIN_ALLOC_SIZE,
         * therefore alignment must be a minimum of that many bytes.
index d722eb830317022d0b18392cdd7e61bc2d52195e..bd8840082c941647cc77113dd8ec30d7a6beff46 100644 (file)
@@ -952,7 +952,7 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend,
                                VM_BUG_ON_PAGE(PageWriteback(page), page);
                                if (shmem_punch_compound(page, start, end))
                                        truncate_inode_page(mapping, page);
-                               else {
+                               else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
                                        /* Wipe the page and don't get stuck */
                                        clear_highpage(page);
                                        flush_dcache_page(page);
@@ -2179,7 +2179,11 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user)
        struct shmem_inode_info *info = SHMEM_I(inode);
        int retval = -ENOMEM;
 
-       spin_lock_irq(&info->lock);
+       /*
+        * What serializes the accesses to info->flags?
+        * ipc_lock_object() when called from shmctl_do_lock(),
+        * no serialization needed when called from shm_destroy().
+        */
        if (lock && !(info->flags & VM_LOCKED)) {
                if (!user_shm_lock(inode->i_size, user))
                        goto out_nomem;
@@ -2194,7 +2198,6 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user)
        retval = 0;
 
 out_nomem:
-       spin_unlock_irq(&info->lock);
        return retval;
 }
 
@@ -2399,11 +2402,11 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
 
        lru_cache_add_anon(page);
 
-       spin_lock(&info->lock);
+       spin_lock_irq(&info->lock);
        info->alloced++;
        inode->i_blocks += BLOCKS_PER_PAGE;
        shmem_recalc_inode(inode);
-       spin_unlock(&info->lock);
+       spin_unlock_irq(&info->lock);
 
        inc_mm_counter(dst_mm, mm_counter_file(page));
        page_add_file_rmap(page, false);
index 332d4b459a907b6a25e8fef7452e26c61604c2ea..b762450fc9f076841a410e8b51067d54beb569a6 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -551,15 +551,32 @@ static void print_section(char *level, char *text, u8 *addr,
        metadata_access_disable();
 }
 
+/*
+ * See comment in calculate_sizes().
+ */
+static inline bool freeptr_outside_object(struct kmem_cache *s)
+{
+       return s->offset >= s->inuse;
+}
+
+/*
+ * Return offset of the end of info block which is inuse + free pointer if
+ * not overlapping with object.
+ */
+static inline unsigned int get_info_end(struct kmem_cache *s)
+{
+       if (freeptr_outside_object(s))
+               return s->inuse + sizeof(void *);
+       else
+               return s->inuse;
+}
+
 static struct track *get_track(struct kmem_cache *s, void *object,
        enum track_item alloc)
 {
        struct track *p;
 
-       if (s->offset)
-               p = object + s->offset + sizeof(void *);
-       else
-               p = object + s->inuse;
+       p = object + get_info_end(s);
 
        return p + alloc;
 }
@@ -686,10 +703,7 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
                print_section(KERN_ERR, "Redzone ", p + s->object_size,
                        s->inuse - s->object_size);
 
-       if (s->offset)
-               off = s->offset + sizeof(void *);
-       else
-               off = s->inuse;
+       off = get_info_end(s);
 
        if (s->flags & SLAB_STORE_USER)
                off += 2 * sizeof(struct track);
@@ -782,7 +796,7 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
  * object address
  *     Bytes of the object to be managed.
  *     If the freepointer may overlay the object then the free
- *     pointer is the first word of the object.
+ *     pointer is at the middle of the object.
  *
  *     Poisoning uses 0x6b (POISON_FREE) and the last byte is
  *     0xa5 (POISON_END)
@@ -816,11 +830,7 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
 
 static int check_pad_bytes(struct kmem_cache *s, struct page *page, u8 *p)
 {
-       unsigned long off = s->inuse;   /* The end of info */
-
-       if (s->offset)
-               /* Freepointer is placed after the object. */
-               off += sizeof(void *);
+       unsigned long off = get_info_end(s);    /* The end of info */
 
        if (s->flags & SLAB_STORE_USER)
                /* We also have user information there */
@@ -907,7 +917,7 @@ static int check_object(struct kmem_cache *s, struct page *page,
                check_pad_bytes(s, page, p);
        }
 
-       if (!s->offset && val == SLUB_RED_ACTIVE)
+       if (!freeptr_outside_object(s) && val == SLUB_RED_ACTIVE)
                /*
                 * Object and freepointer overlap. Cannot check
                 * freepointer while object is allocated.
@@ -3533,6 +3543,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
 {
        slab_flags_t flags = s->flags;
        unsigned int size = s->object_size;
+       unsigned int freepointer_area;
        unsigned int order;
 
        /*
@@ -3541,6 +3552,13 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
         * the possible location of the free pointer.
         */
        size = ALIGN(size, sizeof(void *));
+       /*
+        * This is the area of the object where a freepointer can be
+        * safely written. If redzoning adds more to the inuse size, we
+        * can't use that portion for writing the freepointer, so
+        * s->offset must be limited within this for the general case.
+        */
+       freepointer_area = size;
 
 #ifdef CONFIG_SLUB_DEBUG
        /*
@@ -3579,16 +3597,21 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
                 *
                 * This is the case if we do RCU, have a constructor or
                 * destructor or are poisoning the objects.
+                *
+                * The assumption that s->offset >= s->inuse means free
+                * pointer is outside of the object is used in the
+                * freeptr_outside_object() function. If that is no
+                * longer true, the function needs to be modified.
                 */
                s->offset = size;
                size += sizeof(void *);
-       } else if (size > sizeof(void *)) {
+       } else if (freepointer_area > sizeof(void *)) {
                /*
                 * Store freelist pointer near middle of object to keep
                 * it away from the edges of the object to avoid small
                 * sized over/underflows from neighboring allocations.
                 */
-               s->offset = ALIGN(size / 2, sizeof(void *));
+               s->offset = ALIGN(freepointer_area / 2, sizeof(void *));
        }
 
 #ifdef CONFIG_SLUB_DEBUG
index 399f219544f74eb45ba2766250b45b9cdbeb971a..9a8227afa0738ffa87d3604a28788141d1abdc9a 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/llist.h>
 #include <linux/bitops.h>
 #include <linux/rbtree_augmented.h>
+#include <linux/overflow.h>
 
 #include <linux/uaccess.h>
 #include <asm/tlbflush.h>
@@ -3054,6 +3055,7 @@ finished:
  * @vma:               vma to cover
  * @uaddr:             target user address to start at
  * @kaddr:             virtual address of vmalloc kernel memory
+ * @pgoff:             offset from @kaddr to start at
  * @size:              size of map area
  *
  * Returns:    0 for success, -Exxx on failure
@@ -3066,9 +3068,15 @@ finished:
  * Similar to remap_pfn_range() (see mm/memory.c)
  */
 int remap_vmalloc_range_partial(struct vm_area_struct *vma, unsigned long uaddr,
-                               void *kaddr, unsigned long size)
+                               void *kaddr, unsigned long pgoff,
+                               unsigned long size)
 {
        struct vm_struct *area;
+       unsigned long off;
+       unsigned long end_index;
+
+       if (check_shl_overflow(pgoff, PAGE_SHIFT, &off))
+               return -EINVAL;
 
        size = PAGE_ALIGN(size);
 
@@ -3082,8 +3090,10 @@ int remap_vmalloc_range_partial(struct vm_area_struct *vma, unsigned long uaddr,
        if (!(area->flags & (VM_USERMAP | VM_DMA_COHERENT)))
                return -EINVAL;
 
-       if (kaddr + size > area->addr + get_vm_area_size(area))
+       if (check_add_overflow(size, off, &end_index) ||
+           end_index > get_vm_area_size(area))
                return -EINVAL;
+       kaddr += off;
 
        do {
                struct page *page = vmalloc_to_page(kaddr);
@@ -3122,7 +3132,7 @@ int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
                                                unsigned long pgoff)
 {
        return remap_vmalloc_range_partial(vma, vma->vm_start,
-                                          addr + (pgoff << PAGE_SHIFT),
+                                          addr, pgoff,
                                           vma->vm_end - vma->vm_start);
 }
 EXPORT_SYMBOL(remap_vmalloc_range);
index b06868fc492659a7038eed45a420d3dec391f5d0..a37c87b5aee2f3c038da7920ef8df6ee7de415d2 100644 (file)
@@ -1625,7 +1625,6 @@ static __always_inline void update_lru_sizes(struct lruvec *lruvec,
  * @dst:       The temp list to put pages on to.
  * @nr_scanned:        The number of pages that were scanned.
  * @sc:                The scan_control struct for this reclaim session
- * @mode:      One of the LRU isolation modes
  * @lru:       LRU list id for isolating
  *
  * returns how many pages were moved onto *@dst.
index 0ce530af534ddfed26a32b1b24f202ee7c582198..8575f5d52087d3f64f477e59edac2aa4e261ca9c 100644 (file)
@@ -177,18 +177,18 @@ static void vcc_destroy_socket(struct sock *sk)
 
        set_bit(ATM_VF_CLOSE, &vcc->flags);
        clear_bit(ATM_VF_READY, &vcc->flags);
-       if (vcc->dev) {
-               if (vcc->dev->ops->close)
-                       vcc->dev->ops->close(vcc);
-               if (vcc->push)
-                       vcc->push(vcc, NULL); /* atmarpd has no push */
-               module_put(vcc->owner);
-
-               while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
-                       atm_return(vcc, skb->truesize);
-                       kfree_skb(skb);
-               }
+       if (vcc->dev && vcc->dev->ops->close)
+               vcc->dev->ops->close(vcc);
+       if (vcc->push)
+               vcc->push(vcc, NULL); /* atmarpd has no push */
+       module_put(vcc->owner);
+
+       while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+               atm_return(vcc, skb->truesize);
+               kfree_skb(skb);
+       }
 
+       if (vcc->dev && vcc->dev->ops->owner) {
                module_put(vcc->dev->ops->owner);
                atm_dev_put(vcc->dev);
        }
index 25fa3a7b72bda7f6610db69b421485a9b6db8e8c..ca37f5a71f5e9e44459cbbd6fa2825f7736b9cc0 100644 (file)
@@ -1264,6 +1264,12 @@ static void lec_arp_clear_vccs(struct lec_arp_table *entry)
                entry->vcc = NULL;
        }
        if (entry->recv_vcc) {
+               struct atm_vcc *vcc = entry->recv_vcc;
+               struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
+
+               kfree(vpriv);
+               vcc->user_back = NULL;
+
                entry->recv_vcc->push = entry->old_recv_push;
                vcc_release_async(entry->recv_vcc, -EPIPE);
                entry->recv_vcc = NULL;
index 9694662189992394fc07858ce61285e939ea8755..80b87b1f4e3a89ce52e97ed7117e5e4026f8dea3 100644 (file)
@@ -893,7 +893,7 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset,
 
        orig_node = batadv_v_ogm_orig_get(bat_priv, ogm_packet->orig);
        if (!orig_node)
-               return;
+               goto out;
 
        neigh_node = batadv_neigh_node_get_or_create(orig_node, if_incoming,
                                                     ethhdr->h_source);
index 8f0717c3f7b545d53efc60f3bbbf4847d478a54e..b0469d15da0e9081084959090d00f19256d24594 100644 (file)
@@ -1009,15 +1009,8 @@ static struct batadv_nc_path *batadv_nc_get_path(struct batadv_priv *bat_priv,
  */
 static u8 batadv_nc_random_weight_tq(u8 tq)
 {
-       u8 rand_val, rand_tq;
-
-       get_random_bytes(&rand_val, sizeof(rand_val));
-
        /* randomize the estimated packet loss (max TQ - estimated TQ) */
-       rand_tq = rand_val * (BATADV_TQ_MAX_VALUE - tq);
-
-       /* normalize the randomized packet loss */
-       rand_tq /= BATADV_TQ_MAX_VALUE;
+       u8 rand_tq = prandom_u32_max(BATADV_TQ_MAX_VALUE + 1 - tq);
 
        /* convert to (randomized) estimated tq again */
        return BATADV_TQ_MAX_VALUE - rand_tq;
index c45962d8527bebf80c1e4e709784d139f7fe0a5d..0f962dcd239e64139832850a4f749313f38c6ad0 100644 (file)
@@ -1150,7 +1150,7 @@ static ssize_t batadv_store_throughput_override(struct kobject *kobj,
        ret = batadv_parse_throughput(net_dev, buff, "throughput_override",
                                      &tp_override);
        if (!ret)
-               return count;
+               goto out;
 
        old_tp_override = atomic_read(&hard_iface->bat_v.throughput_override);
        if (old_tp_override == tp_override)
@@ -1190,6 +1190,7 @@ static ssize_t batadv_show_throughput_override(struct kobject *kobj,
 
        tp_override = atomic_read(&hard_iface->bat_v.throughput_override);
 
+       batadv_hardif_put(hard_iface);
        return sprintf(buff, "%u.%u MBit\n", tp_override / 10,
                       tp_override % 10);
 }
index 43dab4066f915bddcdcdc3dafc0d07fa7d50e01f..a0f5dbee8f9cb99a60ee6291757eb0f4a967a7ff 100644 (file)
@@ -612,6 +612,7 @@ int br_process_vlan_info(struct net_bridge *br,
                                               v - 1, rtm_cmd);
                                v_change_start = 0;
                        }
+                       cond_resched();
                }
                /* v_change_start is set only if the last/whole range changed */
                if (v_change_start)
index 9c9e763bfe0e38ff843fa590ff83617a8d2feacc..522288177bbd8ce00d2152c218d7eef6fbcd82ab 100644 (file)
@@ -4140,7 +4140,8 @@ EXPORT_SYMBOL(netdev_max_backlog);
 
 int netdev_tstamp_prequeue __read_mostly = 1;
 int netdev_budget __read_mostly = 300;
-unsigned int __read_mostly netdev_budget_usecs = 2000;
+/* Must be at least 2 jiffes to guarantee 1 jiffy timeout */
+unsigned int __read_mostly netdev_budget_usecs = 2 * USEC_PER_SEC / HZ;
 int weight_p __read_mostly = 64;           /* old backlog weight */
 int dev_weight_rx_bias __read_mostly = 1;  /* bias for backlog weight */
 int dev_weight_tx_bias __read_mostly = 1;  /* bias for output_queue quota */
@@ -8666,8 +8667,8 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
        const struct net_device_ops *ops = dev->netdev_ops;
        enum bpf_netdev_command query;
        u32 prog_id, expected_id = 0;
-       struct bpf_prog *prog = NULL;
        bpf_op_t bpf_op, bpf_chk;
+       struct bpf_prog *prog;
        bool offload;
        int err;
 
@@ -8733,6 +8734,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
        } else {
                if (!prog_id)
                        return 0;
+               prog = NULL;
        }
 
        err = dev_xdp_install(dev, bpf_op, extack, flags, prog);
index 80f97722f31f0d4de8b00048e0c3b6574b0986b9..899edcee7dab02e1d20a2db971f566b88c547d67 100644 (file)
@@ -4283,6 +4283,11 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
                end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
                end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
                dump = false;
+
+               if (start_offset == end_offset) {
+                       err = 0;
+                       goto nla_put_failure;
+               }
        }
 
        err = devlink_nl_region_read_snapshot_fill(skb, devlink,
@@ -5363,6 +5368,7 @@ int devlink_health_report(struct devlink_health_reporter *reporter,
 {
        enum devlink_health_reporter_state prev_health_state;
        struct devlink *devlink = reporter->devlink;
+       unsigned long recover_ts_threshold;
 
        /* write a log message of the current error */
        WARN_ON(!msg);
@@ -5373,10 +5379,12 @@ int devlink_health_report(struct devlink_health_reporter *reporter,
        devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
 
        /* abort if the previous error wasn't recovered */
+       recover_ts_threshold = reporter->last_recovery_ts +
+                              msecs_to_jiffies(reporter->graceful_period);
        if (reporter->auto_recover &&
            (prev_health_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY ||
-            jiffies - reporter->last_recovery_ts <
-            msecs_to_jiffies(reporter->graceful_period))) {
+            (reporter->last_recovery_ts && reporter->recovery_count &&
+             time_is_after_jiffies(recover_ts_threshold)))) {
                trace_devlink_health_recover_aborted(devlink,
                                                     reporter->ops->name,
                                                     reporter->health_state,
index 8e33cec9fc4ef8e3803ddc3457998c05d77f211d..2ee7bc4c9e03fe220171ba6eb6866ced3dd5669e 100644 (file)
@@ -213,6 +213,7 @@ static void sched_send_work(struct timer_list *t)
 static void trace_drop_common(struct sk_buff *skb, void *location)
 {
        struct net_dm_alert_msg *msg;
+       struct net_dm_drop_point *point;
        struct nlmsghdr *nlh;
        struct nlattr *nla;
        int i;
@@ -231,11 +232,13 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
        nlh = (struct nlmsghdr *)dskb->data;
        nla = genlmsg_data(nlmsg_data(nlh));
        msg = nla_data(nla);
+       point = msg->points;
        for (i = 0; i < msg->entries; i++) {
-               if (!memcmp(&location, msg->points[i].pc, sizeof(void *))) {
-                       msg->points[i].count++;
+               if (!memcmp(&location, &point->pc, sizeof(void *))) {
+                       point->count++;
                        goto out;
                }
+               point++;
        }
        if (msg->entries == dm_hit_limit)
                goto out;
@@ -244,8 +247,8 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
         */
        __nla_reserve_nohdr(dskb, sizeof(struct net_dm_drop_point));
        nla->nla_len += NLA_ALIGN(sizeof(struct net_dm_drop_point));
-       memcpy(msg->points[msg->entries].pc, &location, sizeof(void *));
-       msg->points[msg->entries].count = 1;
+       memcpy(point->pc, &location, sizeof(void *));
+       point->count = 1;
        msg->entries++;
 
        if (!timer_pending(&data->send_timer)) {
index 7628b947dbc3aabd289fd6f282c82a7faf8e3256..7d6ceaa54d2147584e2033956c4740e4d0ef4af1 100644 (file)
@@ -5925,7 +5925,7 @@ BPF_CALL_3(bpf_sk_assign, struct sk_buff *, skb, struct sock *, sk, u64, flags)
                return -EOPNOTSUPP;
        if (unlikely(dev_net(skb->dev) != sock_net(sk)))
                return -ENETUNREACH;
-       if (unlikely(sk->sk_reuseport))
+       if (unlikely(sk_fullsock(sk) && sk->sk_reuseport))
                return -ESOCKTNOSUPPORT;
        if (sk_is_refcounted(sk) &&
            unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
index 39d37d0ef575bf38eb1219c476970ddab333a176..116139233d573c1b15969d4a9a9b1b08f2e930bb 100644 (file)
@@ -1956,6 +1956,9 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
                                   NEIGH_UPDATE_F_OVERRIDE_ISROUTER);
        }
 
+       if (protocol)
+               neigh->protocol = protocol;
+
        if (ndm->ndm_flags & NTF_EXT_LEARNED)
                flags |= NEIGH_UPDATE_F_EXT_LEARNED;
 
@@ -1969,9 +1972,6 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
                err = __neigh_update(neigh, lladdr, ndm->ndm_state, flags,
                                     NETLINK_CB(skb).portid, extack);
 
-       if (protocol)
-               neigh->protocol = protocol;
-
        neigh_release(neigh);
 
 out:
index cf0215734ceb07089b60911a269a53bc2f0f1913..4773ad6ec1114cd1dc364cc7470379289d7034db 100644 (file)
@@ -80,7 +80,7 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
        struct net_device *netdev = to_net_dev(dev);
        struct net *net = dev_net(netdev);
        unsigned long new;
-       int ret = -EINVAL;
+       int ret;
 
        if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                return -EPERM;
index b4c87fe31be2e860db70a9840ce88d8c82fe2efb..41b24cd31562addb9c6fa87cf87a282ceda62836 100644 (file)
@@ -127,10 +127,8 @@ static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft,
        cs->classid = (u32)value;
 
        css_task_iter_start(css, 0, &it);
-       while ((p = css_task_iter_next(&it))) {
+       while ((p = css_task_iter_next(&it)))
                update_classid_task(p, cs->classid);
-               cond_resched();
-       }
        css_task_iter_end(&it);
 
        return 0;
index ce1d8dce9b7aba7aa5a7e4b69c09bb6e889fb067..b714162213aeae98bfee24d8b457547fe7abab4f 100644 (file)
@@ -1872,7 +1872,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
                 * as not suitable for copying when cloning.
                 */
                if (sk_user_data_is_nocopy(newsk))
-                       RCU_INIT_POINTER(newsk->sk_user_data, NULL);
+                       newsk->sk_user_data = NULL;
 
                newsk->sk_err      = 0;
                newsk->sk_err_soft = 0;
@@ -2364,7 +2364,6 @@ static void sk_leave_memory_pressure(struct sock *sk)
        }
 }
 
-/* On 32bit arches, an skb frag is limited to 2^15 */
 #define SKB_FRAG_PAGE_ORDER    get_order(32768)
 DEFINE_STATIC_KEY_FALSE(net_high_order_alloc_disable_key);
 
index 9a271a58a41dcf8fa352284f2d23477038e269d2..d90665b465b8ab6ceb2f85750af9eef9dc87cac5 100644 (file)
@@ -459,7 +459,7 @@ static int dsa_tree_setup_switches(struct dsa_switch_tree *dst)
        list_for_each_entry(dp, &dst->ports, list) {
                err = dsa_port_setup(dp);
                if (err)
-                       goto teardown;
+                       continue;
        }
 
        return 0;
index b5c535af63a351182e55d46dd712826e97e9eab5..a621367c6e8c292997984534614b0caea1fa991a 100644 (file)
@@ -289,7 +289,8 @@ static void dsa_master_ndo_teardown(struct net_device *dev)
 {
        struct dsa_port *cpu_dp = dev->dsa_ptr;
 
-       dev->netdev_ops = cpu_dp->orig_ndo_ops;
+       if (cpu_dp->orig_ndo_ops)
+               dev->netdev_ops = cpu_dp->orig_ndo_ops;
        cpu_dp->orig_ndo_ops = NULL;
 }
 
index 231b2d494f1cb4f43985966b9a3c05e10f4dfb91..a58fdd3625743d5314aa57828019fc96b40cecc6 100644 (file)
@@ -670,11 +670,16 @@ int dsa_port_link_register_of(struct dsa_port *dp)
 {
        struct dsa_switch *ds = dp->ds;
        struct device_node *phy_np;
+       int port = dp->index;
 
        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)
+               if (of_phy_is_fixed_link(dp->dn) || phy_np) {
+                       if (ds->ops->phylink_mac_link_down)
+                               ds->ops->phylink_mac_link_down(ds, port,
+                                       MLO_AN_FIXED, PHY_INTERFACE_MODE_NA);
                        return dsa_port_phylink_register(dp);
+               }
                return 0;
        }
 
index e94eb1aac6029e41b65bd2c1ceb044992aec3a4a..62f4ee3da172a0489a183e3e9abd6f1439ad1481 100644 (file)
@@ -856,20 +856,18 @@ dsa_slave_add_cls_matchall_mirred(struct net_device *dev,
        struct dsa_port *to_dp;
        int err;
 
-       act = &cls->rule->action.entries[0];
-
        if (!ds->ops->port_mirror_add)
                return -EOPNOTSUPP;
 
-       if (!act->dev)
-               return -EINVAL;
-
        if (!flow_action_basic_hw_stats_check(&cls->rule->action,
                                              cls->common.extack))
                return -EOPNOTSUPP;
 
        act = &cls->rule->action.entries[0];
 
+       if (!act->dev)
+               return -EINVAL;
+
        if (!dsa_slave_dev_check(act->dev))
                return -EOPNOTSUPP;
 
@@ -1770,11 +1768,9 @@ int dsa_slave_create(struct dsa_port *port)
        rtnl_lock();
        ret = dsa_slave_change_mtu(slave_dev, ETH_DATA_LEN);
        rtnl_unlock();
-       if (ret && ret != -EOPNOTSUPP) {
-               dev_err(ds->dev, "error %d setting MTU on port %d\n",
-                       ret, port->index);
-               goto out_free;
-       }
+       if (ret)
+               dev_warn(ds->dev, "nonfatal error %d setting MTU on port %d\n",
+                        ret, port->index);
 
        netif_carrier_off(slave_dev);
 
index 5465a395da040f2a9e7e0ed57e9509d8c36470ec..1decb25f6764a63578ca0079cd81c487edcc54e1 100644 (file)
@@ -69,10 +69,16 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev,
        else
                multicast_spec = nla_get_u8(data[IFLA_HSR_MULTICAST_SPEC]);
 
-       if (!data[IFLA_HSR_VERSION])
+       if (!data[IFLA_HSR_VERSION]) {
                hsr_version = 0;
-       else
+       } else {
                hsr_version = nla_get_u8(data[IFLA_HSR_VERSION]);
+               if (hsr_version > 1) {
+                       NL_SET_ERR_MSG_MOD(extack,
+                                          "Only versions 0..1 are supported");
+                       return -EINVAL;
+               }
+       }
 
        return hsr_dev_finalize(dev, link, multicast_spec, hsr_version, extack);
 }
index f4b9f7a3ce5196850db57f3e287eb3ca198d5d9b..25b6ffba26cde9eb80f79d4853a735c0d250ef6b 100644 (file)
@@ -18,7 +18,7 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb)
 {
        struct sk_buff *skb = *pskb;
        struct hsr_port *port;
-       u16 protocol;
+       __be16 protocol;
 
        if (!skb_mac_header_was_set(skb)) {
                WARN_ONCE(1, "%s: skb invalid", __func__);
index 30fa42f5997dbc942b03d5b71a172b041b5238cf..c0dd561aa19032f8b6637d9b387e4fa404b31828 100644 (file)
@@ -614,12 +614,15 @@ struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
        return NULL;
 }
 
-static int ip_mc_config(struct sock *sk, bool join, const struct in_ifaddr *ifa)
+static int ip_mc_autojoin_config(struct net *net, bool join,
+                                const struct in_ifaddr *ifa)
 {
+#if defined(CONFIG_IP_MULTICAST)
        struct ip_mreqn mreq = {
                .imr_multiaddr.s_addr = ifa->ifa_address,
                .imr_ifindex = ifa->ifa_dev->dev->ifindex,
        };
+       struct sock *sk = net->ipv4.mc_autojoin_sk;
        int ret;
 
        ASSERT_RTNL();
@@ -632,6 +635,9 @@ static int ip_mc_config(struct sock *sk, bool join, const struct in_ifaddr *ifa)
        release_sock(sk);
 
        return ret;
+#else
+       return -EOPNOTSUPP;
+#endif
 }
 
 static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -675,7 +681,7 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
                        continue;
 
                if (ipv4_is_multicast(ifa->ifa_address))
-                       ip_mc_config(net->ipv4.mc_autojoin_sk, false, ifa);
+                       ip_mc_autojoin_config(net, false, ifa);
                __inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).portid);
                return 0;
        }
@@ -940,8 +946,7 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
                 */
                set_ifa_lifetime(ifa, valid_lft, prefered_lft);
                if (ifa->ifa_flags & IFA_F_MCAUTOJOIN) {
-                       int ret = ip_mc_config(net->ipv4.mc_autojoin_sk,
-                                              true, ifa);
+                       int ret = ip_mc_autojoin_config(net, true, ifa);
 
                        if (ret < 0) {
                                inet_free_ifa(ifa);
index 6ed8c931717942a814aa6c9a8cac5ebd7e626c0f..55ca2e5218280c7857c9bad9351858d38df1916d 100644 (file)
@@ -2014,7 +2014,7 @@ static void fib_select_default(const struct flowi4 *flp, struct fib_result *res)
 
        hlist_for_each_entry_rcu(fa, fa_head, fa_list) {
                struct fib_info *next_fi = fa->fa_info;
-               struct fib_nh *nh;
+               struct fib_nh_common *nhc;
 
                if (fa->fa_slen != slen)
                        continue;
@@ -2037,8 +2037,8 @@ static void fib_select_default(const struct flowi4 *flp, struct fib_result *res)
                    fa->fa_type != RTN_UNICAST)
                        continue;
 
-               nh = fib_info_nh(next_fi, 0);
-               if (!nh->fib_nh_gw4 || nh->fib_nh_scope != RT_SCOPE_LINK)
+               nhc = fib_info_nhc(next_fi, 0);
+               if (!nhc->nhc_gw_family || nhc->nhc_scope != RT_SCOPE_LINK)
                        continue;
 
                fib_alias_accessed(fa);
index bf4ced9273e8e84b95204db9bfe86867c0a3ee13..b996dc1069c53ead2e1f3552716a6cd427942afd 100644 (file)
@@ -3926,10 +3926,6 @@ void tcp_parse_options(const struct net *net,
                                 */
                                break;
 #endif
-                       case TCPOPT_MPTCP:
-                               mptcp_parse_option(skb, ptr, opsize, opt_rx);
-                               break;
-
                        case TCPOPT_FASTOPEN:
                                tcp_parse_fastopen_option(
                                        opsize - TCPOLEN_FASTOPEN_BASE,
@@ -5990,9 +5986,6 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
                tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
                tcp_initialize_rcv_mss(sk);
 
-               if (sk_is_mptcp(sk))
-                       mptcp_rcv_synsent(sk);
-
                /* Remember, tcp_poll() does not lock socket!
                 * Change state from SYN-SENT only after copied_seq
                 * is initialized. */
index 89ba7c87de5df35d8a3807f360fd9d3845fcfa20..30ddb9dc9398beaf8aa7da1a90409c5c2e76d9b6 100644 (file)
@@ -58,9 +58,7 @@ int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb)
 {
        memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
 
-#ifdef CONFIG_NETFILTER
        IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
-#endif
 
        return xfrm_output(sk, skb);
 }
index 2688f3e8216528a116f90f00d433a331ee0ae983..fc5000370030d67094ba11f15aaaaaa7ba519cde 100644 (file)
@@ -229,6 +229,25 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
        return res;
 }
 
+static bool icmpv6_rt_has_prefsrc(struct sock *sk, u8 type,
+                                 struct flowi6 *fl6)
+{
+       struct net *net = sock_net(sk);
+       struct dst_entry *dst;
+       bool res = false;
+
+       dst = ip6_route_output(net, sk, fl6);
+       if (!dst->error) {
+               struct rt6_info *rt = (struct rt6_info *)dst;
+               struct in6_addr prefsrc;
+
+               rt6_get_prefsrc(rt, &prefsrc);
+               res = !ipv6_addr_any(&prefsrc);
+       }
+       dst_release(dst);
+       return res;
+}
+
 /*
  *     an inline helper for the "simple" if statement below
  *     checks if parameter problem report is caused by an
@@ -527,7 +546,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
                saddr = force_saddr;
        if (saddr) {
                fl6.saddr = *saddr;
-       } else {
+       } else if (!icmpv6_rt_has_prefsrc(sk, type, &fl6)) {
                /* select a more meaningful saddr from input if */
                struct net_device *in_netdev;
 
index debdaeba5d8c130dbf7dd099bc29fbed80a7ac75..18d05403d3b52cc0e69c484c61f04d9f4a166457 100644 (file)
@@ -183,15 +183,14 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
                                        retv = -EBUSY;
                                        break;
                                }
-                       } else if (sk->sk_protocol == IPPROTO_TCP) {
-                               if (sk->sk_prot != &tcpv6_prot) {
-                                       retv = -EBUSY;
-                                       break;
-                               }
-                               break;
-                       } else {
+                       }
+                       if (sk->sk_protocol == IPPROTO_TCP &&
+                           sk->sk_prot != &tcpv6_prot) {
+                               retv = -EBUSY;
                                break;
                        }
+                       if (sk->sk_protocol != IPPROTO_TCP)
+                               break;
                        if (sk->sk_state != TCP_ESTABLISHED) {
                                retv = -ENOTCONN;
                                break;
index 310cbddaa533fcefc14c8fe3566afab494b64bc0..8d418038fe32914c2cd828ec4abd81ea0c26f26a 100644 (file)
@@ -1385,9 +1385,18 @@ static struct rt6_info *ip6_rt_pcpu_alloc(const struct fib6_result *res)
        }
        ip6_rt_copy_init(pcpu_rt, res);
        pcpu_rt->rt6i_flags |= RTF_PCPU;
+
+       if (f6i->nh)
+               pcpu_rt->sernum = rt_genid_ipv6(dev_net(dev));
+
        return pcpu_rt;
 }
 
+static bool rt6_is_valid(const struct rt6_info *rt6)
+{
+       return rt6->sernum == rt_genid_ipv6(dev_net(rt6->dst.dev));
+}
+
 /* It should be called with rcu_read_lock() acquired */
 static struct rt6_info *rt6_get_pcpu_route(const struct fib6_result *res)
 {
@@ -1395,6 +1404,19 @@ static struct rt6_info *rt6_get_pcpu_route(const struct fib6_result *res)
 
        pcpu_rt = this_cpu_read(*res->nh->rt6i_pcpu);
 
+       if (pcpu_rt && pcpu_rt->sernum && !rt6_is_valid(pcpu_rt)) {
+               struct rt6_info *prev, **p;
+
+               p = this_cpu_ptr(res->nh->rt6i_pcpu);
+               prev = xchg(p, NULL);
+               if (prev) {
+                       dst_dev_put(&prev->dst);
+                       dst_release(&prev->dst);
+               }
+
+               pcpu_rt = NULL;
+       }
+
        return pcpu_rt;
 }
 
@@ -2593,6 +2615,9 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
 
        rt = container_of(dst, struct rt6_info, dst);
 
+       if (rt->sernum)
+               return rt6_is_valid(rt) ? dst : NULL;
+
        rcu_read_lock();
 
        /* All IPV6 dsts are created with ->obsolete set to the value
index d38b476fc7f2b158c6e62e6f8829c7de1b5686bf..307f336b5353ef617d5ef9a2085cdea2f5276ba2 100644 (file)
@@ -8,6 +8,7 @@
 #include <net/rpl.h>
 
 #define IPV6_PFXTAIL_LEN(x) (sizeof(struct in6_addr) - (x))
+#define IPV6_RPL_BEST_ADDR_COMPRESSION 15
 
 static void ipv6_rpl_addr_decompress(struct in6_addr *dst,
                                     const struct in6_addr *daddr,
@@ -73,7 +74,7 @@ static unsigned char ipv6_rpl_srh_calc_cmpri(const struct ipv6_rpl_sr_hdr *inhdr
                }
        }
 
-       return plen;
+       return IPV6_RPL_BEST_ADDR_COMPRESSION;
 }
 
 static unsigned char ipv6_rpl_srh_calc_cmpre(const struct in6_addr *daddr,
@@ -83,10 +84,10 @@ static unsigned char ipv6_rpl_srh_calc_cmpre(const struct in6_addr *daddr,
 
        for (plen = 0; plen < sizeof(*daddr); plen++) {
                if (daddr->s6_addr[plen] != last_segment->s6_addr[plen])
-                       break;
+                       return plen;
        }
 
-       return plen;
+       return IPV6_RPL_BEST_ADDR_COMPRESSION;
 }
 
 void ipv6_rpl_srh_compress(struct ipv6_rpl_sr_hdr *outhdr,
index 75421a472d25ac4b2cf8df3959b1ea6ec7547827..37b434293bda3bb1986e4c0c09362473c11db179 100644 (file)
@@ -27,8 +27,9 @@
 
 bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len)
 {
-       int trailing;
        unsigned int tlv_offset;
+       int max_last_entry;
+       int trailing;
 
        if (srh->type != IPV6_SRCRT_TYPE_4)
                return false;
@@ -36,7 +37,12 @@ bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len)
        if (((srh->hdrlen + 1) << 3) != len)
                return false;
 
-       if (srh->segments_left > srh->first_segment)
+       max_last_entry = (srh->hdrlen / 2) - 1;
+
+       if (srh->first_segment > max_last_entry)
+               return false;
+
+       if (srh->segments_left > srh->first_segment + 1)
                return false;
 
        tlv_offset = sizeof(*srh) + ((srh->first_segment + 1) << 4);
@@ -434,7 +440,7 @@ static struct genl_family seg6_genl_family __ro_after_init = {
 
 int __init seg6_init(void)
 {
-       int err = -ENOMEM;
+       int err;
 
        err = genl_register_family(&seg6_genl_family);
        if (err)
index fbe51d40bd7e9f8b50bc3ba1c1d41710a162e29d..e34167f790e6795830ebe94b2872f5be4c6740a7 100644 (file)
@@ -111,9 +111,7 @@ int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb)
 {
        memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
 
-#ifdef CONFIG_NETFILTER
        IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
-#endif
 
        return xfrm_output(sk, skb);
 }
index f5a9bdc4980c5b25edf736aaa961269c5cd0c537..ebb381c3f1b9901cf302fc8b3052163eb9ab5504 100644 (file)
@@ -920,51 +920,51 @@ static const struct genl_ops l2tp_nl_ops[] = {
                .cmd = L2TP_CMD_TUNNEL_CREATE,
                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = l2tp_nl_cmd_tunnel_create,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
        },
        {
                .cmd = L2TP_CMD_TUNNEL_DELETE,
                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = l2tp_nl_cmd_tunnel_delete,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
        },
        {
                .cmd = L2TP_CMD_TUNNEL_MODIFY,
                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = l2tp_nl_cmd_tunnel_modify,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
        },
        {
                .cmd = L2TP_CMD_TUNNEL_GET,
                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = l2tp_nl_cmd_tunnel_get,
                .dumpit = l2tp_nl_cmd_tunnel_dump,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
        },
        {
                .cmd = L2TP_CMD_SESSION_CREATE,
                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = l2tp_nl_cmd_session_create,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
        },
        {
                .cmd = L2TP_CMD_SESSION_DELETE,
                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = l2tp_nl_cmd_session_delete,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
        },
        {
                .cmd = L2TP_CMD_SESSION_MODIFY,
                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = l2tp_nl_cmd_session_modify,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
        },
        {
                .cmd = L2TP_CMD_SESSION_GET,
                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = l2tp_nl_cmd_session_get,
                .dumpit = l2tp_nl_cmd_session_dump,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
        },
 };
 
index 8345926193de487c6f783b0a452ff0c74eba02c1..6423173bb87ed4bb0df0b17c59e09644cf2e0e56 100644 (file)
@@ -1069,7 +1069,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
                if (hw->max_signal <= 0) {
                        result = -EINVAL;
-                       goto fail_wiphy_register;
+                       goto fail_workqueue;
                }
        }
 
@@ -1135,7 +1135,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 
        result = ieee80211_init_cipher_suites(local);
        if (result < 0)
-               goto fail_wiphy_register;
+               goto fail_workqueue;
 
        if (!local->ops->remain_on_channel)
                local->hw.wiphy->max_remain_on_channel_duration = 5000;
@@ -1161,10 +1161,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 
        local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM;
 
-       result = wiphy_register(local->hw.wiphy);
-       if (result < 0)
-               goto fail_wiphy_register;
-
        /*
         * We use the number of queues for feature tests (QoS, HT) internally
         * so restrict them appropriately.
@@ -1187,8 +1183,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
                                   IEEE80211_TX_STATUS_HEADROOM);
 
-       debugfs_hw_add(local);
-
        /*
         * if the driver doesn't specify a max listen interval we
         * use 5 which should be a safe default
@@ -1217,9 +1211,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                goto fail_flows;
 
        rtnl_lock();
-
        result = ieee80211_init_rate_ctrl_alg(local,
                                              hw->rate_control_algorithm);
+       rtnl_unlock();
        if (result < 0) {
                wiphy_debug(local->hw.wiphy,
                            "Failed to initialize rate control algorithm\n");
@@ -1273,6 +1267,15 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                local->sband_allocated |= BIT(band);
        }
 
+       result = wiphy_register(local->hw.wiphy);
+       if (result < 0)
+               goto fail_wiphy_register;
+
+       debugfs_hw_add(local);
+       rate_control_add_debugfs(local);
+
+       rtnl_lock();
+
        /* add one default STA interface if supported */
        if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION) &&
            !ieee80211_hw_check(hw, NO_AUTO_VIF)) {
@@ -1312,17 +1315,17 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 #if defined(CONFIG_INET) || defined(CONFIG_IPV6)
  fail_ifa:
 #endif
+       wiphy_unregister(local->hw.wiphy);
+ fail_wiphy_register:
        rtnl_lock();
        rate_control_deinitialize(local);
        ieee80211_remove_interfaces(local);
- fail_rate:
        rtnl_unlock();
+ fail_rate:
  fail_flows:
        ieee80211_led_exit(local);
        destroy_workqueue(local->workqueue);
  fail_workqueue:
-       wiphy_unregister(local->hw.wiphy);
- fail_wiphy_register:
        if (local->wiphy_ciphers_allocated)
                kfree(local->hw.wiphy->cipher_suites);
        kfree(local->int_scan_req);
@@ -1372,8 +1375,8 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
        skb_queue_purge(&local->skb_queue_unreliable);
        skb_queue_purge(&local->skb_queue_tdls_chsw);
 
-       destroy_workqueue(local->workqueue);
        wiphy_unregister(local->hw.wiphy);
+       destroy_workqueue(local->workqueue);
        ieee80211_led_exit(local);
        kfree(local->int_scan_req);
 }
index d09b3c789314da9ade860f96892483a334609b2a..36978a0e500017d0c193fb5bfb86a8f61f210206 100644 (file)
@@ -1257,15 +1257,15 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
                    sdata->u.mesh.mshcfg.rssi_threshold < rx_status->signal)
                        mesh_neighbour_update(sdata, mgmt->sa, &elems,
                                              rx_status);
+
+               if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT &&
+                   !sdata->vif.csa_active)
+                       ieee80211_mesh_process_chnswitch(sdata, &elems, true);
        }
 
        if (ifmsh->sync_ops)
                ifmsh->sync_ops->rx_bcn_presp(sdata,
                        stype, mgmt, &elems, rx_status);
-
-       if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT &&
-           !sdata->vif.csa_active)
-               ieee80211_mesh_process_chnswitch(sdata, &elems, true);
 }
 
 int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
@@ -1373,6 +1373,9 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
        ieee802_11_parse_elems(pos, len - baselen, true, &elems,
                               mgmt->bssid, NULL);
 
+       if (!mesh_matches_local(sdata, &elems))
+               return;
+
        ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
        if (!--ifmsh->chsw_ttl)
                fwd_csa = false;
index a1e9fc7878aa33f252ad33414d5dc1e86f8dd99b..b051f125d3af245a885023fcd124c593ac3c36df 100644 (file)
@@ -214,17 +214,16 @@ static ssize_t rcname_read(struct file *file, char __user *userbuf,
                                       ref->ops->name, len);
 }
 
-static const struct file_operations rcname_ops = {
+const struct file_operations rcname_ops = {
        .read = rcname_read,
        .open = simple_open,
        .llseek = default_llseek,
 };
 #endif
 
-static struct rate_control_ref *rate_control_alloc(const char *name,
-                                           struct ieee80211_local *local)
+static struct rate_control_ref *
+rate_control_alloc(const char *name, struct ieee80211_local *local)
 {
-       struct dentry *debugfsdir = NULL;
        struct rate_control_ref *ref;
 
        ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL);
@@ -234,13 +233,7 @@ static struct rate_control_ref *rate_control_alloc(const char *name,
        if (!ref->ops)
                goto free;
 
-#ifdef CONFIG_MAC80211_DEBUGFS
-       debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir);
-       local->debugfs.rcdir = debugfsdir;
-       debugfs_create_file("name", 0400, debugfsdir, ref, &rcname_ops);
-#endif
-
-       ref->priv = ref->ops->alloc(&local->hw, debugfsdir);
+       ref->priv = ref->ops->alloc(&local->hw);
        if (!ref->priv)
                goto free;
        return ref;
index 5397c6dad056124db564f335404c20736ddd7ab4..79b44d3db171e9ddbc1d6e2de041d88e350696ac 100644 (file)
@@ -60,6 +60,29 @@ static inline void rate_control_add_sta_debugfs(struct sta_info *sta)
 #endif
 }
 
+extern const struct file_operations rcname_ops;
+
+static inline void rate_control_add_debugfs(struct ieee80211_local *local)
+{
+#ifdef CONFIG_MAC80211_DEBUGFS
+       struct dentry *debugfsdir;
+
+       if (!local->rate_ctrl)
+               return;
+
+       if (!local->rate_ctrl->ops->add_debugfs)
+               return;
+
+       debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir);
+       local->debugfs.rcdir = debugfsdir;
+       debugfs_create_file("name", 0400, debugfsdir,
+                           local->rate_ctrl, &rcname_ops);
+
+       local->rate_ctrl->ops->add_debugfs(&local->hw, local->rate_ctrl->priv,
+                                          debugfsdir);
+#endif
+}
+
 void ieee80211_check_rate_mask(struct ieee80211_sub_if_data *sdata);
 
 /* Get a reference to the rate control algorithm. If `name' is NULL, get the
index 694a31978a0443dacbdfdd91ce9dd48d46974afe..5dc3e5bc4e6422f7472f3f5fa6c5fa714fd4ca32 100644 (file)
@@ -1635,7 +1635,7 @@ minstrel_ht_init_cck_rates(struct minstrel_priv *mp)
 }
 
 static void *
-minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+minstrel_ht_alloc(struct ieee80211_hw *hw)
 {
        struct minstrel_priv *mp;
 
@@ -1673,7 +1673,17 @@ minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
        mp->update_interval = HZ / 10;
        mp->new_avg = true;
 
+       minstrel_ht_init_cck_rates(mp);
+
+       return mp;
+}
+
 #ifdef CONFIG_MAC80211_DEBUGFS
+static void minstrel_ht_add_debugfs(struct ieee80211_hw *hw, void *priv,
+                                   struct dentry *debugfsdir)
+{
+       struct minstrel_priv *mp = priv;
+
        mp->fixed_rate_idx = (u32) -1;
        debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir,
                           &mp->fixed_rate_idx);
@@ -1681,12 +1691,8 @@ minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
                           &mp->sample_switch);
        debugfs_create_bool("new_avg", S_IRUGO | S_IWUSR, debugfsdir,
                           &mp->new_avg);
-#endif
-
-       minstrel_ht_init_cck_rates(mp);
-
-       return mp;
 }
+#endif
 
 static void
 minstrel_ht_free(void *priv)
@@ -1725,6 +1731,7 @@ static const struct rate_control_ops mac80211_minstrel_ht = {
        .alloc = minstrel_ht_alloc,
        .free = minstrel_ht_free,
 #ifdef CONFIG_MAC80211_DEBUGFS
+       .add_debugfs = minstrel_ht_add_debugfs,
        .add_sta_debugfs = minstrel_ht_add_sta_debugfs,
 #endif
        .get_expected_throughput = minstrel_ht_get_expected_throughput,
index f8d5c25158293df653236d566418c364da622636..cd8487bc6fc2e368f01e41275518a4056c1cc552 100644 (file)
@@ -231,7 +231,8 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
        struct sta_info *sta;
        int i = 0;
 
-       list_for_each_entry_rcu(sta, &local->sta_list, list) {
+       list_for_each_entry_rcu(sta, &local->sta_list, list,
+                               lockdep_is_held(&local->sta_mtx)) {
                if (sdata != sta->sdata)
                        continue;
                if (i < idx) {
index faf57585b89282aae5937e74e948de8c6270d674..45497af23906cdc33e2b6490d9f3a03c24aa8b1e 100644 (file)
@@ -16,10 +16,10 @@ static bool mptcp_cap_flag_sha256(u8 flags)
        return (flags & MPTCP_CAP_FLAG_MASK) == MPTCP_CAP_HMAC_SHA256;
 }
 
-void mptcp_parse_option(const struct sk_buff *skb, const unsigned char *ptr,
-                       int opsize, struct tcp_options_received *opt_rx)
+static void mptcp_parse_option(const struct sk_buff *skb,
+                              const unsigned char *ptr, int opsize,
+                              struct mptcp_options_received *mp_opt)
 {
-       struct mptcp_options_received *mp_opt = &opt_rx->mptcp;
        u8 subtype = *ptr >> 4;
        int expected_opsize;
        u8 version;
@@ -283,12 +283,20 @@ void mptcp_parse_option(const struct sk_buff *skb, const unsigned char *ptr,
 }
 
 void mptcp_get_options(const struct sk_buff *skb,
-                      struct tcp_options_received *opt_rx)
+                      struct mptcp_options_received *mp_opt)
 {
-       const unsigned char *ptr;
        const struct tcphdr *th = tcp_hdr(skb);
-       int length = (th->doff * 4) - sizeof(struct tcphdr);
+       const unsigned char *ptr;
+       int length;
+
+       /* initialize option status */
+       mp_opt->mp_capable = 0;
+       mp_opt->mp_join = 0;
+       mp_opt->add_addr = 0;
+       mp_opt->rm_addr = 0;
+       mp_opt->dss = 0;
 
+       length = (th->doff * 4) - sizeof(struct tcphdr);
        ptr = (const unsigned char *)(th + 1);
 
        while (length > 0) {
@@ -308,7 +316,7 @@ void mptcp_get_options(const struct sk_buff *skb,
                        if (opsize > length)
                                return; /* don't parse partial options */
                        if (opcode == TCPOPT_MPTCP)
-                               mptcp_parse_option(skb, ptr, opsize, opt_rx);
+                               mptcp_parse_option(skb, ptr, opsize, mp_opt);
                        ptr += opsize - 2;
                        length -= opsize;
                }
@@ -344,28 +352,6 @@ bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
        return false;
 }
 
-void mptcp_rcv_synsent(struct sock *sk)
-{
-       struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
-       struct tcp_sock *tp = tcp_sk(sk);
-
-       if (subflow->request_mptcp && tp->rx_opt.mptcp.mp_capable) {
-               subflow->mp_capable = 1;
-               subflow->can_ack = 1;
-               subflow->remote_key = tp->rx_opt.mptcp.sndr_key;
-               pr_debug("subflow=%p, remote_key=%llu", subflow,
-                        subflow->remote_key);
-       } else if (subflow->request_join && tp->rx_opt.mptcp.mp_join) {
-               subflow->mp_join = 1;
-               subflow->thmac = tp->rx_opt.mptcp.thmac;
-               subflow->remote_nonce = tp->rx_opt.mptcp.nonce;
-               pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u", subflow,
-                        subflow->thmac, subflow->remote_nonce);
-       } else if (subflow->request_mptcp) {
-               tcp_sk(sk)->is_mptcp = 0;
-       }
-}
-
 /* MP_JOIN client subflow must wait for 4th ack before sending any data:
  * TCP can't schedule delack timer before the subflow is fully established.
  * MPTCP uses the delack timer to do 3rd ack retransmissions
@@ -709,7 +695,7 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *sk,
        if (TCP_SKB_CB(skb)->seq != subflow->ssn_offset + 1)
                return subflow->mp_capable;
 
-       if (mp_opt->use_ack) {
+       if (mp_opt->dss && mp_opt->use_ack) {
                /* subflows are fully established as soon as we get any
                 * additional ack.
                 */
@@ -717,8 +703,6 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *sk,
                goto fully_established;
        }
 
-       WARN_ON_ONCE(subflow->can_ack);
-
        /* If the first established packet does not contain MP_CAPABLE + data
         * then fallback to TCP
         */
@@ -728,6 +712,8 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *sk,
                return false;
        }
 
+       if (unlikely(!READ_ONCE(msk->pm.server_side)))
+               pr_warn_once("bogus mpc option on established client sk");
        subflow->fully_established = 1;
        subflow->remote_key = mp_opt->sndr_key;
        subflow->can_ack = 1;
@@ -819,41 +805,41 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
 {
        struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
        struct mptcp_sock *msk = mptcp_sk(subflow->conn);
-       struct mptcp_options_received *mp_opt;
+       struct mptcp_options_received mp_opt;
        struct mptcp_ext *mpext;
 
-       mp_opt = &opt_rx->mptcp;
-       if (!check_fully_established(msk, sk, subflow, skb, mp_opt))
+       mptcp_get_options(skb, &mp_opt);
+       if (!check_fully_established(msk, sk, subflow, skb, &mp_opt))
                return;
 
-       if (mp_opt->add_addr && add_addr_hmac_valid(msk, mp_opt)) {
+       if (mp_opt.add_addr && add_addr_hmac_valid(msk, &mp_opt)) {
                struct mptcp_addr_info addr;
 
-               addr.port = htons(mp_opt->port);
-               addr.id = mp_opt->addr_id;
-               if (mp_opt->family == MPTCP_ADDR_IPVERSION_4) {
+               addr.port = htons(mp_opt.port);
+               addr.id = mp_opt.addr_id;
+               if (mp_opt.family == MPTCP_ADDR_IPVERSION_4) {
                        addr.family = AF_INET;
-                       addr.addr = mp_opt->addr;
+                       addr.addr = mp_opt.addr;
                }
 #if IS_ENABLED(CONFIG_MPTCP_IPV6)
-               else if (mp_opt->family == MPTCP_ADDR_IPVERSION_6) {
+               else if (mp_opt.family == MPTCP_ADDR_IPVERSION_6) {
                        addr.family = AF_INET6;
-                       addr.addr6 = mp_opt->addr6;
+                       addr.addr6 = mp_opt.addr6;
                }
 #endif
-               if (!mp_opt->echo)
+               if (!mp_opt.echo)
                        mptcp_pm_add_addr_received(msk, &addr);
-               mp_opt->add_addr = 0;
+               mp_opt.add_addr = 0;
        }
 
-       if (!mp_opt->dss)
+       if (!mp_opt.dss)
                return;
 
        /* we can't wait for recvmsg() to update the ack_seq, otherwise
         * monodirectional flows will stuck
         */
-       if (mp_opt->use_ack)
-               update_una(msk, mp_opt);
+       if (mp_opt.use_ack)
+               update_una(msk, &mp_opt);
 
        mpext = skb_ext_add(skb, SKB_EXT_MPTCP);
        if (!mpext)
@@ -861,8 +847,8 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
 
        memset(mpext, 0, sizeof(*mpext));
 
-       if (mp_opt->use_map) {
-               if (mp_opt->mpc_map) {
+       if (mp_opt.use_map) {
+               if (mp_opt.mpc_map) {
                        /* this is an MP_CAPABLE carrying MPTCP data
                         * we know this map the first chunk of data
                         */
@@ -872,16 +858,16 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
                        mpext->subflow_seq = 1;
                        mpext->dsn64 = 1;
                        mpext->mpc_map = 1;
+                       mpext->data_fin = 0;
                } else {
-                       mpext->data_seq = mp_opt->data_seq;
-                       mpext->subflow_seq = mp_opt->subflow_seq;
-                       mpext->dsn64 = mp_opt->dsn64;
+                       mpext->data_seq = mp_opt.data_seq;
+                       mpext->subflow_seq = mp_opt.subflow_seq;
+                       mpext->dsn64 = mp_opt.dsn64;
+                       mpext->data_fin = mp_opt.data_fin;
                }
-               mpext->data_len = mp_opt->data_len;
+               mpext->data_len = mp_opt.data_len;
                mpext->use_map = 1;
        }
-
-       mpext->data_fin = mp_opt->data_fin;
 }
 
 void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
index 86d61ab34c7c3c5d8327c7996c813adab634159c..b78edf237ba0ad6457f82758edf8623c913f9a4e 100644 (file)
@@ -599,12 +599,14 @@ static int mptcp_nl_fill_addr(struct sk_buff *skb,
            nla_put_s32(skb, MPTCP_PM_ADDR_ATTR_IF_IDX, entry->ifindex))
                goto nla_put_failure;
 
-       if (addr->family == AF_INET)
-               nla_put_in_addr(skb, MPTCP_PM_ADDR_ATTR_ADDR4,
-                               addr->addr.s_addr);
+       if (addr->family == AF_INET &&
+           nla_put_in_addr(skb, MPTCP_PM_ADDR_ATTR_ADDR4,
+                           addr->addr.s_addr))
+               goto nla_put_failure;
 #if IS_ENABLED(CONFIG_MPTCP_IPV6)
-       else if (addr->family == AF_INET6)
-               nla_put_in6_addr(skb, MPTCP_PM_ADDR_ATTR_ADDR6, &addr->addr6);
+       else if (addr->family == AF_INET6 &&
+                nla_put_in6_addr(skb, MPTCP_PM_ADDR_ATTR_ADDR6, &addr->addr6))
+               goto nla_put_failure;
 #endif
        nla_nest_end(skb, attr);
        return 0;
index 939a5045181a5701b50b4348867790b1ef414960..e1f23016ed3f8181a3249d890829a49b45634645 100644 (file)
@@ -97,12 +97,7 @@ static struct socket *__mptcp_tcp_fallback(struct mptcp_sock *msk)
        if (likely(!__mptcp_needs_tcp_fallback(msk)))
                return NULL;
 
-       if (msk->subflow) {
-               release_sock((struct sock *)msk);
-               return msk->subflow;
-       }
-
-       return NULL;
+       return msk->subflow;
 }
 
 static bool __mptcp_can_create_subflow(const struct mptcp_sock *msk)
@@ -734,9 +729,10 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                        goto out;
        }
 
+fallback:
        ssock = __mptcp_tcp_fallback(msk);
        if (unlikely(ssock)) {
-fallback:
+               release_sock(sk);
                pr_debug("fallback passthrough");
                ret = sock_sendmsg(ssock, msg);
                return ret >= 0 ? ret + copied : (copied ? copied : ret);
@@ -769,8 +765,14 @@ fallback:
                if (ret < 0)
                        break;
                if (ret == 0 && unlikely(__mptcp_needs_tcp_fallback(msk))) {
+                       /* Can happen for passive sockets:
+                        * 3WHS negotiated MPTCP, but first packet after is
+                        * plain TCP (e.g. due to middlebox filtering unknown
+                        * options).
+                        *
+                        * Fall back to TCP.
+                        */
                        release_sock(ssk);
-                       ssock = __mptcp_tcp_fallback(msk);
                        goto fallback;
                }
 
@@ -883,6 +885,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
        ssock = __mptcp_tcp_fallback(msk);
        if (unlikely(ssock)) {
 fallback:
+               release_sock(sk);
                pr_debug("fallback-read subflow=%p",
                         mptcp_subflow_ctx(ssock->sk));
                copied = sock_recvmsg(ssock, msg, flags);
@@ -1313,11 +1316,12 @@ static void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk)
 
 static int mptcp_disconnect(struct sock *sk, int flags)
 {
-       lock_sock(sk);
-       __mptcp_clear_xmit(sk);
-       release_sock(sk);
-       mptcp_cancel_work(sk);
-       return tcp_disconnect(sk, flags);
+       /* Should never be called.
+        * inet_stream_connect() calls ->disconnect, but that
+        * refers to the subflow socket, not the mptcp one.
+        */
+       WARN_ON_ONCE(1);
+       return 0;
 }
 
 #if IS_ENABLED(CONFIG_MPTCP_IPV6)
@@ -1329,7 +1333,9 @@ static struct ipv6_pinfo *mptcp_inet6_sk(const struct sock *sk)
 }
 #endif
 
-struct sock *mptcp_sk_clone(const struct sock *sk, struct request_sock *req)
+struct sock *mptcp_sk_clone(const struct sock *sk,
+                           const struct mptcp_options_received *mp_opt,
+                           struct request_sock *req)
 {
        struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
        struct sock *nsk = sk_clone_lock(sk, GFP_ATOMIC);
@@ -1352,26 +1358,30 @@ struct sock *mptcp_sk_clone(const struct sock *sk, struct request_sock *req)
        msk->subflow = NULL;
 
        if (unlikely(mptcp_token_new_accept(subflow_req->token, nsk))) {
+               nsk->sk_state = TCP_CLOSE;
                bh_unlock_sock(nsk);
 
                /* we can't call into mptcp_close() here - possible BH context
-                * free the sock directly
+                * free the sock directly.
+                * sk_clone_lock() sets nsk refcnt to two, hence call sk_free()
+                * too.
                 */
-               nsk->sk_prot->destroy(nsk);
+               sk_common_release(nsk);
                sk_free(nsk);
                return NULL;
        }
 
        msk->write_seq = subflow_req->idsn + 1;
        atomic64_set(&msk->snd_una, msk->write_seq);
-       if (subflow_req->remote_key_valid) {
+       if (mp_opt->mp_capable) {
                msk->can_ack = true;
-               msk->remote_key = subflow_req->remote_key;
+               msk->remote_key = mp_opt->sndr_key;
                mptcp_crypto_key_sha(msk->remote_key, NULL, &ack_seq);
                ack_seq++;
                msk->ack_seq = ack_seq;
        }
 
+       sock_reset_flag(nsk, SOCK_RCU_FREE);
        /* will be fully established after successful MPC subflow creation */
        inet_sk_state_store(nsk, TCP_SYN_RECV);
        bh_unlock_sock(nsk);
@@ -1428,6 +1438,7 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
                newsk = new_mptcp_sock;
                mptcp_copy_inaddrs(newsk, ssk);
                list_add(&subflow->node, &msk->conn_list);
+               inet_sk_state_store(newsk, TCP_ESTABLISHED);
 
                bh_unlock_sock(new_mptcp_sock);
 
@@ -1467,12 +1478,11 @@ static int mptcp_setsockopt(struct sock *sk, int level, int optname,
         */
        lock_sock(sk);
        ssock = __mptcp_tcp_fallback(msk);
+       release_sock(sk);
        if (ssock)
                return tcp_setsockopt(ssock->sk, level, optname, optval,
                                      optlen);
 
-       release_sock(sk);
-
        return -EOPNOTSUPP;
 }
 
@@ -1492,12 +1502,11 @@ static int mptcp_getsockopt(struct sock *sk, int level, int optname,
         */
        lock_sock(sk);
        ssock = __mptcp_tcp_fallback(msk);
+       release_sock(sk);
        if (ssock)
                return tcp_getsockopt(ssock->sk, level, optname, optval,
                                      option);
 
-       release_sock(sk);
-
        return -EOPNOTSUPP;
 }
 
@@ -1774,6 +1783,8 @@ static int mptcp_listen(struct socket *sock, int backlog)
                goto unlock;
        }
 
+       sock_set_flag(sock->sk, SOCK_RCU_FREE);
+
        err = ssock->ops->listen(ssock, backlog);
        inet_sk_state_store(sock->sk, inet_sk_state_load(ssock->sk));
        if (!err)
index 67448002a2d793ffa47ddb7e9df36891f345b8c7..e4ca6320ce7679c64f588290d65b10686ee3c728 100644 (file)
 #define MPTCP_WORK_RTX         2
 #define MPTCP_WORK_EOF         3
 
+struct mptcp_options_received {
+       u64     sndr_key;
+       u64     rcvr_key;
+       u64     data_ack;
+       u64     data_seq;
+       u32     subflow_seq;
+       u16     data_len;
+       u16     mp_capable : 1,
+               mp_join : 1,
+               dss : 1,
+               add_addr : 1,
+               rm_addr : 1,
+               family : 4,
+               echo : 1,
+               backup : 1;
+       u32     token;
+       u32     nonce;
+       u64     thmac;
+       u8      hmac[20];
+       u8      join_id;
+       u8      use_map:1,
+               dsn64:1,
+               data_fin:1,
+               use_ack:1,
+               ack64:1,
+               mpc_map:1,
+               __unused:2;
+       u8      addr_id;
+       u8      rm_id;
+       union {
+               struct in_addr  addr;
+#if IS_ENABLED(CONFIG_MPTCP_IPV6)
+               struct in6_addr addr6;
+#endif
+       };
+       u64     ahmac;
+       u16     port;
+};
+
 static inline __be32 mptcp_option(u8 subopt, u8 len, u8 nib, u8 field)
 {
        return htonl((TCPOPT_MPTCP << 24) | (len << 16) | (subopt << 12) |
@@ -206,12 +245,10 @@ struct mptcp_subflow_request_sock {
        struct  tcp_request_sock sk;
        u16     mp_capable : 1,
                mp_join : 1,
-               backup : 1,
-               remote_key_valid : 1;
+               backup : 1;
        u8      local_id;
        u8      remote_id;
        u64     local_key;
-       u64     remote_key;
        u64     idsn;
        u32     token;
        u32     ssn_offset;
@@ -332,9 +369,11 @@ void mptcp_proto_init(void);
 int mptcp_proto_v6_init(void);
 #endif
 
-struct sock *mptcp_sk_clone(const struct sock *sk, struct request_sock *req);
+struct sock *mptcp_sk_clone(const struct sock *sk,
+                           const struct mptcp_options_received *mp_opt,
+                           struct request_sock *req);
 void mptcp_get_options(const struct sk_buff *skb,
-                      struct tcp_options_received *opt_rx);
+                      struct mptcp_options_received *mp_opt);
 
 void mptcp_finish_connect(struct sock *sk);
 void mptcp_data_ready(struct sock *sk, struct sock *ssk);
index 50a8bea987c6e859303941d1a41165c651806bfb..67a4e35d48384ee0fd54b3d9cafe0a0bf25e034a 100644 (file)
@@ -124,16 +124,14 @@ static void subflow_init_req(struct request_sock *req,
 {
        struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk_listener);
        struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
-       struct tcp_options_received rx_opt;
+       struct mptcp_options_received mp_opt;
 
        pr_debug("subflow_req=%p, listener=%p", subflow_req, listener);
 
-       memset(&rx_opt.mptcp, 0, sizeof(rx_opt.mptcp));
-       mptcp_get_options(skb, &rx_opt);
+       mptcp_get_options(skb, &mp_opt);
 
        subflow_req->mp_capable = 0;
        subflow_req->mp_join = 0;
-       subflow_req->remote_key_valid = 0;
 
 #ifdef CONFIG_TCP_MD5SIG
        /* no MPTCP if MD5SIG is enabled on this socket or we may run out of
@@ -143,16 +141,16 @@ static void subflow_init_req(struct request_sock *req,
                return;
 #endif
 
-       if (rx_opt.mptcp.mp_capable) {
+       if (mp_opt.mp_capable) {
                SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPCAPABLEPASSIVE);
 
-               if (rx_opt.mptcp.mp_join)
+               if (mp_opt.mp_join)
                        return;
-       } else if (rx_opt.mptcp.mp_join) {
+       } else if (mp_opt.mp_join) {
                SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINSYNRX);
        }
 
-       if (rx_opt.mptcp.mp_capable && listener->request_mptcp) {
+       if (mp_opt.mp_capable && listener->request_mptcp) {
                int err;
 
                err = mptcp_token_new_request(req);
@@ -160,13 +158,13 @@ static void subflow_init_req(struct request_sock *req,
                        subflow_req->mp_capable = 1;
 
                subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq;
-       } else if (rx_opt.mptcp.mp_join && listener->request_mptcp) {
+       } else if (mp_opt.mp_join && listener->request_mptcp) {
                subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq;
                subflow_req->mp_join = 1;
-               subflow_req->backup = rx_opt.mptcp.backup;
-               subflow_req->remote_id = rx_opt.mptcp.join_id;
-               subflow_req->token = rx_opt.mptcp.token;
-               subflow_req->remote_nonce = rx_opt.mptcp.nonce;
+               subflow_req->backup = mp_opt.backup;
+               subflow_req->remote_id = mp_opt.join_id;
+               subflow_req->token = mp_opt.token;
+               subflow_req->remote_nonce = mp_opt.nonce;
                pr_debug("token=%u, remote_nonce=%u", subflow_req->token,
                         subflow_req->remote_nonce);
                if (!subflow_token_join_request(req, skb)) {
@@ -222,23 +220,47 @@ static bool subflow_thmac_valid(struct mptcp_subflow_context *subflow)
 static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
 {
        struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
+       struct mptcp_options_received mp_opt;
        struct sock *parent = subflow->conn;
+       struct tcp_sock *tp = tcp_sk(sk);
 
        subflow->icsk_af_ops->sk_rx_dst_set(sk, skb);
 
-       if (inet_sk_state_load(parent) != TCP_ESTABLISHED) {
+       if (inet_sk_state_load(parent) == TCP_SYN_SENT) {
                inet_sk_state_store(parent, TCP_ESTABLISHED);
                parent->sk_state_change(parent);
        }
 
-       if (subflow->conn_finished || !tcp_sk(sk)->is_mptcp)
+       /* be sure no special action on any packet other than syn-ack */
+       if (subflow->conn_finished)
+               return;
+
+       subflow->conn_finished = 1;
+
+       mptcp_get_options(skb, &mp_opt);
+       if (subflow->request_mptcp && mp_opt.mp_capable) {
+               subflow->mp_capable = 1;
+               subflow->can_ack = 1;
+               subflow->remote_key = mp_opt.sndr_key;
+               pr_debug("subflow=%p, remote_key=%llu", subflow,
+                        subflow->remote_key);
+       } else if (subflow->request_join && mp_opt.mp_join) {
+               subflow->mp_join = 1;
+               subflow->thmac = mp_opt.thmac;
+               subflow->remote_nonce = mp_opt.nonce;
+               pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u", subflow,
+                        subflow->thmac, subflow->remote_nonce);
+       } else if (subflow->request_mptcp) {
+               tp->is_mptcp = 0;
+       }
+
+       if (!tp->is_mptcp)
                return;
 
        if (subflow->mp_capable) {
                pr_debug("subflow=%p, remote_key=%llu", mptcp_subflow_ctx(sk),
                         subflow->remote_key);
                mptcp_finish_connect(sk);
-               subflow->conn_finished = 1;
 
                if (skb) {
                        pr_debug("synack seq=%u", TCP_SKB_CB(skb)->seq);
@@ -265,7 +287,6 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
                if (!mptcp_finish_join(sk))
                        goto do_reset;
 
-               subflow->conn_finished = 1;
                MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNACKRX);
        } else {
 do_reset:
@@ -323,7 +344,7 @@ drop:
 
 /* validate hmac received in third ACK */
 static bool subflow_hmac_valid(const struct request_sock *req,
-                              const struct tcp_options_received *rx_opt)
+                              const struct mptcp_options_received *mp_opt)
 {
        const struct mptcp_subflow_request_sock *subflow_req;
        u8 hmac[MPTCPOPT_HMAC_LEN];
@@ -340,13 +361,53 @@ static bool subflow_hmac_valid(const struct request_sock *req,
                              subflow_req->local_nonce, hmac);
 
        ret = true;
-       if (crypto_memneq(hmac, rx_opt->mptcp.hmac, sizeof(hmac)))
+       if (crypto_memneq(hmac, mp_opt->hmac, sizeof(hmac)))
                ret = false;
 
        sock_put((struct sock *)msk);
        return ret;
 }
 
+static void mptcp_sock_destruct(struct sock *sk)
+{
+       /* if new mptcp socket isn't accepted, it is free'd
+        * from the tcp listener sockets request queue, linked
+        * from req->sk.  The tcp socket is released.
+        * This calls the ULP release function which will
+        * also remove the mptcp socket, via
+        * sock_put(ctx->conn).
+        *
+        * Problem is that the mptcp socket will not be in
+        * SYN_RECV state and doesn't have SOCK_DEAD flag.
+        * Both result in warnings from inet_sock_destruct.
+        */
+
+       if (sk->sk_state == TCP_SYN_RECV) {
+               sk->sk_state = TCP_CLOSE;
+               WARN_ON_ONCE(sk->sk_socket);
+               sock_orphan(sk);
+       }
+
+       inet_sock_destruct(sk);
+}
+
+static void mptcp_force_close(struct sock *sk)
+{
+       inet_sk_state_store(sk, TCP_CLOSE);
+       sk_common_release(sk);
+}
+
+static void subflow_ulp_fallback(struct sock *sk,
+                                struct mptcp_subflow_context *old_ctx)
+{
+       struct inet_connection_sock *icsk = inet_csk(sk);
+
+       mptcp_subflow_tcp_fallback(sk, old_ctx);
+       icsk->icsk_ulp_ops = NULL;
+       rcu_assign_pointer(icsk->icsk_ulp_data, NULL);
+       tcp_sk(sk)->is_mptcp = 0;
+}
+
 static struct sock *subflow_syn_recv_sock(const struct sock *sk,
                                          struct sk_buff *skb,
                                          struct request_sock *req,
@@ -356,13 +417,18 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
 {
        struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk);
        struct mptcp_subflow_request_sock *subflow_req;
-       struct tcp_options_received opt_rx;
+       struct mptcp_options_received mp_opt;
        bool fallback_is_fatal = false;
        struct sock *new_msk = NULL;
+       bool fallback = false;
        struct sock *child;
 
        pr_debug("listener=%p, req=%p, conn=%p", listener, req, listener->conn);
 
+       /* we need later a valid 'mp_capable' value even when options are not
+        * parsed
+        */
+       mp_opt.mp_capable = 0;
        if (tcp_rsk(req)->is_mptcp == 0)
                goto create_child;
 
@@ -377,26 +443,21 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
                        goto create_msk;
                }
 
-               opt_rx.mptcp.mp_capable = 0;
-               mptcp_get_options(skb, &opt_rx);
-               if (opt_rx.mptcp.mp_capable) {
-                       subflow_req->remote_key = opt_rx.mptcp.sndr_key;
-                       subflow_req->remote_key_valid = 1;
-               } else {
-                       subflow_req->mp_capable = 0;
+               mptcp_get_options(skb, &mp_opt);
+               if (!mp_opt.mp_capable) {
+                       fallback = true;
                        goto create_child;
                }
 
 create_msk:
-               new_msk = mptcp_sk_clone(listener->conn, req);
+               new_msk = mptcp_sk_clone(listener->conn, &mp_opt, req);
                if (!new_msk)
-                       subflow_req->mp_capable = 0;
+                       fallback = true;
        } else if (subflow_req->mp_join) {
                fallback_is_fatal = true;
-               opt_rx.mptcp.mp_join = 0;
-               mptcp_get_options(skb, &opt_rx);
-               if (!opt_rx.mptcp.mp_join ||
-                   !subflow_hmac_valid(req, &opt_rx)) {
+               mptcp_get_options(skb, &mp_opt);
+               if (!mp_opt.mp_join ||
+                   !subflow_hmac_valid(req, &mp_opt)) {
                        SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC);
                        return NULL;
                }
@@ -409,12 +470,18 @@ create_child:
        if (child && *own_req) {
                struct mptcp_subflow_context *ctx = mptcp_subflow_ctx(child);
 
-               /* we have null ctx on TCP fallback, which is fatal on
-                * MPJ handshake
+               /* we need to fallback on ctx allocation failure and on pre-reqs
+                * checking above. In the latter scenario we additionally need
+                * to reset the context to non MPTCP status.
                 */
-               if (!ctx) {
+               if (!ctx || fallback) {
                        if (fallback_is_fatal)
                                goto close_child;
+
+                       if (ctx) {
+                               subflow_ulp_fallback(child, ctx);
+                               kfree_rcu(ctx, rcu);
+                       }
                        goto out;
                }
 
@@ -422,10 +489,17 @@ create_child:
                        /* new mpc subflow takes ownership of the newly
                         * created mptcp socket
                         */
-                       inet_sk_state_store(new_msk, TCP_ESTABLISHED);
+                       new_msk->sk_destruct = mptcp_sock_destruct;
                        mptcp_pm_new_connection(mptcp_sk(new_msk), 1);
                        ctx->conn = new_msk;
                        new_msk = NULL;
+
+                       /* with OoO packets we can reach here without ingress
+                        * mpc option
+                        */
+                       ctx->remote_key = mp_opt.sndr_key;
+                       ctx->fully_established = mp_opt.mp_capable;
+                       ctx->can_ack = mp_opt.mp_capable;
                } else if (ctx->mp_join) {
                        struct mptcp_sock *owner;
 
@@ -444,7 +518,14 @@ create_child:
 out:
        /* dispose of the left over mptcp master, if any */
        if (unlikely(new_msk))
-               sock_put(new_msk);
+               mptcp_force_close(new_msk);
+
+       /* check for expected invariant - should never trigger, just help
+        * catching eariler subtle bugs
+        */
+       WARN_ON_ONCE(child && *own_req && tcp_sk(child)->is_mptcp &&
+                    (!mptcp_subflow_ctx(child) ||
+                     !mptcp_subflow_ctx(child)->conn));
        return child;
 
 close_child:
@@ -1047,17 +1128,6 @@ static void subflow_ulp_release(struct sock *sk)
        kfree_rcu(ctx, rcu);
 }
 
-static void subflow_ulp_fallback(struct sock *sk,
-                                struct mptcp_subflow_context *old_ctx)
-{
-       struct inet_connection_sock *icsk = inet_csk(sk);
-
-       mptcp_subflow_tcp_fallback(sk, old_ctx);
-       icsk->icsk_ulp_ops = NULL;
-       rcu_assign_pointer(icsk->icsk_ulp_data, NULL);
-       tcp_sk(sk)->is_mptcp = 0;
-}
-
 static void subflow_ulp_clone(const struct request_sock *req,
                              struct sock *newsk,
                              const gfp_t priority)
@@ -1091,9 +1161,6 @@ static void subflow_ulp_clone(const struct request_sock *req,
                 * is fully established only after we receive the remote key
                 */
                new_ctx->mp_capable = 1;
-               new_ctx->fully_established = subflow_req->remote_key_valid;
-               new_ctx->can_ack = subflow_req->remote_key_valid;
-               new_ctx->remote_key = subflow_req->remote_key;
                new_ctx->local_key = subflow_req->local_key;
                new_ctx->token = subflow_req->token;
                new_ctx->ssn_offset = subflow_req->ssn_offset;
index 8dd17589217d71e4e38f6d442434130cadd290e0..340cb955af25c40da445e1f5482e8ec278dbf098 100644 (file)
@@ -86,7 +86,8 @@ find_set_type(const char *name, u8 family, u8 revision)
 {
        struct ip_set_type *type;
 
-       list_for_each_entry_rcu(type, &ip_set_type_list, list)
+       list_for_each_entry_rcu(type, &ip_set_type_list, list,
+                               lockdep_is_held(&ip_set_type_mutex))
                if (STRNCMP(type->name, name) &&
                    (type->family == family ||
                     type->family == NFPROTO_UNSPEC) &&
index c0cb79495c358e9f70bb72d1ef349553b93cca31..4344e572b7f96c65e7df179f3596be0ad5499c18 100644 (file)
@@ -421,10 +421,12 @@ void nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table,
 
        down_write(&flow_table->flow_block_lock);
        block_cb = flow_block_cb_lookup(block, cb, cb_priv);
-       if (block_cb)
+       if (block_cb) {
                list_del(&block_cb->list);
-       else
+               flow_block_cb_free(block_cb);
+       } else {
                WARN_ON(true);
+       }
        up_write(&flow_table->flow_block_lock);
 }
 EXPORT_SYMBOL_GPL(nf_flow_table_offload_del_cb);
index 64eedc17037ad783d3a99851038e91394465617e..59151dc07fdc14fe6fa640cdd0448723d96bcb48 100644 (file)
@@ -68,15 +68,13 @@ static bool udp_manip_pkt(struct sk_buff *skb,
                          enum nf_nat_manip_type maniptype)
 {
        struct udphdr *hdr;
-       bool do_csum;
 
        if (skb_ensure_writable(skb, hdroff + sizeof(*hdr)))
                return false;
 
        hdr = (struct udphdr *)(skb->data + hdroff);
-       do_csum = hdr->check || skb->ip_summed == CHECKSUM_PARTIAL;
+       __udp_manip_pkt(skb, iphdroff, hdr, tuple, maniptype, !!hdr->check);
 
-       __udp_manip_pkt(skb, iphdroff, hdr, tuple, maniptype, do_csum);
        return true;
 }
 
@@ -1035,8 +1033,8 @@ int nf_nat_inet_register_fn(struct net *net, const struct nf_hook_ops *ops)
        ret = nf_nat_register_fn(net, NFPROTO_IPV4, ops, nf_nat_ipv4_ops,
                                 ARRAY_SIZE(nf_nat_ipv4_ops));
        if (ret)
-               nf_nat_ipv6_unregister_fn(net, ops);
-
+               nf_nat_unregister_fn(net, NFPROTO_IPV6, ops,
+                                       ARRAY_SIZE(nf_nat_ipv6_ops));
        return ret;
 }
 EXPORT_SYMBOL_GPL(nf_nat_inet_register_fn);
index 4471393da6d8dc1e0cfece7bc8fb2e69963d29b7..9780bd93b7e4958771e7244a0fb9101231597a80 100644 (file)
@@ -3542,6 +3542,7 @@ cont:
                        continue;
                if (!strcmp(set->name, i->name)) {
                        kfree(set->name);
+                       set->name = NULL;
                        return -ENFILE;
                }
        }
@@ -3961,8 +3962,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
                if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
                              NFT_SET_INTERVAL | NFT_SET_TIMEOUT |
                              NFT_SET_MAP | NFT_SET_EVAL |
-                             NFT_SET_OBJECT))
-                       return -EINVAL;
+                             NFT_SET_OBJECT | NFT_SET_CONCAT))
+                       return -EOPNOTSUPP;
                /* Only one of these operations is supported */
                if ((flags & (NFT_SET_MAP | NFT_SET_OBJECT)) ==
                             (NFT_SET_MAP | NFT_SET_OBJECT))
@@ -4000,7 +4001,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
                objtype = ntohl(nla_get_be32(nla[NFTA_SET_OBJ_TYPE]));
                if (objtype == NFT_OBJECT_UNSPEC ||
                    objtype > NFT_OBJECT_MAX)
-                       return -EINVAL;
+                       return -EOPNOTSUPP;
        } else if (flags & NFT_SET_OBJECT)
                return -EINVAL;
        else
index 9f5dea0064ea86b52dbca0c1e127564be91a7cca..916a3c7f9eafe78b6a5507ae6bb5ac39f42e6ba7 100644 (file)
@@ -165,12 +165,12 @@ static bool nf_osf_match_one(const struct sk_buff *skb,
 static const struct tcphdr *nf_osf_hdr_ctx_init(struct nf_osf_hdr_ctx *ctx,
                                                const struct sk_buff *skb,
                                                const struct iphdr *ip,
-                                               unsigned char *opts)
+                                               unsigned char *opts,
+                                               struct tcphdr *_tcph)
 {
        const struct tcphdr *tcp;
-       struct tcphdr _tcph;
 
-       tcp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(struct tcphdr), &_tcph);
+       tcp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(struct tcphdr), _tcph);
        if (!tcp)
                return NULL;
 
@@ -205,10 +205,11 @@ nf_osf_match(const struct sk_buff *skb, u_int8_t family,
        int fmatch = FMATCH_WRONG;
        struct nf_osf_hdr_ctx ctx;
        const struct tcphdr *tcp;
+       struct tcphdr _tcph;
 
        memset(&ctx, 0, sizeof(ctx));
 
-       tcp = nf_osf_hdr_ctx_init(&ctx, skb, ip, opts);
+       tcp = nf_osf_hdr_ctx_init(&ctx, skb, ip, opts, &_tcph);
        if (!tcp)
                return false;
 
@@ -265,10 +266,11 @@ bool nf_osf_find(const struct sk_buff *skb,
        const struct nf_osf_finger *kf;
        struct nf_osf_hdr_ctx ctx;
        const struct tcphdr *tcp;
+       struct tcphdr _tcph;
 
        memset(&ctx, 0, sizeof(ctx));
 
-       tcp = nf_osf_hdr_ctx_init(&ctx, skb, ip, opts);
+       tcp = nf_osf_hdr_ctx_init(&ctx, skb, ip, opts, &_tcph);
        if (!tcp)
                return false;
 
index 1e70359d633c0eac04745860a9deb6bfd2f2c6df..f1363b8aabba84a63170fc84dbeeff132d58276c 100644 (file)
@@ -29,7 +29,7 @@ void nft_lookup_eval(const struct nft_expr *expr,
 {
        const struct nft_lookup *priv = nft_expr_priv(expr);
        const struct nft_set *set = priv->set;
-       const struct nft_set_ext *ext;
+       const struct nft_set_ext *ext = NULL;
        bool found;
 
        found = set->ops->lookup(nft_net(pkt), set, &regs->data[priv->sreg],
@@ -39,11 +39,13 @@ void nft_lookup_eval(const struct nft_expr *expr,
                return;
        }
 
-       if (set->flags & NFT_SET_MAP)
-               nft_data_copy(&regs->data[priv->dreg],
-                             nft_set_ext_data(ext), set->dlen);
+       if (ext) {
+               if (set->flags & NFT_SET_MAP)
+                       nft_data_copy(&regs->data[priv->dreg],
+                                     nft_set_ext_data(ext), set->dlen);
 
-       nft_set_elem_update_expr(ext, regs, pkt);
+               nft_set_elem_update_expr(ext, regs, pkt);
+       }
 }
 
 static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = {
index 32f0fc8be3a4c475f85595bf1fadba92afa600ea..2a81ea4218193aac5ae82a38d770572509c6d14e 100644 (file)
@@ -81,7 +81,6 @@ static bool nft_bitmap_lookup(const struct net *net, const struct nft_set *set,
        u32 idx, off;
 
        nft_bitmap_location(set, key, &idx, &off);
-       *ext = NULL;
 
        return nft_bitmap_active(priv->bitmap, idx, off, genmask);
 }
index 3a5552e14f75dbc260d385a365e050ce337d02ef..3ffef454d4699f025fb390c7e60a5bc119e77887 100644 (file)
@@ -218,27 +218,26 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
 
        /* Detect overlaps as we descend the tree. Set the flag in these cases:
         *
-        * a1. |__ _ _?  >|__ _ _  (insert start after existing start)
-        * a2. _ _ __>|  ?_ _ __|  (insert end before existing end)
-        * a3. _ _ ___|  ?_ _ _>|  (insert end after existing end)
-        * a4. >|__ _ _   _ _ __|  (insert start before existing end)
+        * a1. _ _ __>|  ?_ _ __|  (insert end before existing end)
+        * a2. _ _ ___|  ?_ _ _>|  (insert end after existing end)
+        * a3. _ _ ___? >|_ _ __|  (insert start before existing end)
         *
         * and clear it later on, as we eventually reach the points indicated by
         * '?' above, in the cases described below. We'll always meet these
         * later, locally, due to tree ordering, and overlaps for the intervals
         * that are the closest together are always evaluated last.
         *
-        * b1. |__ _ _!  >|__ _ _  (insert start after existing end)
-        * b2. _ _ __>|  !_ _ __|  (insert end before existing start)
-        * b3. !_____>|            (insert end after existing start)
+        * b1. _ _ __>|  !_ _ __|  (insert end before existing start)
+        * b2. _ _ ___|  !_ _ _>|  (insert end after existing start)
+        * b3. _ _ ___! >|_ _ __|  (insert start after existing end)
         *
-        * Case a4. resolves to b1.:
+        * Case a3. resolves to b3.:
         * - if the inserted start element is the leftmost, because the '0'
         *   element in the tree serves as end element
         * - otherwise, if an existing end is found. Note that end elements are
         *   always inserted after corresponding start elements.
         *
-        * For a new, rightmost pair of elements, we'll hit cases b1. and b3.,
+        * For a new, rightmost pair of elements, we'll hit cases b3. and b2.,
         * in that order.
         *
         * The flag is also cleared in two special cases:
@@ -262,9 +261,9 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
                        p = &parent->rb_left;
 
                        if (nft_rbtree_interval_start(new)) {
-                               overlap = nft_rbtree_interval_start(rbe) &&
-                                         nft_set_elem_active(&rbe->ext,
-                                                             genmask);
+                               if (nft_rbtree_interval_end(rbe) &&
+                                   nft_set_elem_active(&rbe->ext, genmask))
+                                       overlap = false;
                        } else {
                                overlap = nft_rbtree_interval_end(rbe) &&
                                          nft_set_elem_active(&rbe->ext,
index 75bd0e5dd312e1d9e807f15de87cb4b0e2d3f387..7b2f359bfce46160acc3c29e7a9b4b68bbe3b731 100644 (file)
@@ -346,6 +346,9 @@ static int idletimer_tg_checkentry_v1(const struct xt_tgchk_param *par)
 
        pr_debug("checkentry targinfo%s\n", info->label);
 
+       if (info->send_nl_msg)
+               return -EOPNOTSUPP;
+
        ret = idletimer_tg_helper((struct idletimer_tg_info *)info);
        if(ret < 0)
        {
index 64280a1d3906c2b8f8fea3ad4796d14c210654ce..07b03c306f28abc4758ea3e17ac5c6ff1dff67ce 100644 (file)
@@ -14,6 +14,6 @@ config NETLABEL
          Documentation/netlabel as well as the NetLabel SourceForge project
          for configuration tools and additional documentation.
 
-          * http://netlabel.sf.net
+          * https://github.com/netlabel/netlabel_tools
 
          If you are unsure, say N.
index 79f12d8c7b86f59636f95c16d7974a5397f398f8..0891ee02ca4fe03145066852035de38e62a06ee2 100644 (file)
@@ -208,6 +208,7 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
                /* refcount initialized at 1 */
                spin_unlock_bh(&nr_node_list_lock);
 
+               nr_neigh_put(nr_neigh);
                return 0;
        }
        nr_node_lock(nr_node);
index e726159cfcfae3151d21a76a1a9b5c29bb54fd6f..4340f25fe390f5baac7d0602e67803f2dc05ae57 100644 (file)
@@ -1895,7 +1895,8 @@ static void ovs_ct_limit_exit(struct net *net, struct ovs_net *ovs_net)
                struct hlist_head *head = &info->limits[i];
                struct ovs_ct_limit *ct_limit;
 
-               hlist_for_each_entry_rcu(ct_limit, head, hlist_node)
+               hlist_for_each_entry_rcu(ct_limit, head, hlist_node,
+                                        lockdep_ovsl_is_held())
                        kfree_rcu(ct_limit, rcu);
        }
        kfree(ovs_net->ct_limit_info->limits);
index d8ae541d22a8ce8979aef099be0c1e85801c91fc..94b024534987a02428e7bd579e531958ca4b190b 100644 (file)
@@ -2466,8 +2466,10 @@ static void __net_exit ovs_exit_net(struct net *dnet)
        struct net *net;
        LIST_HEAD(head);
 
-       ovs_ct_exit(dnet);
        ovs_lock();
+
+       ovs_ct_exit(dnet);
+
        list_for_each_entry_safe(dp, dp_next, &ovs_net->dps, list_node)
                __dp_destroy(dp);
 
index e22092e4a783861a57179a61bc055d0b5e53f1ca..7ed31b5e77e46060b9138e6c8e11cc18febffc24 100644 (file)
@@ -906,20 +906,21 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 
        node = NULL;
        if (addr->sq_node == QRTR_NODE_BCAST) {
-               enqueue_fn = qrtr_bcast_enqueue;
-               if (addr->sq_port != QRTR_PORT_CTRL) {
+               if (addr->sq_port != QRTR_PORT_CTRL &&
+                   qrtr_local_nid != QRTR_NODE_BCAST) {
                        release_sock(sk);
                        return -ENOTCONN;
                }
+               enqueue_fn = qrtr_bcast_enqueue;
        } else if (addr->sq_node == ipc->us.sq_node) {
                enqueue_fn = qrtr_local_enqueue;
        } else {
-               enqueue_fn = qrtr_node_enqueue;
                node = qrtr_node_lookup(addr->sq_node);
                if (!node) {
                        release_sock(sk);
                        return -ECONNRESET;
                }
+               enqueue_fn = qrtr_node_enqueue;
        }
 
        plen = (len + 3) & ~3;
index 50f13f1d4ae091accfbeae36192cc219e9e63aca..071a261fdaabbfbefe2ddc007c162f61e70a1d96 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 Oracle.  All rights reserved.
+ * Copyright (c) 2006, 2020 Oracle and/or its affiliates.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -162,12 +162,12 @@ static void rds_message_purge(struct rds_message *rm)
        if (rm->rdma.op_active)
                rds_rdma_free_op(&rm->rdma);
        if (rm->rdma.op_rdma_mr)
-               rds_mr_put(rm->rdma.op_rdma_mr);
+               kref_put(&rm->rdma.op_rdma_mr->r_kref, __rds_put_mr_final);
 
        if (rm->atomic.op_active)
                rds_atomic_free_op(&rm->atomic);
        if (rm->atomic.op_rdma_mr)
-               rds_mr_put(rm->atomic.op_rdma_mr);
+               kref_put(&rm->atomic.op_rdma_mr->r_kref, __rds_put_mr_final);
 }
 
 void rds_message_put(struct rds_message *rm)
@@ -308,26 +308,20 @@ out:
 /*
  * RDS ops use this to grab SG entries from the rm's sg pool.
  */
-struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents,
-                                         int *ret)
+struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents)
 {
        struct scatterlist *sg_first = (struct scatterlist *) &rm[1];
        struct scatterlist *sg_ret;
 
-       if (WARN_ON(!ret))
-               return NULL;
-
        if (nents <= 0) {
                pr_warn("rds: alloc sgs failed! nents <= 0\n");
-               *ret = -EINVAL;
-               return NULL;
+               return ERR_PTR(-EINVAL);
        }
 
        if (rm->m_used_sgs + nents > rm->m_total_sgs) {
                pr_warn("rds: alloc sgs failed! total %d used %d nents %d\n",
                        rm->m_total_sgs, rm->m_used_sgs, nents);
-               *ret = -ENOMEM;
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        }
 
        sg_ret = &sg_first[rm->m_used_sgs];
@@ -343,7 +337,6 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
        unsigned int i;
        int num_sgs = DIV_ROUND_UP(total_len, PAGE_SIZE);
        int extra_bytes = num_sgs * sizeof(struct scatterlist);
-       int ret;
 
        rm = rds_message_alloc(extra_bytes, GFP_NOWAIT);
        if (!rm)
@@ -352,10 +345,10 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
        set_bit(RDS_MSG_PAGEVEC, &rm->m_flags);
        rm->m_inc.i_hdr.h_len = cpu_to_be32(total_len);
        rm->data.op_nents = DIV_ROUND_UP(total_len, PAGE_SIZE);
-       rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs, &ret);
-       if (!rm->data.op_sg) {
+       rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs);
+       if (IS_ERR(rm->data.op_sg)) {
                rds_message_put(rm);
-               return ERR_PTR(ret);
+               return ERR_CAST(rm->data.op_sg);
        }
 
        for (i = 0; i < rm->data.op_nents; ++i) {
index 585e6b3b69ce4c32ec9404ee5ad88065b0979f75..a7ae11846cd7f57c066ec4967d75ca3b5d906c57 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -84,7 +84,7 @@ static struct rds_mr *rds_mr_tree_walk(struct rb_root *root, u64 key,
        if (insert) {
                rb_link_node(&insert->r_rb_node, parent, p);
                rb_insert_color(&insert->r_rb_node, root);
-               refcount_inc(&insert->r_refcount);
+               kref_get(&insert->r_kref);
        }
        return NULL;
 }
@@ -99,10 +99,7 @@ static void rds_destroy_mr(struct rds_mr *mr)
        unsigned long flags;
 
        rdsdebug("RDS: destroy mr key is %x refcnt %u\n",
-                       mr->r_key, refcount_read(&mr->r_refcount));
-
-       if (test_and_set_bit(RDS_MR_DEAD, &mr->r_state))
-               return;
+                mr->r_key, kref_read(&mr->r_kref));
 
        spin_lock_irqsave(&rs->rs_rdma_lock, flags);
        if (!RB_EMPTY_NODE(&mr->r_rb_node))
@@ -115,8 +112,10 @@ static void rds_destroy_mr(struct rds_mr *mr)
                mr->r_trans->free_mr(trans_private, mr->r_invalidate);
 }
 
-void __rds_put_mr_final(struct rds_mr *mr)
+void __rds_put_mr_final(struct kref *kref)
 {
+       struct rds_mr *mr = container_of(kref, struct rds_mr, r_kref);
+
        rds_destroy_mr(mr);
        kfree(mr);
 }
@@ -140,8 +139,7 @@ void rds_rdma_drop_keys(struct rds_sock *rs)
                rb_erase(&mr->r_rb_node, &rs->rs_rdma_keys);
                RB_CLEAR_NODE(&mr->r_rb_node);
                spin_unlock_irqrestore(&rs->rs_rdma_lock, flags);
-               rds_destroy_mr(mr);
-               rds_mr_put(mr);
+               kref_put(&mr->r_kref, __rds_put_mr_final);
                spin_lock_irqsave(&rs->rs_rdma_lock, flags);
        }
        spin_unlock_irqrestore(&rs->rs_rdma_lock, flags);
@@ -242,7 +240,7 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
                goto out;
        }
 
-       refcount_set(&mr->r_refcount, 1);
+       kref_init(&mr->r_kref);
        RB_CLEAR_NODE(&mr->r_rb_node);
        mr->r_trans = rs->rs_transport;
        mr->r_sock = rs;
@@ -343,7 +341,7 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
 
        rdsdebug("RDS: get_mr key is %x\n", mr->r_key);
        if (mr_ret) {
-               refcount_inc(&mr->r_refcount);
+               kref_get(&mr->r_kref);
                *mr_ret = mr;
        }
 
@@ -351,7 +349,7 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
 out:
        kfree(pages);
        if (mr)
-               rds_mr_put(mr);
+               kref_put(&mr->r_kref, __rds_put_mr_final);
        return ret;
 }
 
@@ -434,13 +432,7 @@ int rds_free_mr(struct rds_sock *rs, char __user *optval, int optlen)
        if (!mr)
                return -EINVAL;
 
-       /*
-        * call rds_destroy_mr() ourselves so that we're sure it's done by the time
-        * we return.  If we let rds_mr_put() do it it might not happen until
-        * someone else drops their ref.
-        */
-       rds_destroy_mr(mr);
-       rds_mr_put(mr);
+       kref_put(&mr->r_kref, __rds_put_mr_final);
        return 0;
 }
 
@@ -464,6 +456,14 @@ void rds_rdma_unuse(struct rds_sock *rs, u32 r_key, int force)
                return;
        }
 
+       /* Get a reference so that the MR won't go away before calling
+        * sync_mr() below.
+        */
+       kref_get(&mr->r_kref);
+
+       /* If it is going to be freed, remove it from the tree now so
+        * that no other thread can find it and free it.
+        */
        if (mr->r_use_once || force) {
                rb_erase(&mr->r_rb_node, &rs->rs_rdma_keys);
                RB_CLEAR_NODE(&mr->r_rb_node);
@@ -477,12 +477,13 @@ void rds_rdma_unuse(struct rds_sock *rs, u32 r_key, int force)
        if (mr->r_trans->sync_mr)
                mr->r_trans->sync_mr(mr->r_trans_private, DMA_FROM_DEVICE);
 
+       /* Release the reference held above. */
+       kref_put(&mr->r_kref, __rds_put_mr_final);
+
        /* If the MR was marked as invalidate, this will
         * trigger an async flush. */
-       if (zot_me) {
-               rds_destroy_mr(mr);
-               rds_mr_put(mr);
-       }
+       if (zot_me)
+               kref_put(&mr->r_kref, __rds_put_mr_final);
 }
 
 void rds_rdma_free_op(struct rm_rdma_op *ro)
@@ -490,7 +491,7 @@ void rds_rdma_free_op(struct rm_rdma_op *ro)
        unsigned int i;
 
        if (ro->op_odp_mr) {
-               rds_mr_put(ro->op_odp_mr);
+               kref_put(&ro->op_odp_mr->r_kref, __rds_put_mr_final);
        } else {
                for (i = 0; i < ro->op_nents; i++) {
                        struct page *page = sg_page(&ro->op_sg[i]);
@@ -664,9 +665,11 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
        op->op_odp_mr = NULL;
 
        WARN_ON(!nr_pages);
-       op->op_sg = rds_message_alloc_sgs(rm, nr_pages, &ret);
-       if (!op->op_sg)
+       op->op_sg = rds_message_alloc_sgs(rm, nr_pages);
+       if (IS_ERR(op->op_sg)) {
+               ret = PTR_ERR(op->op_sg);
                goto out_pages;
+       }
 
        if (op->op_notify || op->op_recverr) {
                /* We allocate an uninitialized notifier here, because
@@ -730,7 +733,7 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
                                goto out_pages;
                        }
                        RB_CLEAR_NODE(&local_odp_mr->r_rb_node);
-                       refcount_set(&local_odp_mr->r_refcount, 1);
+                       kref_init(&local_odp_mr->r_kref);
                        local_odp_mr->r_trans = rs->rs_transport;
                        local_odp_mr->r_sock = rs;
                        local_odp_mr->r_trans_private =
@@ -827,7 +830,7 @@ int rds_cmsg_rdma_dest(struct rds_sock *rs, struct rds_message *rm,
        if (!mr)
                err = -EINVAL;  /* invalid r_key */
        else
-               refcount_inc(&mr->r_refcount);
+               kref_get(&mr->r_kref);
        spin_unlock_irqrestore(&rs->rs_rdma_lock, flags);
 
        if (mr) {
@@ -905,9 +908,11 @@ int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm,
        rm->atomic.op_silent = !!(args->flags & RDS_RDMA_SILENT);
        rm->atomic.op_active = 1;
        rm->atomic.op_recverr = rs->rs_recverr;
-       rm->atomic.op_sg = rds_message_alloc_sgs(rm, 1, &ret);
-       if (!rm->atomic.op_sg)
+       rm->atomic.op_sg = rds_message_alloc_sgs(rm, 1);
+       if (IS_ERR(rm->atomic.op_sg)) {
+               ret = PTR_ERR(rm->atomic.op_sg);
                goto err;
+       }
 
        /* verify 8 byte-aligned */
        if (args->local_addr & 0x7) {
index e4a6035230836981a286b2b87ea09de361bff3a8..6019b0c004a9df23fbaafd614c8b03492485b294 100644 (file)
@@ -291,7 +291,7 @@ struct rds_incoming {
 
 struct rds_mr {
        struct rb_node          r_rb_node;
-       refcount_t              r_refcount;
+       struct kref             r_kref;
        u32                     r_key;
 
        /* A copy of the creation flags */
@@ -299,19 +299,11 @@ struct rds_mr {
        unsigned int            r_invalidate:1;
        unsigned int            r_write:1;
 
-       /* This is for RDS_MR_DEAD.
-        * It would be nice & consistent to make this part of the above
-        * bit field here, but we need to use test_and_set_bit.
-        */
-       unsigned long           r_state;
        struct rds_sock         *r_sock; /* back pointer to the socket that owns us */
        struct rds_transport    *r_trans;
        void                    *r_trans_private;
 };
 
-/* Flags for mr->r_state */
-#define RDS_MR_DEAD            0
-
 static inline rds_rdma_cookie_t rds_rdma_make_cookie(u32 r_key, u32 offset)
 {
        return r_key | (((u64) offset) << 32);
@@ -852,8 +844,7 @@ rds_conn_connecting(struct rds_connection *conn)
 
 /* message.c */
 struct rds_message *rds_message_alloc(unsigned int nents, gfp_t gfp);
-struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents,
-                                         int *ret);
+struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents);
 int rds_message_copy_from_user(struct rds_message *rm, struct iov_iter *from,
                               bool zcopy);
 struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned int total_len);
@@ -946,12 +937,7 @@ void rds_atomic_send_complete(struct rds_message *rm, int wc_status);
 int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm,
                    struct cmsghdr *cmsg);
 
-void __rds_put_mr_final(struct rds_mr *mr);
-static inline void rds_mr_put(struct rds_mr *mr)
-{
-       if (refcount_dec_and_test(&mr->r_refcount))
-               __rds_put_mr_final(mr);
-}
+void __rds_put_mr_final(struct kref *kref);
 
 static inline bool rds_destroy_pending(struct rds_connection *conn)
 {
index 82dcd8b84fe779ab42c4c81e5a7c1faf94c2158d..68e2bdb08fd099fd930d0ea66ae037af6a3ba8d2 100644 (file)
@@ -1274,9 +1274,11 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
 
        /* Attach data to the rm */
        if (payload_len) {
-               rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs, &ret);
-               if (!rm->data.op_sg)
+               rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs);
+               if (IS_ERR(rm->data.op_sg)) {
+                       ret = PTR_ERR(rm->data.op_sg);
                        goto out;
+               }
                ret = rds_message_copy_from_user(rm, &msg->msg_iter, zcopy);
                if (ret)
                        goto out;
index a6c1349e965d94c3ef6361c04298799a25a2f8c3..01135e54d95d2c6f7cffc3010e0c2ca7beb2761c 100644 (file)
@@ -165,15 +165,6 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
                        goto error;
                }
 
-               /* we want to set the don't fragment bit */
-               opt = IPV6_PMTUDISC_DO;
-               ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_MTU_DISCOVER,
-                                       (char *) &opt, sizeof(opt));
-               if (ret < 0) {
-                       _debug("setsockopt failed");
-                       goto error;
-               }
-
                /* Fall through and set IPv4 options too otherwise we don't get
                 * errors from IPv4 packets sent through the IPv6 socket.
                 */
index bad3d242034466d9b3a21b9d92bd26d30d829c4a..90e263c6aa69e441c5c9e1232bab6acc375a663b 100644 (file)
@@ -474,41 +474,21 @@ send_fragmentable:
        skb->tstamp = ktime_get_real();
 
        switch (conn->params.local->srx.transport.family) {
+       case AF_INET6:
        case AF_INET:
                opt = IP_PMTUDISC_DONT;
-               ret = kernel_setsockopt(conn->params.local->socket,
-                                       SOL_IP, IP_MTU_DISCOVER,
-                                       (char *)&opt, sizeof(opt));
-               if (ret == 0) {
-                       ret = kernel_sendmsg(conn->params.local->socket, &msg,
-                                            iov, 2, len);
-                       conn->params.peer->last_tx_at = ktime_get_seconds();
-
-                       opt = IP_PMTUDISC_DO;
-                       kernel_setsockopt(conn->params.local->socket, SOL_IP,
-                                         IP_MTU_DISCOVER,
-                                         (char *)&opt, sizeof(opt));
-               }
-               break;
-
-#ifdef CONFIG_AF_RXRPC_IPV6
-       case AF_INET6:
-               opt = IPV6_PMTUDISC_DONT;
-               ret = kernel_setsockopt(conn->params.local->socket,
-                                       SOL_IPV6, IPV6_MTU_DISCOVER,
-                                       (char *)&opt, sizeof(opt));
-               if (ret == 0) {
-                       ret = kernel_sendmsg(conn->params.local->socket, &msg,
-                                            iov, 2, len);
-                       conn->params.peer->last_tx_at = ktime_get_seconds();
-
-                       opt = IPV6_PMTUDISC_DO;
-                       kernel_setsockopt(conn->params.local->socket,
-                                         SOL_IPV6, IPV6_MTU_DISCOVER,
-                                         (char *)&opt, sizeof(opt));
-               }
+               kernel_setsockopt(conn->params.local->socket,
+                                 SOL_IP, IP_MTU_DISCOVER,
+                                 (char *)&opt, sizeof(opt));
+               ret = kernel_sendmsg(conn->params.local->socket, &msg,
+                                    iov, 2, len);
+               conn->params.peer->last_tx_at = ktime_get_seconds();
+
+               opt = IP_PMTUDISC_DO;
+               kernel_setsockopt(conn->params.local->socket,
+                                 SOL_IP, IP_MTU_DISCOVER,
+                                 (char *)&opt, sizeof(opt));
                break;
-#endif
 
        default:
                BUG();
index f6a3b969ead0d25e422a67121a4ba7d5bf26e1b6..0a7ecc292bd31b6dbbc98c2c8ef29d86745f7656 100644 (file)
@@ -1667,6 +1667,7 @@ int tcf_classify_ingress(struct sk_buff *skb,
                skb_ext_del(skb, TC_SKB_EXT);
 
                tp = rcu_dereference_bh(fchain->filter_chain);
+               last_executed_chain = fchain->index;
        }
 
        ret = __tcf_classify(skb, tp, orig_tp, res, compat_mode,
@@ -2069,6 +2070,7 @@ replay:
                err = PTR_ERR(block);
                goto errout;
        }
+       block->classid = parent;
 
        chain_index = tca[TCA_CHAIN] ? nla_get_u32(tca[TCA_CHAIN]) : 0;
        if (chain_index > TC_ACT_EXT_VAL_MASK) {
@@ -2611,12 +2613,10 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
                        return skb->len;
 
                parent = tcm->tcm_parent;
-               if (!parent) {
+               if (!parent)
                        q = dev->qdisc;
-                       parent = q->handle;
-               } else {
+               else
                        q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent));
-               }
                if (!q)
                        goto out;
                cops = q->ops->cl_ops;
@@ -2632,6 +2632,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
                block = cops->tcf_block(q, cl, NULL);
                if (!block)
                        goto out;
+               parent = block->classid;
                if (tcf_block_shared(block))
                        q = NULL;
        }
@@ -3522,6 +3523,16 @@ static void tcf_sample_get_group(struct flow_action_entry *entry,
 #endif
 }
 
+static enum flow_action_hw_stats tc_act_hw_stats(u8 hw_stats)
+{
+       if (WARN_ON_ONCE(hw_stats > TCA_ACT_HW_STATS_ANY))
+               return FLOW_ACTION_HW_STATS_DONT_CARE;
+       else if (!hw_stats)
+               return FLOW_ACTION_HW_STATS_DISABLED;
+
+       return hw_stats;
+}
+
 int tc_setup_flow_action(struct flow_action *flow_action,
                         const struct tcf_exts *exts)
 {
@@ -3545,7 +3556,7 @@ int tc_setup_flow_action(struct flow_action *flow_action,
                if (err)
                        goto err_out_locked;
 
-               entry->hw_stats = act->hw_stats;
+               entry->hw_stats = tc_act_hw_stats(act->hw_stats);
 
                if (is_tcf_gact_ok(act)) {
                        entry->id = FLOW_ACTION_ACCEPT;
@@ -3613,7 +3624,7 @@ int tc_setup_flow_action(struct flow_action *flow_action,
                                entry->mangle.mask = tcf_pedit_mask(act, k);
                                entry->mangle.val = tcf_pedit_val(act, k);
                                entry->mangle.offset = tcf_pedit_offset(act, k);
-                               entry->hw_stats = act->hw_stats;
+                               entry->hw_stats = tc_act_hw_stats(act->hw_stats);
                                entry = &flow_action->entries[++j];
                        }
                } else if (is_tcf_csum(act)) {
index a36974e9c601eca97ea98501f0c05f75d0a9fe3e..1bcf8fbfd40e4c56baddd8b8f0fe1bb804cc5b4e 100644 (file)
@@ -323,7 +323,8 @@ static void choke_reset(struct Qdisc *sch)
 
        sch->q.qlen = 0;
        sch->qstats.backlog = 0;
-       memset(q->tab, 0, (q->tab_mask + 1) * sizeof(struct sk_buff *));
+       if (q->tab)
+               memset(q->tab, 0, (q->tab_mask + 1) * sizeof(struct sk_buff *));
        q->head = q->tail = 0;
        red_restart(&q->vars);
 }
index b1da5589a0c6a2c9db9912430dca3d5f06fff10c..c48f91075b5c60ee4fe9e10186c913baf5894a69 100644 (file)
@@ -82,7 +82,7 @@ static bool is_packet_valid(struct Qdisc *sch, struct sk_buff *nskb)
        if (q->skip_sock_check)
                goto skip;
 
-       if (!sk)
+       if (!sk || !sk_fullsock(sk))
                return false;
 
        if (!sock_flag(sk, SOCK_TXTIME))
@@ -137,8 +137,9 @@ static void report_sock_error(struct sk_buff *skb, u32 err, u8 code)
        struct sock_exterr_skb *serr;
        struct sk_buff *clone;
        ktime_t txtime = skb->tstamp;
+       struct sock *sk = skb->sk;
 
-       if (!skb->sk || !(skb->sk->sk_txtime_report_errors))
+       if (!sk || !sk_fullsock(sk) || !(sk->sk_txtime_report_errors))
                return;
 
        clone = skb_clone(skb, GFP_ATOMIC);
@@ -154,7 +155,7 @@ static void report_sock_error(struct sk_buff *skb, u32 err, u8 code)
        serr->ee.ee_data = (txtime >> 32); /* high part of tstamp */
        serr->ee.ee_info = txtime; /* low part of tstamp */
 
-       if (sock_queue_err_skb(skb->sk, clone))
+       if (sock_queue_err_skb(sk, clone))
                kfree_skb(clone);
 }
 
index 968519ff36e97734e495d90331d3e3197660b8f6..436160be9c180ceedaeb74126e40c7e24bf7ccba 100644 (file)
@@ -416,7 +416,7 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
                q->quantum = max(256U, nla_get_u32(tb[TCA_FQ_CODEL_QUANTUM]));
 
        if (tb[TCA_FQ_CODEL_DROP_BATCH_SIZE])
-               q->drop_batch_size = min(1U, nla_get_u32(tb[TCA_FQ_CODEL_DROP_BATCH_SIZE]));
+               q->drop_batch_size = max(1U, nla_get_u32(tb[TCA_FQ_CODEL_DROP_BATCH_SIZE]));
 
        if (tb[TCA_FQ_CODEL_MEMORY_LIMIT])
                q->memory_limit = min(1U << 31, nla_get_u32(tb[TCA_FQ_CODEL_MEMORY_LIMIT]));
index c787d4d46017b4b41b8eb6d41f2b0a44560ff5bf..5a6def5e4e6df2e7b66c88aa877c7318270d48be 100644 (file)
@@ -637,6 +637,15 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
        if (ctl->divisor &&
            (!is_power_of_2(ctl->divisor) || ctl->divisor > 65536))
                return -EINVAL;
+
+       /* slot->allot is a short, make sure quantum is not too big. */
+       if (ctl->quantum) {
+               unsigned int scaled = SFQ_ALLOT_SIZE(ctl->quantum);
+
+               if (scaled <= 0 || scaled > SHRT_MAX)
+                       return -EINVAL;
+       }
+
        if (ctl_v1 && !red_check_params(ctl_v1->qth_min, ctl_v1->qth_max,
                                        ctl_v1->Wlog))
                return -EINVAL;
index 0fb10abf757962c1e3e6feb8c68dedd9a1808f1b..7a5e4c454715617cb57c6db7de7fdaa9e6886d40 100644 (file)
@@ -169,6 +169,9 @@ static int skbprio_change(struct Qdisc *sch, struct nlattr *opt,
 {
        struct tc_skbprio_qopt *ctl = nla_data(opt);
 
+       if (opt->nla_len != nla_attr_size(sizeof(*ctl)))
+               return -EINVAL;
+
        sch->limit = ctl->limit;
        return 0;
 }
index 09050c1d5517e7b9269314423a550f2202cd6051..f7cb0b7faec2327ea803d5159eea22fe9f612c2f 100644 (file)
@@ -858,7 +858,11 @@ struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc,
        struct sctp_chunk *retval;
        __u32 ctsn;
 
-       ctsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map);
+       if (chunk && chunk->asoc)
+               ctsn = sctp_tsnmap_get_ctsn(&chunk->asoc->peer.tsn_map);
+       else
+               ctsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map);
+
        shut.cum_tsn_ack = htonl(ctsn);
 
        retval = sctp_make_control(asoc, SCTP_CID_SHUTDOWN, 0,
index 6a16af4b1ef61810fed8a04169109f311b070575..26788f4a3b9eb66091e03dec907a8b4e4ddc8554 100644 (file)
@@ -1865,7 +1865,7 @@ static enum sctp_disposition sctp_sf_do_dupcook_a(
                 */
                sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
                return sctp_sf_do_9_2_start_shutdown(net, ep, asoc,
-                                                    SCTP_ST_CHUNK(0), NULL,
+                                                    SCTP_ST_CHUNK(0), repl,
                                                     commands);
        } else {
                sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
@@ -5470,7 +5470,7 @@ enum sctp_disposition sctp_sf_do_9_2_start_shutdown(
         * in the Cumulative TSN Ack field the last sequential TSN it
         * has received from the peer.
         */
-       reply = sctp_make_shutdown(asoc, NULL);
+       reply = sctp_make_shutdown(asoc, arg);
        if (!reply)
                goto nomem;
 
@@ -6068,7 +6068,7 @@ enum sctp_disposition sctp_sf_autoclose_timer_expire(
        disposition = SCTP_DISPOSITION_CONSUME;
        if (sctp_outq_is_empty(&asoc->outqueue)) {
                disposition = sctp_sf_do_9_2_start_shutdown(net, ep, asoc, type,
-                                                           arg, commands);
+                                                           NULL, commands);
        }
 
        return disposition;
index af0ddd28b081cd166b4dc4339bfdcc0f548a6256..baef5ee43dbbdb3fbc9b5bdf780a585e8d877404 100644 (file)
@@ -529,7 +529,6 @@ void cache_purge(struct cache_detail *detail)
 {
        struct cache_head *ch = NULL;
        struct hlist_head *head = NULL;
-       struct hlist_node *tmp = NULL;
        int i = 0;
 
        spin_lock(&detail->hash_lock);
@@ -541,7 +540,9 @@ void cache_purge(struct cache_detail *detail)
        dprintk("RPC: %d entries in %s cache\n", detail->entries, detail->name);
        for (i = 0; i < detail->hash_size; i++) {
                head = &detail->hash_table[i];
-               hlist_for_each_entry_safe(ch, tmp, head, cache_list) {
+               while (!hlist_empty(head)) {
+                       ch = hlist_entry(head->first, struct cache_head,
+                                        cache_list);
                        sunrpc_begin_cache_remove_entry(ch, detail);
                        spin_unlock(&detail->hash_lock);
                        sunrpc_end_cache_remove_entry(ch, detail);
index 325a0858700f6c4eba5d9a0c0fe1c7800d42d541..8350d3a2e9a72309b8238bac4be3e5c603d57a1d 100644 (file)
@@ -880,6 +880,20 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client);
 /*
  * Free an RPC client
  */
+static void rpc_free_client_work(struct work_struct *work)
+{
+       struct rpc_clnt *clnt = container_of(work, struct rpc_clnt, cl_work);
+
+       /* These might block on processes that might allocate memory,
+        * so they cannot be called in rpciod, so they are handled separately
+        * here.
+        */
+       rpc_clnt_debugfs_unregister(clnt);
+       rpc_clnt_remove_pipedir(clnt);
+
+       kfree(clnt);
+       rpciod_down();
+}
 static struct rpc_clnt *
 rpc_free_client(struct rpc_clnt *clnt)
 {
@@ -890,17 +904,16 @@ rpc_free_client(struct rpc_clnt *clnt)
                        rcu_dereference(clnt->cl_xprt)->servername);
        if (clnt->cl_parent != clnt)
                parent = clnt->cl_parent;
-       rpc_clnt_debugfs_unregister(clnt);
-       rpc_clnt_remove_pipedir(clnt);
        rpc_unregister_client(clnt);
        rpc_free_iostats(clnt->cl_metrics);
        clnt->cl_metrics = NULL;
        xprt_put(rcu_dereference_raw(clnt->cl_xprt));
        xprt_iter_destroy(&clnt->cl_xpi);
-       rpciod_down();
        put_cred(clnt->cl_cred);
        rpc_free_clid(clnt);
-       kfree(clnt);
+
+       INIT_WORK(&clnt->cl_work, rpc_free_client_work);
+       schedule_work(&clnt->cl_work);
        return parent;
 }
 
@@ -2808,8 +2821,7 @@ int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt,
        task = rpc_call_null_helper(clnt, xprt, NULL,
                        RPC_TASK_SOFT|RPC_TASK_SOFTCONN|RPC_TASK_ASYNC|RPC_TASK_NULLCREDS,
                        &rpc_cb_add_xprt_call_ops, data);
-       if (IS_ERR(task))
-               return PTR_ERR(task);
+
        rpc_put_task(task);
 success:
        return 1;
index e27e3532ec7567a9b4e3dd07f158c26f58aafb64..2284ff038dadb9f9b7f505e8a07eb49c33e79f62 100644 (file)
@@ -908,9 +908,6 @@ int svc_send(struct svc_rqst *rqstp)
        if (!xprt)
                goto out;
 
-       /* release the receive skb before sending the reply */
-       xprt->xpt_ops->xpo_release_rqst(rqstp);
-
        /* calculate over-all length */
        xb = &rqstp->rq_res;
        xb->len = xb->head[0].iov_len +
@@ -1040,6 +1037,8 @@ static void svc_delete_xprt(struct svc_xprt *xprt)
 
        dprintk("svc: svc_delete_xprt(%p)\n", xprt);
        xprt->xpt_ops->xpo_detach(xprt);
+       if (xprt->xpt_bc_xprt)
+               xprt->xpt_bc_xprt->ops->close(xprt->xpt_bc_xprt);
 
        spin_lock_bh(&serv->sv_lock);
        list_del_init(&xprt->xpt_list);
index 519cf9c4f8fd8bf46539c8b0ddca293838fde26a..023514e392b3106d4bec9867510f3279676637e6 100644 (file)
@@ -527,6 +527,8 @@ static int svc_udp_sendto(struct svc_rqst *rqstp)
        unsigned int uninitialized_var(sent);
        int err;
 
+       svc_release_udp_skb(rqstp);
+
        svc_set_cmsg_data(rqstp, cmh);
 
        err = xprt_sock_sendmsg(svsk->sk_sock, &msg, xdr, 0, 0, &sent);
@@ -1076,6 +1078,8 @@ static int svc_tcp_sendto(struct svc_rqst *rqstp)
        unsigned int uninitialized_var(sent);
        int err;
 
+       svc_release_skb(rqstp);
+
        err = xprt_sock_sendmsg(svsk->sk_sock, &msg, xdr, 0, marker, &sent);
        xdr_free_bvec(xdr);
        if (err < 0 || sent != (xdr->len + sizeof(marker)))
index 4a81e6995d3e46442e68d97fbdd0cc1344255f11..3c627dc685cc85e5f415e2248d2ac95d416b84c4 100644 (file)
@@ -388,7 +388,9 @@ static int rpcrdma_encode_read_list(struct rpcrdma_xprt *r_xprt,
        } while (nsegs);
 
 done:
-       return xdr_stream_encode_item_absent(xdr);
+       if (xdr_stream_encode_item_absent(xdr) < 0)
+               return -EMSGSIZE;
+       return 0;
 }
 
 /* Register and XDR encode the Write list. Supports encoding a list
@@ -454,7 +456,9 @@ static int rpcrdma_encode_write_list(struct rpcrdma_xprt *r_xprt,
        *segcount = cpu_to_be32(nchunks);
 
 done:
-       return xdr_stream_encode_item_absent(xdr);
+       if (xdr_stream_encode_item_absent(xdr) < 0)
+               return -EMSGSIZE;
+       return 0;
 }
 
 /* Register and XDR encode the Reply chunk. Supports encoding an array
@@ -480,8 +484,11 @@ static int rpcrdma_encode_reply_chunk(struct rpcrdma_xprt *r_xprt,
        int nsegs, nchunks;
        __be32 *segcount;
 
-       if (wtype != rpcrdma_replych)
-               return xdr_stream_encode_item_absent(xdr);
+       if (wtype != rpcrdma_replych) {
+               if (xdr_stream_encode_item_absent(xdr) < 0)
+                       return -EMSGSIZE;
+               return 0;
+       }
 
        seg = req->rl_segments;
        nsegs = rpcrdma_convert_iovs(r_xprt, &rqst->rq_rcv_buf, 0, wtype, seg);
index d510a3a15d4be9d169598da0a06db896357190a0..af7eb8d202ae70fceffe554d184e27f9348dcc05 100644 (file)
@@ -244,6 +244,8 @@ static void
 xprt_rdma_bc_close(struct rpc_xprt *xprt)
 {
        dprintk("svcrdma: %s: xprt %p\n", __func__, xprt);
+
+       xprt_disconnect_done(xprt);
        xprt->cwnd = RPC_CWNDSHIFT;
 }
 
index 54469b72b25f3cf067d78d14daa1b1b5a58b58e5..efa5fcb5793f710cdd6d8eabe5a1353849f44db9 100644 (file)
@@ -223,6 +223,26 @@ void svc_rdma_recv_ctxt_put(struct svcxprt_rdma *rdma,
                svc_rdma_recv_ctxt_destroy(rdma, ctxt);
 }
 
+/**
+ * svc_rdma_release_rqst - Release transport-specific per-rqst resources
+ * @rqstp: svc_rqst being released
+ *
+ * Ensure that the recv_ctxt is released whether or not a Reply
+ * was sent. For example, the client could close the connection,
+ * or svc_process could drop an RPC, before the Reply is sent.
+ */
+void svc_rdma_release_rqst(struct svc_rqst *rqstp)
+{
+       struct svc_rdma_recv_ctxt *ctxt = rqstp->rq_xprt_ctxt;
+       struct svc_xprt *xprt = rqstp->rq_xprt;
+       struct svcxprt_rdma *rdma =
+               container_of(xprt, struct svcxprt_rdma, sc_xprt);
+
+       rqstp->rq_xprt_ctxt = NULL;
+       if (ctxt)
+               svc_rdma_recv_ctxt_put(rdma, ctxt);
+}
+
 static int __svc_rdma_post_recv(struct svcxprt_rdma *rdma,
                                struct svc_rdma_recv_ctxt *ctxt)
 {
@@ -820,6 +840,8 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp)
        __be32 *p;
        int ret;
 
+       rqstp->rq_xprt_ctxt = NULL;
+
        spin_lock(&rdma_xprt->sc_rq_dto_lock);
        ctxt = svc_rdma_next_recv_ctxt(&rdma_xprt->sc_read_complete_q);
        if (ctxt) {
index bd7c195d872ec0036ae0fee4f81747a0a34e7925..23c2d3ce0dc9a01d162a84f4aba6e607f34a05cf 100644 (file)
@@ -323,8 +323,6 @@ static int svc_rdma_post_chunk_ctxt(struct svc_rdma_chunk_ctxt *cc)
                if (atomic_sub_return(cc->cc_sqecount,
                                      &rdma->sc_sq_avail) > 0) {
                        ret = ib_post_send(rdma->sc_qp, first_wr, &bad_wr);
-                       trace_svcrdma_post_rw(&cc->cc_cqe,
-                                             cc->cc_sqecount, ret);
                        if (ret)
                                break;
                        return 0;
@@ -337,6 +335,7 @@ static int svc_rdma_post_chunk_ctxt(struct svc_rdma_chunk_ctxt *cc)
                trace_svcrdma_sq_retry(rdma);
        } while (1);
 
+       trace_svcrdma_sq_post_err(rdma, ret);
        set_bit(XPT_CLOSE, &xprt->xpt_flags);
 
        /* If even one was posted, there will be a completion. */
index 90cba3058f04cf40f69985ad01ee631982331f5c..b6c8643867f2cc943a16de17f70bcb8033e421c4 100644 (file)
@@ -322,15 +322,17 @@ int svc_rdma_send(struct svcxprt_rdma *rdma, struct ib_send_wr *wr)
                }
 
                svc_xprt_get(&rdma->sc_xprt);
+               trace_svcrdma_post_send(wr);
                ret = ib_post_send(rdma->sc_qp, wr, NULL);
-               trace_svcrdma_post_send(wr, ret);
-               if (ret) {
-                       set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
-                       svc_xprt_put(&rdma->sc_xprt);
-                       wake_up(&rdma->sc_send_wait);
-               }
-               break;
+               if (ret)
+                       break;
+               return 0;
        }
+
+       trace_svcrdma_sq_post_err(rdma, ret);
+       set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
+       svc_xprt_put(&rdma->sc_xprt);
+       wake_up(&rdma->sc_send_wait);
        return ret;
 }
 
@@ -924,12 +926,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
        ret = svc_rdma_send_reply_msg(rdma, sctxt, rctxt, rqstp);
        if (ret < 0)
                goto err1;
-       ret = 0;
-
-out:
-       rqstp->rq_xprt_ctxt = NULL;
-       svc_rdma_recv_ctxt_put(rdma, rctxt);
-       return ret;
+       return 0;
 
  err2:
        if (ret != -E2BIG && ret != -EINVAL)
@@ -938,16 +935,14 @@ out:
        ret = svc_rdma_send_error_msg(rdma, sctxt, rqstp);
        if (ret < 0)
                goto err1;
-       ret = 0;
-       goto out;
+       return 0;
 
  err1:
        svc_rdma_send_ctxt_put(rdma, sctxt);
  err0:
        trace_svcrdma_send_failed(rqstp, ret);
        set_bit(XPT_CLOSE, &xprt->xpt_flags);
-       ret = -ENOTCONN;
-       goto out;
+       return -ENOTCONN;
 }
 
 /**
index 8bb99980ae8562eb4ba4a62f7f2d5ee7f63c0887..ea54785db4f8fb60bece91da79e16aec93dce7ca 100644 (file)
@@ -71,7 +71,6 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,
                                        struct sockaddr *sa, int salen,
                                        int flags);
 static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt);
-static void svc_rdma_release_rqst(struct svc_rqst *);
 static void svc_rdma_detach(struct svc_xprt *xprt);
 static void svc_rdma_free(struct svc_xprt *xprt);
 static int svc_rdma_has_wspace(struct svc_xprt *xprt);
@@ -552,10 +551,6 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
        return NULL;
 }
 
-static void svc_rdma_release_rqst(struct svc_rqst *rqstp)
-{
-}
-
 /*
  * When connected, an svc_xprt has at least two references:
  *
index cdd84c09df10b4a218953c0f07287ca7cec95cb9..05c4d3a9cda27fc6971bb40d0f088e76acd93df4 100644 (file)
@@ -289,6 +289,7 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
        case RDMA_CM_EVENT_DISCONNECTED:
                ep->re_connect_status = -ECONNABORTED;
 disconnected:
+               xprt_force_disconnect(xprt);
                return rpcrdma_ep_destroy(ep);
        default:
                break;
@@ -1355,8 +1356,8 @@ int rpcrdma_post_sends(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
                --ep->re_send_count;
        }
 
+       trace_xprtrdma_post_send(req);
        rc = frwr_send(r_xprt, req);
-       trace_xprtrdma_post_send(req, rc);
        if (rc)
                return -ENOTCONN;
        return 0;
index 0bda8a73e8a86ea99ff5c04192a4624752d8a067..845d0be805ece18da98e87886c08595d18252d65 100644 (file)
@@ -2584,6 +2584,7 @@ static int bc_send_request(struct rpc_rqst *req)
 
 static void bc_close(struct rpc_xprt *xprt)
 {
+       xprt_disconnect_done(xprt);
 }
 
 /*
index c8c47fc7265361229c9e19f7e46eeb840089d93d..8c47ded2edb6143d3a79782e5f8404546a726ac4 100644 (file)
@@ -1712,6 +1712,7 @@ exit:
        case -EBUSY:
                this_cpu_inc(stats->stat[STAT_ASYNC]);
                *skb = NULL;
+               tipc_aead_put(aead);
                return rc;
        default:
                this_cpu_inc(stats->stat[STAT_NOK]);
index 467c53a1fb5cf2a5d98513853024d3c6a61ab4a9..d4675e922a8f717682f465fd2c5664ba6bc1e878 100644 (file)
@@ -1065,7 +1065,7 @@ static void tipc_link_update_cwin(struct tipc_link *l, int released,
        /* Enter fast recovery */
        if (unlikely(retransmitted)) {
                l->ssthresh = max_t(u16, l->window / 2, 300);
-               l->window = l->ssthresh;
+               l->window = min_t(u16, l->ssthresh, l->window);
                return;
        }
        /* Enter slow start */
index 10292c942384dbb0fc51e9f931bd25fbacfeab6a..803a3a6d0f50245023f3d179c025aaefc5963577 100644 (file)
@@ -2038,6 +2038,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b)
                n = tipc_node_find_by_id(net, ehdr->id);
        }
        tipc_crypto_rcv(net, (n) ? n->crypto_rx : NULL, &skb, b);
+       tipc_node_put(n);
        if (!skb)
                return;
 
@@ -2090,7 +2091,7 @@ rcv:
        /* Check/update node state before receiving */
        if (unlikely(skb)) {
                if (unlikely(skb_linearize(skb)))
-                       goto discard;
+                       goto out_node_put;
                tipc_node_write_lock(n);
                if (tipc_node_check_state(n, skb, bearer_id, &xmitq)) {
                        if (le->link) {
@@ -2119,6 +2120,7 @@ rcv:
        if (!skb_queue_empty(&xmitq))
                tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr, n);
 
+out_node_put:
        tipc_node_put(n);
 discard:
        kfree_skb(skb);
index 3a12fc18239b8184526b027ee9b3afce5893f717..73dbed0c4b6b8dd5fa4ee484208349b9f7a85455 100644 (file)
@@ -402,10 +402,11 @@ static int tipc_conn_rcv_from_sock(struct tipc_conn *con)
                read_lock_bh(&sk->sk_callback_lock);
                ret = tipc_conn_rcv_sub(srv, con, &s);
                read_unlock_bh(&sk->sk_callback_lock);
+               if (!ret)
+                       return 0;
        }
-       if (ret < 0)
-               tipc_conn_close(con);
 
+       tipc_conn_close(con);
        return ret;
 }
 
index 156efce50dbd10e134e13ba28afc802f78e9a4b5..0e989005bdc2126390d5491af5c42632b1e2373c 100644 (file)
@@ -56,9 +56,9 @@ enum {
        TLS_NUM_PROTS,
 };
 
-static struct proto *saved_tcpv6_prot;
+static const struct proto *saved_tcpv6_prot;
 static DEFINE_MUTEX(tcpv6_prot_mutex);
-static struct proto *saved_tcpv4_prot;
+static const struct proto *saved_tcpv4_prot;
 static DEFINE_MUTEX(tcpv4_prot_mutex);
 static struct proto tls_prots[TLS_NUM_PROTS][TLS_NUM_CONFIG][TLS_NUM_CONFIG];
 static struct proto_ops tls_sw_proto_ops;
index c98e602a1a2ded6f90743723445dd4b4a6a3a4c2..e23f94a5549b878ee3f9c75860425fbf3c632dbe 100644 (file)
@@ -800,6 +800,8 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk,
                        *copied -= sk_msg_free(sk, msg);
                        tls_free_open_rec(sk);
                }
+               if (psock)
+                       sk_psock_put(sk, psock);
                return err;
        }
 more_data:
@@ -2081,8 +2083,9 @@ static void tls_data_ready(struct sock *sk)
        strp_data_ready(&ctx->strp);
 
        psock = sk_psock_get(sk);
-       if (psock && !list_empty(&psock->ingress_msg)) {
-               ctx->saved_data_ready(sk);
+       if (psock) {
+               if (!list_empty(&psock->ingress_msg))
+                       ctx->saved_data_ready(sk);
                sk_psock_put(sk, psock);
        }
 }
index 709038a4783e526d5c108c87b69c65202d2aff86..69efc891885f6ef3c309bdf8a718983b5c299561 100644 (file)
@@ -157,7 +157,11 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque)
 
 void virtio_transport_deliver_tap_pkt(struct virtio_vsock_pkt *pkt)
 {
+       if (pkt->tap_delivered)
+               return;
+
        vsock_deliver_tap(virtio_transport_build_skb, pkt);
+       pkt->tap_delivered = true;
 }
 EXPORT_SYMBOL_GPL(virtio_transport_deliver_tap_pkt);
 
index 5fa402144cda460cf4ec8dee94d22cc4059f068e..692bcd35f8094e85758f529e24459d2d10fd7368 100644 (file)
@@ -644,10 +644,8 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_HE_CAPABILITY] = { .type = NLA_BINARY,
                                         .len = NL80211_HE_MAX_CAPABILITY_LEN },
 
-       [NL80211_ATTR_FTM_RESPONDER] = {
-               .type = NLA_NESTED,
-               .validation_data = nl80211_ftm_responder_policy,
-       },
+       [NL80211_ATTR_FTM_RESPONDER] =
+               NLA_POLICY_NESTED(nl80211_ftm_responder_policy),
        [NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
        [NL80211_ATTR_PEER_MEASUREMENTS] =
                NLA_POLICY_NESTED(nl80211_pmsr_attr_policy),
index 00e782335cb0740daa172f0c1835bcc3285ba46b..25bf72ee6cad070804f26ab353b5192a8ebbf923 100644 (file)
@@ -115,8 +115,10 @@ int x25_lapb_receive_frame(struct sk_buff *skb, struct net_device *dev,
                goto drop;
        }
 
-       if (!pskb_may_pull(skb, 1))
+       if (!pskb_may_pull(skb, 1)) {
+               x25_neigh_put(nb);
                return 0;
+       }
 
        switch (skb->data[0]) {
 
index 8aa415a38814b1545e73b89ef128aa4e4276885f..0285aaa1e93c17233748d38eef6d8b5c6059b67a 100644 (file)
@@ -357,6 +357,12 @@ void x25_disconnect(struct sock *sk, int reason, unsigned char cause,
                sk->sk_state_change(sk);
                sock_set_flag(sk, SOCK_DEAD);
        }
+       if (x25->neighbour) {
+               read_lock_bh(&x25_list_lock);
+               x25_neigh_put(x25->neighbour);
+               x25->neighbour = NULL;
+               read_unlock_bh(&x25_list_lock);
+       }
 }
 
 /*
index fa7bb5e060d0c1bc29053fef34debbfc683c8be5..ed7a6060f73cadc9c0b812898be9132387a70846 100644 (file)
@@ -343,7 +343,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
        u32 chunk_size = mr->chunk_size, headroom = mr->headroom;
        unsigned int chunks, chunks_per_page;
        u64 addr = mr->addr, size = mr->len;
-       int size_chk, err;
+       int err;
 
        if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) {
                /* Strictly speaking we could support this, if:
@@ -382,8 +382,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
                        return -EINVAL;
        }
 
-       size_chk = chunk_size - headroom - XDP_PACKET_HEADROOM;
-       if (size_chk < 0)
+       if (headroom >= chunk_size - XDP_PACKET_HEADROOM)
                return -EINVAL;
 
        umem->address = (unsigned long)addr;
index 356f90e4522b4cc39bf05ae4765d0517c43e5dc4..c350108aa38de784b2652bffcc1732191e93ed88 100644 (file)
@@ -131,8 +131,9 @@ static void __xsk_rcv_memcpy(struct xdp_umem *umem, u64 addr, void *from_buf,
                u64 page_start = addr & ~(PAGE_SIZE - 1);
                u64 first_len = PAGE_SIZE - (addr - page_start);
 
-               memcpy(to_buf, from_buf, first_len + metalen);
-               memcpy(next_pg_addr, from_buf + first_len, len - first_len);
+               memcpy(to_buf, from_buf, first_len);
+               memcpy(next_pg_addr, from_buf + first_len,
+                      len + metalen - first_len);
 
                return;
        }
index 80b4a70315b68f2758a2e126236280a2fa799fa3..13a35f7cbe661cfb3aa5334346417e20a2fe92f0 100644 (file)
@@ -416,7 +416,7 @@ TRACE_EVENT_FN(foo_bar_with_fn,
  * Note, TRACE_EVENT() itself is simply defined as:
  *
  * #define TRACE_EVENT(name, proto, args, tstruct, assign, printk)  \
- *  DEFINE_EVENT_CLASS(name, proto, args, tstruct, assign, printk); \
+ *  DECLARE_EVENT_CLASS(name, proto, args, tstruct, assign, printk); \
  *  DEFINE_EVENT(name, name, proto, args)
  *
  * The DEFINE_EVENT() also can be declared with conditions and reg functions:
index cc86bf6566e42aa4326c45f34d10592041133510..9894693f3be17817345afd206e277d4e9421f41f 100644 (file)
@@ -418,7 +418,7 @@ static int mdpy_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
                return -EINVAL;
 
        return remap_vmalloc_range_partial(vma, vma->vm_start,
-                                          mdev_state->memblk,
+                                          mdev_state->memblk, 0,
                                           vma->vm_end - vma->vm_start);
 }
 
index 97547108ee7fdb8b20f55280db7d6bd17e1e60f1..4b799737722c89f670d763bef0146685fb333b96 100644 (file)
@@ -309,7 +309,7 @@ define rule_dtc
 endef
 
 $(obj)/%.dt.yaml: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE
-       $(call if_changed_rule,dtc)
+       $(call if_changed_rule,dtc,yaml)
 
 dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
 
index d64c67b67e3c7b76073798f2959ee5ef41206f1b..eac40f0abd56a9f4700423664824da8a537bfd61 100755 (executable)
@@ -479,7 +479,7 @@ our $allocFunctions = qr{(?x:
                (?:kv|k|v)[czm]alloc(?:_node|_array)? |
                kstrdup(?:_const)? |
                kmemdup(?:_nul)?) |
-       (?:\w+)?alloc_skb(?:ip_align)? |
+       (?:\w+)?alloc_skb(?:_ip_align)? |
                                # dev_alloc_skb/netdev_alloc_skb, et al
        dma_alloc_coherent
 )};
index e0e39826dae90ab735d1510e882bd32a9536e005..eee5b7f3a092ae4ac46bcdf92ffe8bb3c643aafd 100755 (executable)
@@ -7,6 +7,9 @@ myname=${0##*/}
 # If no prefix forced, use the default CONFIG_
 CONFIG_="${CONFIG_-CONFIG_}"
 
+# We use an uncommon delimiter for sed substitutions
+SED_DELIM=$(echo -en "\001")
+
 usage() {
        cat >&2 <<EOL
 Manipulate options in a .config file from the command line.
@@ -83,7 +86,7 @@ txt_subst() {
        local infile="$3"
        local tmpfile="$infile.swp"
 
-       sed -e "s:$before:$after:" "$infile" >"$tmpfile"
+       sed -e "s$SED_DELIM$before$SED_DELIM$after$SED_DELIM" "$infile" >"$tmpfile"
        # replace original file with the edited one
        mv "$tmpfile" "$infile"
 }
index ba8b8d5834e67922e0028dbec04b9e7cebc2766d..fbdb325cdf4f09e8fe34c76de9e2d1c26a82d41b 100755 (executable)
@@ -126,7 +126,7 @@ faultlinenum=$(( $(wc -l $T.oo  | cut -d" " -f1) - \
 faultline=`cat $T.dis | head -1 | cut -d":" -f2-`
 faultline=`echo "$faultline" | sed -e 's/\[/\\\[/g; s/\]/\\\]/g'`
 
-cat $T.oo | sed -e "${faultlinenum}s/^\(.*:\)\(.*\)/\1\*\2\t\t<-- trapping instruction/"
+cat $T.oo | sed -e "${faultlinenum}s/^\([^:]*:\)\(.*\)/\1\*\2\t\t<-- trapping instruction/"
 echo
 cat $T.aa
 cleanup
index 9a8cc10cffd0b03522f4781fd0ac3ad83586b569..c71832b2312b94ba31ef060860bb9c6c04717183 100755 (executable)
@@ -25,7 +25,7 @@ my $fix = 0;
 my $warn = 0;
 
 if (! -d ".git") {
-       printf "Warning: can't check if file exists, as this is not a git tree";
+       printf "Warning: can't check if file exists, as this is not a git tree\n";
        exit 0;
 }
 
index 2f3c3a7e1620fb205767ae2f7d8dd32100f92547..ef85f8b7d4a76ebcd0bed42be4f8105eae42a15f 100644 (file)
@@ -13,7 +13,7 @@ dtc-objs      += dtc-lexer.lex.o dtc-parser.tab.o
 HOST_EXTRACFLAGS := -I $(srctree)/$(src)/libfdt
 
 ifeq ($(shell pkg-config --exists yaml-0.1 2>/dev/null && echo yes),)
-ifneq ($(CHECK_DTBS),)
+ifneq ($(CHECK_DT_BINDING)$(CHECK_DTBS),)
 $(error dtc needs libyaml for DT schema validation support. \
        Install the necessary libyaml development package.)
 endif
index f22858b2c3d695b28f9e9ad15f48c07ed8dfdeb9..80f354289eeb9423e5b6f0cb40845682e371668d 100644 (file)
@@ -4,6 +4,7 @@ GCC_PLUGINS_DIR := $(shell $(CC) -print-file-name=plugin)
 HOST_EXTRACXXFLAGS += -I$(GCC_PLUGINS_DIR)/include -I$(src) -std=gnu++98 -fno-rtti
 HOST_EXTRACXXFLAGS += -fno-exceptions -fasynchronous-unwind-tables -ggdb
 HOST_EXTRACXXFLAGS += -Wno-narrowing -Wno-unused-variable -Wno-c++11-compat
+HOST_EXTRACXXFLAGS += -Wno-format-diag
 
 $(obj)/randomize_layout_plugin.o: $(objtree)/$(obj)/randomize_layout_seed.h
 quiet_cmd_create_randomize_layout_seed = GENSEED $@
index 17f06079a71231180cb0fd5a4d096c15841a8e01..9ad76b7f3f10e71fc04c4a64196388ffe4e40481 100644 (file)
@@ -35,7 +35,9 @@
 #include "ggc.h"
 #include "timevar.h"
 
+#if BUILDING_GCC_VERSION < 10000
 #include "params.h"
+#endif
 
 #if BUILDING_GCC_VERSION <= 4009
 #include "pointer-set.h"
@@ -847,6 +849,7 @@ static inline gimple gimple_build_assign_with_ops(enum tree_code subcode, tree l
        return gimple_build_assign(lhs, subcode, op1, op2 PASS_MEM_STAT);
 }
 
+#if BUILDING_GCC_VERSION < 10000
 template <>
 template <>
 inline bool is_a_helper<const ggoto *>::test(const_gimple gs)
@@ -860,6 +863,7 @@ inline bool is_a_helper<const greturn *>::test(const_gimple gs)
 {
        return gs->code == GIMPLE_RETURN;
 }
+#endif
 
 static inline gasm *as_a_gasm(gimple stmt)
 {
index dbd37460c573ec549fe33c7015f77206f4485064..cc75eeba0be1015fde86c981dfc1b3b02e99ff8e 100644 (file)
@@ -51,7 +51,6 @@ static void stackleak_add_track_stack(gimple_stmt_iterator *gsi, bool after)
        gimple stmt;
        gcall *stackleak_track_stack;
        cgraph_node_ptr node;
-       int frequency;
        basic_block bb;
 
        /* Insert call to void stackleak_track_stack(void) */
@@ -68,9 +67,9 @@ static void stackleak_add_track_stack(gimple_stmt_iterator *gsi, bool after)
        bb = gimple_bb(stackleak_track_stack);
        node = cgraph_get_create_node(track_function_decl);
        gcc_assert(node);
-       frequency = compute_call_stmt_bb_frequency(current_function_decl, bb);
        cgraph_create_edge(cgraph_get_node(current_function_decl), node,
-                       stackleak_track_stack, bb->count, frequency);
+                       stackleak_track_stack, bb->count,
+                       compute_call_stmt_bb_frequency(current_function_decl, bb));
 }
 
 static bool is_alloca(gimple stmt)
index 39db889b874c9e59136f626519514dec6c246962..c4b99160791785e5b346b0a86e8cb4e28f182b2d 100644 (file)
@@ -12,7 +12,7 @@ rb_node_type = utils.CachedType("struct rb_node")
 
 def rb_first(root):
     if root.type == rb_root_type.get_type():
-        node = node.address.cast(rb_root_type.get_type().pointer())
+        node = root.address.cast(rb_root_type.get_type().pointer())
     elif root.type != rb_root_type.get_type().pointer():
         raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
 
@@ -28,7 +28,7 @@ def rb_first(root):
 
 def rb_last(root):
     if root.type == rb_root_type.get_type():
-        node = node.address.cast(rb_root_type.get_type().pointer())
+        node = root.address.cast(rb_root_type.get_type().pointer())
     elif root.type != rb_root_type.get_type().pointer():
         raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
 
index 3e8dea6e0a9572c21b719b8ac111ed8097bab77e..6dc3078649fa0c41c79a8d4d26db82b11b15d9df 100644 (file)
@@ -34,7 +34,7 @@ struct sym_entry {
        unsigned int len;
        unsigned int start_pos;
        unsigned int percpu_absolute;
-       unsigned char sym[0];
+       unsigned char sym[];
 };
 
 struct addr_range {
index f2d73f04e71d6a7e823904eb1265b3f94f227035..f746ca8fa403c43fc63cfbbe6d637bd06d61ff08 100755 (executable)
@@ -853,7 +853,7 @@ sub output_function_rst(%) {
 
        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
            # pointer-to-function
-           print $1 . $parameter . ") (" . $2;
+           print $1 . $parameter . ") (" . $2 . ")";
        } else {
            print $type . " " . $parameter;
        }
index 415f3f1c2da042f794608522aeddd772fc706011..d0cde6685627f2ab6d3cc0d6919b7e8a50c10dd0 100644 (file)
@@ -139,6 +139,8 @@ static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos)
        n = key_serial_next(p, v);
        if (n)
                *_pos = key_node_serial(n);
+       else
+               (*_pos)++;
        return n;
 }
 
index 0b4e32161b7775df189e59624dd43923d8df1019..4c037c2545c1613b2b517d583f8d696ae00452bf 100644 (file)
@@ -5842,40 +5842,60 @@ static unsigned int selinux_ipv6_postroute(void *priv,
 
 static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
 {
-       int err = 0;
-       u32 perm;
+       int rc = 0;
+       unsigned int msg_len;
+       unsigned int data_len = skb->len;
+       unsigned char *data = skb->data;
        struct nlmsghdr *nlh;
        struct sk_security_struct *sksec = sk->sk_security;
+       u16 sclass = sksec->sclass;
+       u32 perm;
 
-       if (skb->len < NLMSG_HDRLEN) {
-               err = -EINVAL;
-               goto out;
-       }
-       nlh = nlmsg_hdr(skb);
+       while (data_len >= nlmsg_total_size(0)) {
+               nlh = (struct nlmsghdr *)data;
+
+               /* NOTE: the nlmsg_len field isn't reliably set by some netlink
+                *       users which means we can't reject skb's with bogus
+                *       length fields; our solution is to follow what
+                *       netlink_rcv_skb() does and simply skip processing at
+                *       messages with length fields that are clearly junk
+                */
+               if (nlh->nlmsg_len < NLMSG_HDRLEN || nlh->nlmsg_len > data_len)
+                       return 0;
 
-       err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
-       if (err) {
-               if (err == -EINVAL) {
+               rc = selinux_nlmsg_lookup(sclass, nlh->nlmsg_type, &perm);
+               if (rc == 0) {
+                       rc = sock_has_perm(sk, perm);
+                       if (rc)
+                               return rc;
+               } else if (rc == -EINVAL) {
+                       /* -EINVAL is a missing msg/perm mapping */
                        pr_warn_ratelimited("SELinux: unrecognized netlink"
-                              " message: protocol=%hu nlmsg_type=%hu sclass=%s"
-                              " pid=%d comm=%s\n",
-                              sk->sk_protocol, nlh->nlmsg_type,
-                              secclass_map[sksec->sclass - 1].name,
-                              task_pid_nr(current), current->comm);
-                       if (!enforcing_enabled(&selinux_state) ||
-                           security_get_allow_unknown(&selinux_state))
-                               err = 0;
+                               " message: protocol=%hu nlmsg_type=%hu sclass=%s"
+                               " pid=%d comm=%s\n",
+                               sk->sk_protocol, nlh->nlmsg_type,
+                               secclass_map[sclass - 1].name,
+                               task_pid_nr(current), current->comm);
+                       if (enforcing_enabled(&selinux_state) &&
+                           !security_get_allow_unknown(&selinux_state))
+                               return rc;
+                       rc = 0;
+               } else if (rc == -ENOENT) {
+                       /* -ENOENT is a missing socket/class mapping, ignore */
+                       rc = 0;
+               } else {
+                       return rc;
                }
 
-               /* Ignore */
-               if (err == -ENOENT)
-                       err = 0;
-               goto out;
+               /* move to the next message after applying netlink padding */
+               msg_len = NLMSG_ALIGN(nlh->nlmsg_len);
+               if (msg_len >= data_len)
+                       return 0;
+               data_len -= msg_len;
+               data += msg_len;
        }
 
-       err = sock_has_perm(sk, perm);
-out:
-       return err;
+       return rc;
 }
 
 static void ipc_init_security(struct ipc_security_struct *isec, u16 sclass)
index 939a74fd8fb470e68ef6fd9172a11fd2e42679d4..da94a1b4bfda07dccee4dfeaf04b86c3440f82ce 100644 (file)
@@ -429,7 +429,7 @@ int cond_read_list(struct policydb *p, void *fp)
 
        p->cond_list = kcalloc(len, sizeof(*p->cond_list), GFP_KERNEL);
        if (!p->cond_list)
-               return rc;
+               return -ENOMEM;
 
        rc = avtab_alloc(&(p->te_cond_avtab), p->te_avtab.nel);
        if (rc)
index 70ecdc78efbd9f148d5a6744f4981ded87e5aac3..c21b922e5ebec1c851c74c22d43e17c39ff0c4e8 100644 (file)
@@ -1035,14 +1035,14 @@ static int str_read(char **strp, gfp_t flags, void *fp, u32 len)
        if (!str)
                return -ENOMEM;
 
-       /* it's expected the caller should free the str */
-       *strp = str;
-
        rc = next_entry(str, fp, len);
-       if (rc)
+       if (rc) {
+               kfree(str);
                return rc;
+       }
 
        str[len] = '\0';
+       *strp = str;
        return 0;
 }
 
index 59d62f05658f9e2626c62885a32bacbb9b9a387d..1545f8fdb4db6c4c7420151b7014ad8830132622 100644 (file)
@@ -205,13 +205,14 @@ static snd_pcm_sframes_t calc_dst_frames(struct snd_pcm_substream *plug,
        plugin = snd_pcm_plug_first(plug);
        while (plugin && frames > 0) {
                plugin_next = plugin->next;
+               if (check_size && plugin->buf_frames &&
+                   frames > plugin->buf_frames)
+                       frames = plugin->buf_frames;
                if (plugin->dst_frames) {
                        frames = plugin->dst_frames(plugin, frames);
                        if (frames < 0)
                                return frames;
                }
-               if (check_size && frames > plugin->buf_frames)
-                       frames = plugin->buf_frames;
                plugin = plugin_next;
        }
        return frames;
@@ -225,14 +226,15 @@ static snd_pcm_sframes_t calc_src_frames(struct snd_pcm_substream *plug,
 
        plugin = snd_pcm_plug_last(plug);
        while (plugin && frames > 0) {
-               if (check_size && frames > plugin->buf_frames)
-                       frames = plugin->buf_frames;
                plugin_prev = plugin->prev;
                if (plugin->src_frames) {
                        frames = plugin->src_frames(plugin, frames);
                        if (frames < 0)
                                return frames;
                }
+               if (check_size && plugin->buf_frames &&
+                   frames > plugin->buf_frames)
+                       frames = plugin->buf_frames;
                plugin = plugin_prev;
        }
        return frames;
index 4ca6b09056f396e7d2cfd8e4ca7ba63a2584e167..3bc9224d5e4fee31b7d133bc84e2bfdb966beb50 100644 (file)
@@ -21,16 +21,17 @@ config SND_HDA_EXT_CORE
        select SND_HDA_CORE
 
 config SND_HDA_PREALLOC_SIZE
-       int "Pre-allocated buffer size for HD-audio driver" if !SND_DMA_SGBUF
+       int "Pre-allocated buffer size for HD-audio driver"
        range 0 32768
-       default 0 if SND_DMA_SGBUF
+       default 2048 if SND_DMA_SGBUF
        default 64 if !SND_DMA_SGBUF
        help
          Specifies the default pre-allocated buffer-size in kB for the
          HD-audio driver.  A larger buffer (e.g. 2048) is preferred
          for systems using PulseAudio.  The default 64 is chosen just
          for compatibility reasons.
-         On x86 systems, the default is zero as we need no preallocation.
+         On x86 systems, the default is 2048 as a reasonable value for
+         most of modern systems.
 
          Note that the pre-allocation size can be changed dynamically
          via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too.
index e764816a8f7a1f89f045cedaa149d8ee21180e9f..b039429e687171c5cf40fe942383f53acd3f82fa 100644 (file)
@@ -867,10 +867,13 @@ static void snd_miro_write(struct snd_miro *chip, unsigned char reg,
        spin_unlock_irqrestore(&chip->lock, flags);
 }
 
+static inline void snd_miro_write_mask(struct snd_miro *chip,
+               unsigned char reg, unsigned char value, unsigned char mask)
+{
+       unsigned char oldval = snd_miro_read(chip, reg);
 
-#define snd_miro_write_mask(chip, reg, value, mask)    \
-       snd_miro_write(chip, reg,                       \
-               (snd_miro_read(chip, reg) & ~(mask)) | ((value) & (mask)))
+       snd_miro_write(chip, reg, (oldval & ~mask) | (value & mask));
+}
 
 /*
  *  Proc Interface
index d06b29693c85f0e4f02e9b81c88d0b00897f83c2..0e6d20e4915854f99517c7cc47dbe5a5dafe0773 100644 (file)
@@ -317,10 +317,13 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
 }
 
 
-#define snd_opti9xx_write_mask(chip, reg, value, mask) \
-       snd_opti9xx_write(chip, reg,                    \
-               (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask)))
+static inline void snd_opti9xx_write_mask(struct snd_opti9xx *chip,
+               unsigned char reg, unsigned char value, unsigned char mask)
+{
+       unsigned char oldval = snd_opti9xx_read(chip, reg);
 
+       snd_opti9xx_write(chip, reg, (oldval & ~mask) | (value & mask));
+}
 
 static int snd_opti9xx_configure(struct snd_opti9xx *chip,
                                           long port,
index 6e3177bcc7097954ae2e26cec1e7620e394b7088..015c0d676897a48b8e02bc29e88557d8c9b1afb0 100644 (file)
@@ -168,7 +168,7 @@ static int src_get_rsc_ctrl_blk(void **rblk)
 
 static int src_put_rsc_ctrl_blk(void *blk)
 {
-       kfree((struct src_rsc_ctrl_blk *)blk);
+       kfree(blk);
 
        return 0;
 }
@@ -494,7 +494,7 @@ static int src_mgr_get_ctrl_blk(void **rblk)
 
 static int src_mgr_put_ctrl_blk(void *blk)
 {
-       kfree((struct src_mgr_ctrl_blk *)blk);
+       kfree(blk);
 
        return 0;
 }
@@ -515,7 +515,7 @@ static int srcimp_mgr_get_ctrl_blk(void **rblk)
 
 static int srcimp_mgr_put_ctrl_blk(void *blk)
 {
-       kfree((struct srcimp_mgr_ctrl_blk *)blk);
+       kfree(blk);
 
        return 0;
 }
@@ -702,7 +702,7 @@ static int amixer_rsc_get_ctrl_blk(void **rblk)
 
 static int amixer_rsc_put_ctrl_blk(void *blk)
 {
-       kfree((struct amixer_rsc_ctrl_blk *)blk);
+       kfree(blk);
 
        return 0;
 }
@@ -909,7 +909,7 @@ static int dai_get_ctrl_blk(void **rblk)
 
 static int dai_put_ctrl_blk(void *blk)
 {
-       kfree((struct dai_ctrl_blk *)blk);
+       kfree(blk);
 
        return 0;
 }
@@ -958,7 +958,7 @@ static int dao_get_ctrl_blk(void **rblk)
 
 static int dao_put_ctrl_blk(void *blk)
 {
-       kfree((struct dao_ctrl_blk *)blk);
+       kfree(blk);
 
        return 0;
 }
@@ -1156,7 +1156,7 @@ static int daio_mgr_get_ctrl_blk(struct hw *hw, void **rblk)
 
 static int daio_mgr_put_ctrl_blk(void *blk)
 {
-       kfree((struct daio_mgr_ctrl_blk *)blk);
+       kfree(blk);
 
        return 0;
 }
index a34a2c9f4bcf4c12e20d0097a924fe67bf327090..7e3ae4534df9164cb57d69a19f29f006ad3a218c 100644 (file)
@@ -641,8 +641,18 @@ static void hda_jackpoll_work(struct work_struct *work)
        struct hda_codec *codec =
                container_of(work, struct hda_codec, jackpoll_work.work);
 
-       snd_hda_jack_set_dirty_all(codec);
-       snd_hda_jack_poll_all(codec);
+       /* for non-polling trigger: we need nothing if already powered on */
+       if (!codec->jackpoll_interval && snd_hdac_is_power_on(&codec->core))
+               return;
+
+       /* the power-up/down sequence triggers the runtime resume */
+       snd_hda_power_up_pm(codec);
+       /* update jacks manually if polling is required, too */
+       if (codec->jackpoll_interval) {
+               snd_hda_jack_set_dirty_all(codec);
+               snd_hda_jack_poll_all(codec);
+       }
+       snd_hda_power_down_pm(codec);
 
        if (!codec->jackpoll_interval)
                return;
@@ -2951,18 +2961,14 @@ static int hda_codec_runtime_resume(struct device *dev)
 static int hda_codec_force_resume(struct device *dev)
 {
        struct hda_codec *codec = dev_to_hda_codec(dev);
-       bool forced_resume = !codec->relaxed_resume && codec->jacktbl.used;
        int ret;
 
-       /* The get/put pair below enforces the runtime resume even if the
-        * device hasn't been used at suspend time.  This trick is needed to
-        * update the jack state change during the sleep.
-        */
-       if (forced_resume)
-               pm_runtime_get_noresume(dev);
        ret = pm_runtime_force_resume(dev);
-       if (forced_resume)
-               pm_runtime_put(dev);
+       /* schedule jackpoll work for jack detection update */
+       if (codec->jackpoll_interval ||
+           (pm_runtime_suspended(dev) && hda_codec_need_resume(codec)))
+               schedule_delayed_work(&codec->jackpoll_work,
+                                     codec->jackpoll_interval);
        return ret;
 }
 
index bd093593f8fbdff5b1735e81c53a6d386f673906..0310193ea1bd4dd59beda03b250109aea56497dd 100644 (file)
@@ -1004,7 +1004,8 @@ static void __azx_runtime_resume(struct azx *chip, bool from_rt)
 
        if (status && from_rt) {
                list_for_each_codec(codec, &chip->bus)
-                       if (status & (1 << codec->addr))
+                       if (!codec->relaxed_resume &&
+                           (status & (1 << codec->addr)))
                                schedule_delayed_work(&codec->jackpoll_work,
                                                      codec->jackpoll_interval);
        }
@@ -1027,7 +1028,7 @@ static int azx_suspend(struct device *dev)
        chip = card->private_data;
        bus = azx_bus(chip);
        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-       __azx_runtime_suspend(chip);
+       pm_runtime_force_suspend(dev);
        if (bus->irq >= 0) {
                free_irq(bus->irq, chip);
                bus->irq = -1;
@@ -1055,7 +1056,8 @@ static int azx_resume(struct device *dev)
                        chip->msi = 0;
        if (azx_acquire_irq(chip, 1) < 0)
                return -EIO;
-       __azx_runtime_resume(chip, false);
+
+       pm_runtime_force_resume(dev);
        snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 
        trace_azx_resume(chip);
@@ -1071,6 +1073,8 @@ static int azx_freeze_noirq(struct device *dev)
        struct azx *chip = card->private_data;
        struct pci_dev *pci = to_pci_dev(dev);
 
+       if (!azx_is_pm_ready(card))
+               return 0;
        if (chip->driver_type == AZX_DRIVER_SKL)
                pci_set_power_state(pci, PCI_D3hot);
 
@@ -1083,6 +1087,8 @@ static int azx_thaw_noirq(struct device *dev)
        struct azx *chip = card->private_data;
        struct pci_dev *pci = to_pci_dev(dev);
 
+       if (!azx_is_pm_ready(card))
+               return 0;
        if (chip->driver_type == AZX_DRIVER_SKL)
                pci_set_power_state(pci, PCI_D0);
 
@@ -1098,12 +1104,12 @@ static int azx_runtime_suspend(struct device *dev)
        if (!azx_is_pm_ready(card))
                return 0;
        chip = card->private_data;
-       if (!azx_has_pm_runtime(chip))
-               return 0;
 
        /* enable controller wake up event */
-       azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) |
-                 STATESTS_INT_MASK);
+       if (snd_power_get_state(card) == SNDRV_CTL_POWER_D0) {
+               azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) |
+                          STATESTS_INT_MASK);
+       }
 
        __azx_runtime_suspend(chip);
        trace_azx_runtime_suspend(chip);
@@ -1114,17 +1120,18 @@ static int azx_runtime_resume(struct device *dev)
 {
        struct snd_card *card = dev_get_drvdata(dev);
        struct azx *chip;
+       bool from_rt = snd_power_get_state(card) == SNDRV_CTL_POWER_D0;
 
        if (!azx_is_pm_ready(card))
                return 0;
        chip = card->private_data;
-       if (!azx_has_pm_runtime(chip))
-               return 0;
-       __azx_runtime_resume(chip, true);
+       __azx_runtime_resume(chip, from_rt);
 
        /* disable controller Wake Up event*/
-       azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) &
-                       ~STATESTS_INT_MASK);
+       if (from_rt) {
+               azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) &
+                          ~STATESTS_INT_MASK);
+       }
 
        trace_azx_runtime_resume(chip);
        return 0;
@@ -1199,10 +1206,8 @@ static void azx_vs_set_state(struct pci_dev *pci,
                if (!disabled) {
                        dev_info(chip->card->dev,
                                 "Start delayed initialization\n");
-                       if (azx_probe_continue(chip) < 0) {
+                       if (azx_probe_continue(chip) < 0)
                                dev_err(chip->card->dev, "initialization error\n");
-                               hda->init_failed = true;
-                       }
                }
        } else {
                dev_info(chip->card->dev, "%s via vga_switcheroo\n",
@@ -1335,12 +1340,15 @@ static int register_vga_switcheroo(struct azx *chip)
 /*
  * destructor
  */
-static int azx_free(struct azx *chip)
+static void azx_free(struct azx *chip)
 {
        struct pci_dev *pci = chip->pci;
        struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
        struct hdac_bus *bus = azx_bus(chip);
 
+       if (hda->freed)
+               return;
+
        if (azx_has_pm_runtime(chip) && chip->running)
                pm_runtime_get_noresume(&pci->dev);
        chip->running = 0;
@@ -1384,9 +1392,8 @@ static int azx_free(struct azx *chip)
 
        if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT)
                snd_hdac_i915_exit(bus);
-       kfree(hda);
 
-       return 0;
+       hda->freed = 1;
 }
 
 static int azx_dev_disconnect(struct snd_device *device)
@@ -1402,7 +1409,8 @@ static int azx_dev_disconnect(struct snd_device *device)
 
 static int azx_dev_free(struct snd_device *device)
 {
-       return azx_free(device->device_data);
+       azx_free(device->device_data);
+       return 0;
 }
 
 #ifdef SUPPORT_VGA_SWITCHEROO
@@ -1769,7 +1777,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
        if (err < 0)
                return err;
 
-       hda = kzalloc(sizeof(*hda), GFP_KERNEL);
+       hda = devm_kzalloc(&pci->dev, sizeof(*hda), GFP_KERNEL);
        if (!hda) {
                pci_disable_device(pci);
                return -ENOMEM;
@@ -1810,7 +1818,6 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
 
        err = azx_bus_init(chip, model[dev]);
        if (err < 0) {
-               kfree(hda);
                pci_disable_device(pci);
                return err;
        }
@@ -2005,7 +2012,7 @@ static int azx_first_init(struct azx *chip)
        /* codec detection */
        if (!azx_bus(chip)->codec_mask) {
                dev_err(card->dev, "no codecs found!\n");
-               return -ENODEV;
+               /* keep running the rest for the runtime PM */
        }
 
        if (azx_acquire_irq(chip, 0) < 0)
@@ -2027,24 +2034,15 @@ static void azx_firmware_cb(const struct firmware *fw, void *context)
 {
        struct snd_card *card = context;
        struct azx *chip = card->private_data;
-       struct pci_dev *pci = chip->pci;
-
-       if (!fw) {
-               dev_err(card->dev, "Cannot load firmware, aborting\n");
-               goto error;
-       }
 
-       chip->fw = fw;
+       if (fw)
+               chip->fw = fw;
+       else
+               dev_err(card->dev, "Cannot load firmware, continue without patching\n");
        if (!chip->disabled) {
                /* continue probing */
-               if (azx_probe_continue(chip))
-                       goto error;
+               azx_probe_continue(chip);
        }
-       return; /* OK */
-
- error:
-       snd_card_free(card);
-       pci_set_drvdata(pci, NULL);
 }
 #endif
 
@@ -2080,10 +2078,10 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream,
  * some HD-audio PCI entries are exposed without any codecs, and such devices
  * should be ignored from the beginning.
  */
-static const struct snd_pci_quirk driver_blacklist[] = {
-       SND_PCI_QUIRK(0x1043, 0x874f, "ASUS ROG Zenith II / Strix", 0),
-       SND_PCI_QUIRK(0x1462, 0xcb59, "MSI TRX40 Creator", 0),
-       SND_PCI_QUIRK(0x1462, 0xcb60, "MSI TRX40", 0),
+static const struct pci_device_id driver_blacklist[] = {
+       { PCI_DEVICE_SUB(0x1022, 0x1487, 0x1043, 0x874f) }, /* ASUS ROG Zenith II / Strix */
+       { PCI_DEVICE_SUB(0x1022, 0x1487, 0x1462, 0xcb59) }, /* MSI TRX40 Creator */
+       { PCI_DEVICE_SUB(0x1022, 0x1487, 0x1462, 0xcb60) }, /* MSI TRX40 */
        {}
 };
 
@@ -2103,7 +2101,7 @@ static int azx_probe(struct pci_dev *pci,
        bool schedule_probe;
        int err;
 
-       if (snd_pci_quirk_lookup(pci, driver_blacklist)) {
+       if (pci_match_id(driver_blacklist, pci)) {
                dev_info(&pci->dev, "Skipping the blacklisted device\n");
                return -ENODEV;
        }
@@ -2308,9 +2306,11 @@ static int azx_probe_continue(struct azx *chip)
 #endif
 
        /* create codec instances */
-       err = azx_probe_codecs(chip, azx_max_codecs[chip->driver_type]);
-       if (err < 0)
-               goto out_free;
+       if (bus->codec_mask) {
+               err = azx_probe_codecs(chip, azx_max_codecs[chip->driver_type]);
+               if (err < 0)
+                       goto out_free;
+       }
 
 #ifdef CONFIG_SND_HDA_PATCH_LOADER
        if (chip->fw) {
@@ -2324,7 +2324,7 @@ static int azx_probe_continue(struct azx *chip)
 #endif
        }
 #endif
-       if ((probe_only[dev] & 1) == 0) {
+       if (bus->codec_mask && !(probe_only[dev] & 1)) {
                err = azx_codec_configure(chip);
                if (err < 0)
                        goto out_free;
@@ -2341,17 +2341,23 @@ static int azx_probe_continue(struct azx *chip)
 
        set_default_power_save(chip);
 
-       if (azx_has_pm_runtime(chip))
+       if (azx_has_pm_runtime(chip)) {
+               pm_runtime_use_autosuspend(&pci->dev);
+               pm_runtime_allow(&pci->dev);
                pm_runtime_put_autosuspend(&pci->dev);
+       }
 
 out_free:
-       if (err < 0 || !hda->need_i915_power)
+       if (err < 0) {
+               azx_free(chip);
+               return err;
+       }
+
+       if (!hda->need_i915_power)
                display_power(chip, false);
-       if (err < 0)
-               hda->init_failed = 1;
        complete_all(&hda->probe_wait);
        to_hda_bus(bus)->bus_probing = 0;
-       return err;
+       return 0;
 }
 
 static void azx_remove(struct pci_dev *pci)
index 2acfff3da1a04797c6bb4a7d2880ad58b58ec621..3fb119f090408865e2a380292807469b9bd8d369 100644 (file)
@@ -27,6 +27,7 @@ struct hda_intel {
        unsigned int use_vga_switcheroo:1;
        unsigned int vga_switcheroo_registered:1;
        unsigned int init_failed:1; /* delayed init failed */
+       unsigned int freed:1; /* resources already released */
 
        bool need_i915_power:1; /* the hda controller needs i915 power */
 };
index bb287a916dae0c8668ff09989e94ab2c4da1cef6..93760a3564cfa5261e2f00f10863d971730b4d05 100644 (file)
@@ -38,6 +38,10 @@ static bool static_hdmi_pcm;
 module_param(static_hdmi_pcm, bool, 0644);
 MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
 
+static bool enable_acomp = true;
+module_param(enable_acomp, bool, 0444);
+MODULE_PARM_DESC(enable_acomp, "Enable audio component binding (default=yes)");
+
 struct hdmi_spec_per_cvt {
        hda_nid_t cvt_nid;
        int assigned;
@@ -1844,8 +1848,10 @@ static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
        /* Add sanity check to pass klockwork check.
         * This should never happen.
         */
-       if (WARN_ON(spdif == NULL))
+       if (WARN_ON(spdif == NULL)) {
+               mutex_unlock(&codec->spdif_mutex);
                return true;
+       }
        non_pcm = !!(spdif->status & IEC958_AES0_NONAUDIO);
        mutex_unlock(&codec->spdif_mutex);
        return non_pcm;
@@ -2194,7 +2200,9 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
 
        for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
                struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
+               struct hdmi_eld *pin_eld = &per_pin->sink_eld;
 
+               pin_eld->eld_valid = false;
                hdmi_present_sense(per_pin, 0);
        }
 
@@ -2505,6 +2513,11 @@ static void generic_acomp_init(struct hda_codec *codec,
 {
        struct hdmi_spec *spec = codec->spec;
 
+       if (!enable_acomp) {
+               codec_info(codec, "audio component disabled by module option\n");
+               return;
+       }
+
        spec->port2pin = port2pin;
        setup_drm_audio_ops(codec, ops);
        if (!snd_hdac_acomp_init(&codec->bus->core, &spec->drm_audio_ops,
index de2826f90d343c06ad974ef79ca9cb3123c558d4..c16f63957c5af047b3f158f95d9a319b2afd4ab0 100644 (file)
@@ -377,6 +377,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
        case 0x10ec0233:
        case 0x10ec0235:
        case 0x10ec0236:
+       case 0x10ec0245:
        case 0x10ec0255:
        case 0x10ec0256:
        case 0x10ec0257:
@@ -797,9 +798,11 @@ static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
 {
        if (!alc_subsystem_id(codec, ports)) {
                struct alc_spec *spec = codec->spec;
-               codec_dbg(codec,
-                         "realtek: Enable default setup for auto mode as fallback\n");
-               spec->init_amp = ALC_INIT_DEFAULT;
+               if (spec->init_amp == ALC_INIT_UNDEFINED) {
+                       codec_dbg(codec,
+                                 "realtek: Enable default setup for auto mode as fallback\n");
+                       spec->init_amp = ALC_INIT_DEFAULT;
+               }
        }
 }
 
@@ -7378,6 +7381,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, 0x18f1, "Asus FX505DT", 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),
@@ -7416,6 +7420,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x8560, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1558, 0x8561, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS),
+       SND_PCI_QUIRK(0x17aa, 0x1048, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
@@ -8195,6 +8200,7 @@ static int patch_alc269(struct hda_codec *codec)
                spec->gen.mixer_nid = 0;
                break;
        case 0x10ec0215:
+       case 0x10ec0245:
        case 0x10ec0285:
        case 0x10ec0289:
                spec->codec_variant = ALC269_TYPE_ALC215;
@@ -9456,6 +9462,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
        HDA_CODEC_ENTRY(0x10ec0234, "ALC234", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0235, "ALC233", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0236, "ALC236", patch_alc269),
+       HDA_CODEC_ENTRY(0x10ec0245, "ALC245", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0255, "ALC255", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0256, "ALC256", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0257, "ALC257", patch_alc269),
index 024a7ee54cd5a6a36adae4a1326cee69330e49ca..e499c00e0c66a036acea52018756a11d1aaa6bee 100644 (file)
@@ -89,9 +89,9 @@ static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd)
        }
 
        snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
-       snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
-       snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
-       snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
+       snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+       snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+       snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
 
        ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
        if (ret) {
index e6a0c5d05fa5e458340b4f04c425c868babdbfe2..e60e0b6a689cdb2ca44e021f0478e308c7e75f08 100644 (file)
@@ -1525,6 +1525,7 @@ config SND_SOC_WM8804_SPI
 
 config SND_SOC_WM8900
        tristate
+       depends on SND_SOC_I2C_AND_SPI
 
 config SND_SOC_WM8903
        tristate "Wolfson Microelectronics WM8903 CODEC"
@@ -1576,6 +1577,7 @@ config SND_SOC_WM8985
 
 config SND_SOC_WM8988
        tristate
+       depends on SND_SOC_I2C_AND_SPI
 
 config SND_SOC_WM8990
        tristate
@@ -1594,6 +1596,7 @@ config SND_SOC_WM8994
 
 config SND_SOC_WM8995
        tristate
+       depends on SND_SOC_I2C_AND_SPI
 
 config SND_SOC_WM8996
        tristate
index fba9b749839ded0a2684075d4ccdeda6c521584e..f26b77faed5993730b0890a2f5b7069fabb65649 100644 (file)
@@ -142,14 +142,14 @@ static struct hdac_hdmi_pcm *
 hdac_hdmi_get_pcm_from_cvt(struct hdac_hdmi_priv *hdmi,
                           struct hdac_hdmi_cvt *cvt)
 {
-       struct hdac_hdmi_pcm *pcm = NULL;
+       struct hdac_hdmi_pcm *pcm;
 
        list_for_each_entry(pcm, &hdmi->pcm_list, head) {
                if (pcm->cvt == cvt)
-                       break;
+                       return pcm;
        }
 
-       return pcm;
+       return NULL;
 }
 
 static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm,
index 40de9d7811d1fe29c45616b1fe24d05be16af4c8..a448d2a2918a95a3cca9e24576817033e05fe908 100644 (file)
@@ -1903,7 +1903,6 @@ const struct soc_enum madera_isrc_fsh[] = {
                              MADERA_ISRC4_FSH_SHIFT, 0xf,
                              MADERA_RATE_ENUM_SIZE,
                              madera_rate_text, madera_rate_val),
-
 };
 EXPORT_SYMBOL_GPL(madera_isrc_fsh);
 
@@ -1924,7 +1923,6 @@ const struct soc_enum madera_isrc_fsl[] = {
                              MADERA_ISRC4_FSL_SHIFT, 0xf,
                              MADERA_RATE_ENUM_SIZE,
                              madera_rate_text, madera_rate_val),
-
 };
 EXPORT_SYMBOL_GPL(madera_isrc_fsl);
 
@@ -1938,7 +1936,6 @@ const struct soc_enum madera_asrc1_rate[] = {
                              MADERA_ASYNC_RATE_ENUM_SIZE,
                              madera_rate_text + MADERA_SYNC_RATE_ENUM_SIZE,
                              madera_rate_val + MADERA_SYNC_RATE_ENUM_SIZE),
-
 };
 EXPORT_SYMBOL_GPL(madera_asrc1_rate);
 
@@ -1964,7 +1961,6 @@ const struct soc_enum madera_asrc2_rate[] = {
                              MADERA_ASYNC_RATE_ENUM_SIZE,
                              madera_rate_text + MADERA_SYNC_RATE_ENUM_SIZE,
                              madera_rate_val + MADERA_SYNC_RATE_ENUM_SIZE),
-
 };
 EXPORT_SYMBOL_GPL(madera_asrc2_rate);
 
index d5130193b4a2f9ba37b5502bac75b3e5a5c2f4bc..e8a8bf7b4ffed041e6e1b48430fb0702a9a74fa8 100644 (file)
@@ -1653,6 +1653,40 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
                dev_err(&client->dev,
                        "Error %d initializing CHIP_CLK_CTRL\n", ret);
 
+       /* Mute everything to avoid pop from the following power-up */
+       ret = regmap_write(sgtl5000->regmap, SGTL5000_CHIP_ANA_CTRL,
+                          SGTL5000_CHIP_ANA_CTRL_DEFAULT);
+       if (ret) {
+               dev_err(&client->dev,
+                       "Error %d muting outputs via CHIP_ANA_CTRL\n", ret);
+               goto disable_clk;
+       }
+
+       /*
+        * If VAG is powered-on (e.g. from previous boot), it would be disabled
+        * by the write to ANA_POWER in later steps of the probe code. This
+        * may create a loud pop even with all outputs muted. The proper way
+        * to circumvent this is disabling the bit first and waiting the proper
+        * cool-down time.
+        */
+       ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ANA_POWER, &value);
+       if (ret) {
+               dev_err(&client->dev, "Failed to read ANA_POWER: %d\n", ret);
+               goto disable_clk;
+       }
+       if (value & SGTL5000_VAG_POWERUP) {
+               ret = regmap_update_bits(sgtl5000->regmap,
+                                        SGTL5000_CHIP_ANA_POWER,
+                                        SGTL5000_VAG_POWERUP,
+                                        0);
+               if (ret) {
+                       dev_err(&client->dev, "Error %d disabling VAG\n", ret);
+                       goto disable_clk;
+               }
+
+               msleep(SGTL5000_VAG_POWERDOWN_DELAY);
+       }
+
        /* Follow section 2.2.1.1 of AN3663 */
        ana_pwr = SGTL5000_ANA_POWER_DEFAULT;
        if (sgtl5000->num_supplies <= VDDD) {
index a4bf4bca95bf7681bfb9f8b38dada3aa368d3c4e..56ec5863f25071ef2f78fd5c018f5b05f27c1e3b 100644 (file)
 /*
  * SGTL5000_CHIP_ANA_CTRL
  */
+#define SGTL5000_CHIP_ANA_CTRL_DEFAULT         0x0133
 #define SGTL5000_LINE_OUT_MUTE                 0x0100
 #define SGTL5000_HP_SEL_MASK                   0x0040
 #define SGTL5000_HP_SEL_SHIFT                  6
index 1554631cb397b1bf75f50cb520141636e1db6461..5b7f9fcf6cbf3b2781f0f38df83f37cfb7efb110 100644 (file)
@@ -820,8 +820,10 @@ static int tas571x_i2c_probe(struct i2c_client *client,
 
        priv->regmap = devm_regmap_init(dev, NULL, client,
                                        priv->chip->regmap_config);
-       if (IS_ERR(priv->regmap))
-               return PTR_ERR(priv->regmap);
+       if (IS_ERR(priv->regmap)) {
+               ret = PTR_ERR(priv->regmap);
+               goto disable_regs;
+       }
 
        priv->pdn_gpio = devm_gpiod_get_optional(dev, "pdn", GPIOD_OUT_LOW);
        if (IS_ERR(priv->pdn_gpio)) {
@@ -845,7 +847,7 @@ static int tas571x_i2c_probe(struct i2c_client *client,
 
        ret = regmap_write(priv->regmap, TAS571X_OSC_TRIM_REG, 0);
        if (ret)
-               return ret;
+               goto disable_regs;
 
        usleep_range(50000, 60000);
 
@@ -861,12 +863,20 @@ static int tas571x_i2c_probe(struct i2c_client *client,
                 */
                ret = regmap_update_bits(priv->regmap, TAS571X_MVOL_REG, 1, 0);
                if (ret)
-                       return ret;
+                       goto disable_regs;
        }
 
-       return devm_snd_soc_register_component(&client->dev,
+       ret = devm_snd_soc_register_component(&client->dev,
                                      &priv->component_driver,
                                      &tas571x_dai, 1);
+       if (ret)
+               goto disable_regs;
+
+       return ret;
+
+disable_regs:
+       regulator_bulk_disable(priv->chip->num_supply_names, priv->supplies);
+       return ret;
 }
 
 static int tas571x_i2c_remove(struct i2c_client *client)
index 55112c1bba5e74458d4a922d519a8e7162b38f72..6cf0f6612bdaf44685a20f7b99847e4f45675b44 100644 (file)
@@ -860,8 +860,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
 
        wm8960->is_stream_in_use[tx] = true;
 
-       if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_ON &&
-           !wm8960->is_stream_in_use[!tx])
+       if (!wm8960->is_stream_in_use[!tx])
                return wm8960_configure_clocking(component);
 
        return 0;
index f2d6f2f81f14e15535189755e4c82b4553772230..d39d479e23786eb814d9adaedaeeb8cd37f20d39 100644 (file)
@@ -394,6 +394,7 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = {
                .min_ch = 1,
                .max_ch = 1,
                .simple_ch_prep_sm = true,
+               .read_only_wordlength = true,
        }, {
                /* COMP */
                .num = 2,
@@ -401,6 +402,7 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = {
                .min_ch = 1,
                .max_ch = 1,
                .simple_ch_prep_sm = true,
+               .read_only_wordlength = true,
        }, {
                /* BOOST */
                .num = 3,
@@ -408,6 +410,7 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = {
                .min_ch = 1,
                .max_ch = 1,
                .simple_ch_prep_sm = true,
+               .read_only_wordlength = true,
        }, {
                /* VISENSE */
                .num = 4,
@@ -415,6 +418,7 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = {
                .min_ch = 1,
                .max_ch = 1,
                .simple_ch_prep_sm = true,
+               .read_only_wordlength = true,
        }
 };
 
index bcedec6c6117cbae801548bf87607e6b0b26e8a1..7d85bd5aff9f0cb2f8d307940317f8dfbef72150 100644 (file)
@@ -113,14 +113,6 @@ static const struct snd_soc_acpi_adr_device rt1308_1_adr[] = {
        }
 };
 
-static const struct snd_soc_acpi_adr_device rt1308_2_adr[] = {
-       {
-               .adr = 0x000210025D130800,
-               .num_endpoints = 1,
-               .endpoints = &single_endpoint,
-       }
-};
-
 static const struct snd_soc_acpi_adr_device rt1308_1_group1_adr[] = {
        {
                .adr = 0x000110025D130800,
index ef8500349f2f2f335787cb9f63b20fc9848cda83..16ec9f382b0ffd9e45cadb32e47888e81f13cd7e 100644 (file)
@@ -87,14 +87,6 @@ static const struct snd_soc_acpi_adr_device rt1308_1_adr[] = {
        }
 };
 
-static const struct snd_soc_acpi_adr_device rt1308_2_adr[] = {
-       {
-               .adr = 0x000210025D130800,
-               .num_endpoints = 1,
-               .endpoints = &single_endpoint,
-       }
-};
-
 static const struct snd_soc_acpi_adr_device rt1308_1_group1_adr[] = {
        {
                .adr = 0x000110025D130800,
index af46845f4ef2ba184f1d85318cf1a3b17015dce1..89f7f64747cd0a562e3915fbf3918947b37d671e 100644 (file)
@@ -338,8 +338,10 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np,
 
        if (axg_card_cpu_is_tdm_iface(dai_link->cpus->of_node))
                ret = axg_card_parse_tdm(card, np, index);
-       else if (axg_card_cpu_is_codec(dai_link->cpus->of_node))
+       else if (axg_card_cpu_is_codec(dai_link->cpus->of_node)) {
                dai_link->params = &codec_params;
+               dai_link->no_pcm = 0; /* link is not a DPCM BE */
+       }
 
        return ret;
 }
index 7b01dcb73e5e1c00b1082347cb12e9f4da275b44..4abf7efb7eacc54442ad7c3a662050d427086bbc 100644 (file)
@@ -108,8 +108,10 @@ static int gx_card_add_link(struct snd_soc_card *card, struct device_node *np,
                ret = gx_card_parse_i2s(card, np, index);
 
        /* Or apply codec to codec params if necessary */
-       else if (gx_card_cpu_identify(dai_link->cpus, "CODEC CTRL"))
+       else if (gx_card_cpu_identify(dai_link->cpus, "CODEC CTRL")) {
                dai_link->params = &codec_params;
+               dai_link->no_pcm = 0; /* link is not a DPCM BE */
+       }
 
        return ret;
 }
index d55e3ad96716081d679e21d100a881fc5eb8fc83..287ad2aa27f373154733b7de83a2a69af7050068 100644 (file)
@@ -116,10 +116,8 @@ static int apq8096_platform_probe(struct platform_device *pdev)
        card->dev = dev;
        dev_set_drvdata(dev, card);
        ret = qcom_snd_parse_of(card);
-       if (ret) {
-               dev_err(dev, "Error parsing OF data\n");
+       if (ret)
                goto err;
-       }
 
        apq8096_add_be_ops(card);
        ret = snd_soc_register_card(card);
index c1a7624eaf175f7856401e40b89b7a73d50b6255..2a5302f1db98aa9b5ad1a8604c723a2f9c36c682 100644 (file)
@@ -902,6 +902,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE |
                                   SNDRV_PCM_FMTBIT_S24_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
@@ -917,6 +919,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE |
                                   SNDRV_PCM_FMTBIT_S24_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
@@ -931,6 +935,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                        .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
@@ -946,6 +952,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE |
                                   SNDRV_PCM_FMTBIT_S24_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
@@ -960,6 +968,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                        .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
@@ -975,6 +985,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE |
                                   SNDRV_PCM_FMTBIT_S24_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
@@ -989,6 +1001,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                        .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
@@ -1004,6 +1018,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE |
                                   SNDRV_PCM_FMTBIT_S24_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
index b2de65c7f95cb73248ed2436442472956abfe862..68e9388ff46f1b8b9b7d7995b0e6bcdb880fb2d2 100644 (file)
@@ -559,10 +559,8 @@ static int sdm845_snd_platform_probe(struct platform_device *pdev)
        card->dev = dev;
        dev_set_drvdata(dev, card);
        ret = qcom_snd_parse_of(card);
-       if (ret) {
-               dev_err(dev, "Error parsing OF data\n");
+       if (ret)
                goto parse_dt_fail;
-       }
 
        data->card = card;
        snd_soc_card_set_drvdata(card, data);
index 35888784829388bac9417c1e541911b2a92f7dfc..5e95c30fb2bacc936c9e3c25ac9588f5e8ac2f81 100644 (file)
@@ -656,60 +656,6 @@ void s3c_i2sv2_cleanup(struct snd_soc_dai *dai,
 }
 EXPORT_SYMBOL_GPL(s3c_i2sv2_cleanup);
 
-#ifdef CONFIG_PM
-static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
-{
-       struct s3c_i2sv2_info *i2s = to_info(dai);
-       u32 iismod;
-
-       if (dai->active) {
-               i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD);
-               i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON);
-               i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR);
-
-               /* some basic suspend checks */
-
-               iismod = readl(i2s->regs + S3C2412_IISMOD);
-
-               if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
-                       pr_warn("%s: RXDMA active?\n", __func__);
-
-               if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
-                       pr_warn("%s: TXDMA active?\n", __func__);
-
-               if (iismod & S3C2412_IISCON_IIS_ACTIVE)
-                       pr_warn("%s: IIS active\n", __func__);
-       }
-
-       return 0;
-}
-
-static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
-{
-       struct s3c_i2sv2_info *i2s = to_info(dai);
-
-       pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
-               dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
-
-       if (dai->active) {
-               writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
-               writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD);
-               writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR);
-
-               writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
-                      i2s->regs + S3C2412_IISFIC);
-
-               ndelay(250);
-               writel(0x0, i2s->regs + S3C2412_IISFIC);
-       }
-
-       return 0;
-}
-#else
-#define s3c2412_i2s_suspend NULL
-#define s3c2412_i2s_resume  NULL
-#endif
-
 int s3c_i2sv2_register_component(struct device *dev, int id,
                           const struct snd_soc_component_driver *cmp_drv,
                           struct snd_soc_dai_driver *dai_drv)
@@ -727,9 +673,6 @@ int s3c_i2sv2_register_component(struct device *dev, int id,
        if (!ops->delay)
                ops->delay = s3c2412_i2s_delay;
 
-       dai_drv->suspend = s3c2412_i2s_suspend;
-       dai_drv->resume = s3c2412_i2s_resume;
-
        return devm_snd_soc_register_component(dev, cmp_drv, dai_drv, 1);
 }
 EXPORT_SYMBOL_GPL(s3c_i2sv2_register_component);
index 787a3f6e9f242235f581aec16c32e28b862d9903..b35d828c1cfe9b8ed6f46367ed2fbe485e5b7794 100644 (file)
@@ -117,6 +117,60 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int s3c2412_i2s_suspend(struct snd_soc_component *component)
+{
+       struct s3c_i2sv2_info *i2s = snd_soc_component_get_drvdata(component);
+       u32 iismod;
+
+       if (component->active) {
+               i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD);
+               i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON);
+               i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR);
+
+               /* some basic suspend checks */
+
+               iismod = readl(i2s->regs + S3C2412_IISMOD);
+
+               if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
+                       pr_warn("%s: RXDMA active?\n", __func__);
+
+               if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
+                       pr_warn("%s: TXDMA active?\n", __func__);
+
+               if (iismod & S3C2412_IISCON_IIS_ACTIVE)
+                       pr_warn("%s: IIS active\n", __func__);
+       }
+
+       return 0;
+}
+
+static int s3c2412_i2s_resume(struct snd_soc_component *component)
+{
+       struct s3c_i2sv2_info *i2s = snd_soc_component_get_drvdata(component);
+
+       pr_info("component_active %d, IISMOD %08x, IISCON %08x\n",
+               component->active, i2s->suspend_iismod, i2s->suspend_iiscon);
+
+       if (component->active) {
+               writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
+               writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD);
+               writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR);
+
+               writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
+                      i2s->regs + S3C2412_IISFIC);
+
+               ndelay(250);
+               writel(0x0, i2s->regs + S3C2412_IISFIC);
+       }
+
+       return 0;
+}
+#else
+#define s3c2412_i2s_suspend NULL
+#define s3c2412_i2s_resume  NULL
+#endif
+
 #define S3C2412_I2S_RATES \
        (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
        SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
@@ -146,6 +200,8 @@ static struct snd_soc_dai_driver s3c2412_i2s_dai = {
 
 static const struct snd_soc_component_driver s3c2412_i2s_component = {
        .name           = "s3c2412-i2s",
+       .suspend        = s3c2412_i2s_suspend,
+       .resume         = s3c2412_i2s_resume,
 };
 
 static int s3c2412_iis_dev_probe(struct platform_device *pdev)
index fc5d089868dfc084cfa4e3234259a57402cd8d5e..4a7d3413917fc253e873e9f8f46bba6fa4ba63cf 100644 (file)
@@ -594,10 +594,16 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod,
         * Capture:  It might not receave data. Do nothing
         */
        if (rsnd_io_is_play(io)) {
-               rsnd_mod_write(mod, SSICR, cr | EN);
+               rsnd_mod_write(mod, SSICR, cr | ssi->cr_en);
                rsnd_ssi_status_check(mod, DIRQ);
        }
 
+       /* In multi-SSI mode, stop is performed by setting ssi0129 in
+        * SSI_CONTROL to 0 (in rsnd_ssio_stop_gen2). Do nothing here.
+        */
+       if (rsnd_ssi_multi_slaves_runtime(io))
+               return 0;
+
        /*
         * disable SSI,
         * and, wait idle state
@@ -737,6 +743,9 @@ static void rsnd_ssi_parent_attach(struct rsnd_mod *mod,
        if (!rsnd_rdai_is_clk_master(rdai))
                return;
 
+       if (rsnd_ssi_is_multi_slave(mod, io))
+               return;
+
        switch (rsnd_mod_id(mod)) {
        case 1:
        case 2:
index f35d882118874c6868e14fe5a849dc15c7f3eb2f..9c7c3e7539c9347e2a045cad6ca167003524449e 100644 (file)
@@ -221,7 +221,7 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
                        i;
 
                for_each_rsnd_mod_array(i, pos, io, rsnd_ssi_array) {
-                       shift   = (i * 4) + 16;
+                       shift   = (i * 4) + 20;
                        val     = (val & ~(0xF << shift)) |
                                rsnd_mod_id(pos) << shift;
                }
index 8f3cad8db89a4979a6ecefedb4e0972b73bc91af..31c41559034b9b29d8daeef299b470aaac1e3cff 100644 (file)
@@ -295,24 +295,17 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai,
 {
        int ret = 0;
 
-       if (!dai->started[substream->stream] &&
-           dai->driver->ops->startup)
+       if (dai->driver->ops->startup)
                ret = dai->driver->ops->startup(substream, dai);
 
-       if (ret == 0)
-               dai->started[substream->stream] = 1;
-
        return ret;
 }
 
 void snd_soc_dai_shutdown(struct snd_soc_dai *dai,
                         struct snd_pcm_substream *substream)
 {
-       if (dai->started[substream->stream] &&
-           dai->driver->ops->shutdown)
+       if (dai->driver->ops->shutdown)
                dai->driver->ops->shutdown(substream, dai);
-
-       dai->started[substream->stream] = 0;
 }
 
 int snd_soc_dai_prepare(struct snd_soc_dai *dai,
index 679ed60d850ec6e00946c54ecc4c9aece98b1614..e2632841b321a2bdb47aff11fbe2f2493d808658 100644 (file)
@@ -423,7 +423,7 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
 
                        memset(&template, 0, sizeof(template));
                        template.reg = e->reg;
-                       template.mask = e->mask << e->shift_l;
+                       template.mask = e->mask;
                        template.shift = e->shift_l;
                        template.off_val = snd_soc_enum_item_to_val(e, 0);
                        template.on_val = template.off_val;
@@ -546,8 +546,22 @@ static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol,
        if (data->value == value)
                return false;
 
-       if (data->widget)
-               data->widget->on_val = value;
+       if (data->widget) {
+               switch (dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->id) {
+               case snd_soc_dapm_switch:
+               case snd_soc_dapm_mixer:
+               case snd_soc_dapm_mixer_named_ctl:
+                       data->widget->on_val = value & data->widget->mask;
+                       break;
+               case snd_soc_dapm_demux:
+               case snd_soc_dapm_mux:
+                       data->widget->on_val = value >> data->widget->shift;
+                       break;
+               default:
+                       data->widget->on_val = value;
+                       break;
+               }
+       }
 
        data->value = value;
 
@@ -4165,6 +4179,8 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card,
        w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template);
        if (IS_ERR(w)) {
                ret = PTR_ERR(w);
+               dev_err(rtd->dev, "ASoC: Failed to create %s widget: %d\n",
+                       link_name, ret);
                goto outfree_kcontrol_news;
        }
 
@@ -4283,52 +4299,58 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
        return 0;
 }
 
-static void dapm_add_valid_dai_widget(struct snd_soc_card *card,
-                                     struct snd_soc_pcm_runtime *rtd,
-                                     struct snd_soc_dai *codec_dai,
-                                     struct snd_soc_dai *cpu_dai)
+static void dapm_connect_dai_routes(struct snd_soc_dapm_context *dapm,
+                                   struct snd_soc_dai *src_dai,
+                                   struct snd_soc_dapm_widget *src,
+                                   struct snd_soc_dapm_widget *dai,
+                                   struct snd_soc_dai *sink_dai,
+                                   struct snd_soc_dapm_widget *sink)
 {
-       struct snd_soc_dapm_widget *playback = NULL, *capture = NULL;
-       struct snd_soc_dapm_widget *codec, *playback_cpu, *capture_cpu;
+       dev_dbg(dapm->dev, "connected DAI link %s:%s -> %s:%s\n",
+               src_dai->component->name, src->name,
+               sink_dai->component->name, sink->name);
+
+       if (dai) {
+               snd_soc_dapm_add_path(dapm, src, dai, NULL, NULL);
+               src = dai;
+       }
+
+       snd_soc_dapm_add_path(dapm, src, sink, NULL, NULL);
+}
+
+static void dapm_connect_dai_pair(struct snd_soc_card *card,
+                                 struct snd_soc_pcm_runtime *rtd,
+                                 struct snd_soc_dai *codec_dai,
+                                 struct snd_soc_dai *cpu_dai)
+{
+       struct snd_soc_dai_link *dai_link = rtd->dai_link;
+       struct snd_soc_dapm_widget *dai, *codec, *playback_cpu, *capture_cpu;
        struct snd_pcm_substream *substream;
        struct snd_pcm_str *streams = rtd->pcm->streams;
 
-       if (rtd->dai_link->params) {
+       if (dai_link->params) {
                playback_cpu = cpu_dai->capture_widget;
                capture_cpu = cpu_dai->playback_widget;
        } else {
-               playback = cpu_dai->playback_widget;
-               capture = cpu_dai->capture_widget;
-               playback_cpu = playback;
-               capture_cpu = capture;
+               playback_cpu = cpu_dai->playback_widget;
+               capture_cpu = cpu_dai->capture_widget;
        }
 
        /* connect BE DAI playback if widgets are valid */
        codec = codec_dai->playback_widget;
 
        if (playback_cpu && codec) {
-               if (!playback) {
+               if (dai_link->params && !dai_link->playback_widget) {
                        substream = streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
-                       playback = snd_soc_dapm_new_dai(card, substream,
-                                                       "playback");
-                       if (IS_ERR(playback)) {
-                               dev_err(rtd->dev,
-                                       "ASoC: Failed to create DAI %s: %ld\n",
-                                       codec_dai->name,
-                                       PTR_ERR(playback));
+                       dai = snd_soc_dapm_new_dai(card, substream, "playback");
+                       if (IS_ERR(dai))
                                goto capture;
-                       }
-
-                       snd_soc_dapm_add_path(&card->dapm, playback_cpu,
-                                             playback, NULL, NULL);
+                       dai_link->playback_widget = dai;
                }
 
-               dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
-                       cpu_dai->component->name, playback_cpu->name,
-                       codec_dai->component->name, codec->name);
-
-               snd_soc_dapm_add_path(&card->dapm, playback, codec,
-                                     NULL, NULL);
+               dapm_connect_dai_routes(&card->dapm, cpu_dai, playback_cpu,
+                                       dai_link->playback_widget,
+                                       codec_dai, codec);
        }
 
 capture:
@@ -4336,50 +4358,18 @@ capture:
        codec = codec_dai->capture_widget;
 
        if (codec && capture_cpu) {
-               if (!capture) {
+               if (dai_link->params && !dai_link->capture_widget) {
                        substream = streams[SNDRV_PCM_STREAM_CAPTURE].substream;
-                       capture = snd_soc_dapm_new_dai(card, substream,
-                                                      "capture");
-                       if (IS_ERR(capture)) {
-                               dev_err(rtd->dev,
-                                       "ASoC: Failed to create DAI %s: %ld\n",
-                                       codec_dai->name,
-                                       PTR_ERR(capture));
+                       dai = snd_soc_dapm_new_dai(card, substream, "capture");
+                       if (IS_ERR(dai))
                                return;
-                       }
-
-                       snd_soc_dapm_add_path(&card->dapm, capture,
-                                             capture_cpu, NULL, NULL);
+                       dai_link->capture_widget = dai;
                }
 
-               dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
-                       codec_dai->component->name, codec->name,
-                       cpu_dai->component->name, capture_cpu->name);
-
-               snd_soc_dapm_add_path(&card->dapm, codec, capture,
-                                     NULL, NULL);
-       }
-}
-
-static void dapm_connect_dai_link_widgets(struct snd_soc_card *card,
-                                         struct snd_soc_pcm_runtime *rtd)
-{
-       struct snd_soc_dai *codec_dai;
-       int i;
-
-       if (rtd->num_cpus == 1) {
-               for_each_rtd_codec_dais(rtd, i, codec_dai)
-                       dapm_add_valid_dai_widget(card, rtd, codec_dai,
-                                                 rtd->cpu_dais[0]);
-       } else if (rtd->num_codecs == rtd->num_cpus) {
-               for_each_rtd_codec_dais(rtd, i, codec_dai)
-                       dapm_add_valid_dai_widget(card, rtd, codec_dai,
-                                                 rtd->cpu_dais[i]);
-       } else {
-               dev_err(card->dev,
-                       "N cpus to M codecs link is not supported yet\n");
+               dapm_connect_dai_routes(&card->dapm, codec_dai, codec,
+                                       dai_link->capture_widget,
+                                       cpu_dai, capture_cpu);
        }
-
 }
 
 static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
@@ -4422,6 +4412,8 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
 void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
 {
        struct snd_soc_pcm_runtime *rtd;
+       struct snd_soc_dai *codec_dai;
+       int i;
 
        /* for each BE DAI link... */
        for_each_card_rtds(card, rtd)  {
@@ -4432,7 +4424,18 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
                if (rtd->dai_link->dynamic)
                        continue;
 
-               dapm_connect_dai_link_widgets(card, rtd);
+               if (rtd->num_cpus == 1) {
+                       for_each_rtd_codec_dais(rtd, i, codec_dai)
+                               dapm_connect_dai_pair(card, rtd, codec_dai,
+                                                     rtd->cpu_dais[0]);
+               } else if (rtd->num_codecs == rtd->num_cpus) {
+                       for_each_rtd_codec_dais(rtd, i, codec_dai)
+                               dapm_connect_dai_pair(card, rtd, codec_dai,
+                                                     rtd->cpu_dais[i]);
+               } else {
+                       dev_err(card->dev,
+                               "N cpus to M codecs link is not supported yet\n");
+               }
        }
 }
 
index 289aebc1552935b273463f579f3d4a865a4f409f..1f302de4405259afc43ef17d244975de4addd229 100644 (file)
@@ -2911,8 +2911,17 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
        int i;
 
        if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
-               playback = rtd->dai_link->dpcm_playback;
-               capture = rtd->dai_link->dpcm_capture;
+               cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+               if (rtd->num_cpus > 1) {
+                       dev_err(rtd->dev,
+                               "DPCM doesn't support Multi CPU yet\n");
+                       return -EINVAL;
+               }
+
+               playback = rtd->dai_link->dpcm_playback &&
+                          snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK);
+               capture = rtd->dai_link->dpcm_capture &&
+                         snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE);
        } else {
                /* Adapt stream for codec2codec links */
                int cpu_capture = rtd->dai_link->params ?
index 87f75edba3dc8454a80b7f6ece5253156e0d03d9..6df3b0d12d87d5355fe130497ab0e96fc082f75c 100644 (file)
@@ -894,7 +894,13 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count,
                }
 
                /* create any TLV data */
-               soc_tplg_create_tlv(tplg, &kc, &mc->hdr);
+               err = soc_tplg_create_tlv(tplg, &kc, &mc->hdr);
+               if (err < 0) {
+                       dev_err(tplg->dev, "ASoC: failed to create TLV %s\n",
+                               mc->hdr.name);
+                       kfree(sm);
+                       continue;
+               }
 
                /* pass control to driver for optional further init */
                err = soc_tplg_init_kcontrol(tplg, &kc,
@@ -1118,6 +1124,7 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
        struct snd_soc_tplg_hdr *hdr)
 {
        struct snd_soc_tplg_ctl_hdr *control_hdr;
+       int ret;
        int i;
 
        if (tplg->pass != SOC_TPLG_PASS_MIXER) {
@@ -1146,25 +1153,30 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
                case SND_SOC_TPLG_CTL_RANGE:
                case SND_SOC_TPLG_DAPM_CTL_VOLSW:
                case SND_SOC_TPLG_DAPM_CTL_PIN:
-                       soc_tplg_dmixer_create(tplg, 1,
-                                              le32_to_cpu(hdr->payload_size));
+                       ret = soc_tplg_dmixer_create(tplg, 1,
+                                       le32_to_cpu(hdr->payload_size));
                        break;
                case SND_SOC_TPLG_CTL_ENUM:
                case SND_SOC_TPLG_CTL_ENUM_VALUE:
                case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
                case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
                case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
-                       soc_tplg_denum_create(tplg, 1,
-                                             le32_to_cpu(hdr->payload_size));
+                       ret = soc_tplg_denum_create(tplg, 1,
+                                       le32_to_cpu(hdr->payload_size));
                        break;
                case SND_SOC_TPLG_CTL_BYTES:
-                       soc_tplg_dbytes_create(tplg, 1,
-                                              le32_to_cpu(hdr->payload_size));
+                       ret = soc_tplg_dbytes_create(tplg, 1,
+                                       le32_to_cpu(hdr->payload_size));
                        break;
                default:
                        soc_bind_err(tplg, control_hdr, i);
                        return -EINVAL;
                }
+               if (ret < 0) {
+                       dev_err(tplg->dev, "ASoC: invalid control\n");
+                       return ret;
+               }
+
        }
 
        return 0;
@@ -1272,7 +1284,9 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
                routes[i]->dobj.index = tplg->index;
                list_add(&routes[i]->dobj.list, &tplg->comp->dobj_list);
 
-               soc_tplg_add_route(tplg, routes[i]);
+               ret = soc_tplg_add_route(tplg, routes[i]);
+               if (ret < 0)
+                       break;
 
                /* add route, but keep going if some fail */
                snd_soc_dapm_add_routes(dapm, routes[i], 1);
@@ -1355,7 +1369,13 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create(
                }
 
                /* create any TLV data */
-               soc_tplg_create_tlv(tplg, &kc[i], &mc->hdr);
+               err = soc_tplg_create_tlv(tplg, &kc[i], &mc->hdr);
+               if (err < 0) {
+                       dev_err(tplg->dev, "ASoC: failed to create TLV %s\n",
+                               mc->hdr.name);
+                       kfree(sm);
+                       continue;
+               }
 
                /* pass control to driver for optional further init */
                err = soc_tplg_init_kcontrol(tplg, &kc[i],
@@ -1766,10 +1786,13 @@ static int soc_tplg_dapm_complete(struct soc_tplg *tplg)
        return 0;
 }
 
-static void set_stream_info(struct snd_soc_pcm_stream *stream,
+static int set_stream_info(struct snd_soc_pcm_stream *stream,
        struct snd_soc_tplg_stream_caps *caps)
 {
        stream->stream_name = kstrdup(caps->name, GFP_KERNEL);
+       if (!stream->stream_name)
+               return -ENOMEM;
+
        stream->channels_min = le32_to_cpu(caps->channels_min);
        stream->channels_max = le32_to_cpu(caps->channels_max);
        stream->rates = le32_to_cpu(caps->rates);
@@ -1777,6 +1800,8 @@ static void set_stream_info(struct snd_soc_pcm_stream *stream,
        stream->rate_max = le32_to_cpu(caps->rate_max);
        stream->formats = le64_to_cpu(caps->formats);
        stream->sig_bits = le32_to_cpu(caps->sig_bits);
+
+       return 0;
 }
 
 static void set_dai_flags(struct snd_soc_dai_driver *dai_drv,
@@ -1812,20 +1837,29 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
        if (dai_drv == NULL)
                return -ENOMEM;
 
-       if (strlen(pcm->dai_name))
+       if (strlen(pcm->dai_name)) {
                dai_drv->name = kstrdup(pcm->dai_name, GFP_KERNEL);
+               if (!dai_drv->name) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+       }
        dai_drv->id = le32_to_cpu(pcm->dai_id);
 
        if (pcm->playback) {
                stream = &dai_drv->playback;
                caps = &pcm->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
-               set_stream_info(stream, caps);
+               ret = set_stream_info(stream, caps);
+               if (ret < 0)
+                       goto err;
        }
 
        if (pcm->capture) {
                stream = &dai_drv->capture;
                caps = &pcm->caps[SND_SOC_TPLG_STREAM_CAPTURE];
-               set_stream_info(stream, caps);
+               ret = set_stream_info(stream, caps);
+               if (ret < 0)
+                       goto err;
        }
 
        if (pcm->compress)
@@ -1835,11 +1869,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
        ret = soc_tplg_dai_load(tplg, dai_drv, pcm, NULL);
        if (ret < 0) {
                dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
-               kfree(dai_drv->playback.stream_name);
-               kfree(dai_drv->capture.stream_name);
-               kfree(dai_drv->name);
-               kfree(dai_drv);
-               return ret;
+               goto err;
        }
 
        dai_drv->dobj.index = tplg->index;
@@ -1860,6 +1890,14 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
                return ret;
        }
 
+       return 0;
+
+err:
+       kfree(dai_drv->playback.stream_name);
+       kfree(dai_drv->capture.stream_name);
+       kfree(dai_drv->name);
+       kfree(dai_drv);
+
        return ret;
 }
 
@@ -1916,11 +1954,20 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
        if (strlen(pcm->pcm_name)) {
                link->name = kstrdup(pcm->pcm_name, GFP_KERNEL);
                link->stream_name = kstrdup(pcm->pcm_name, GFP_KERNEL);
+               if (!link->name || !link->stream_name) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
        }
        link->id = le32_to_cpu(pcm->pcm_id);
 
-       if (strlen(pcm->dai_name))
+       if (strlen(pcm->dai_name)) {
                link->cpus->dai_name = kstrdup(pcm->dai_name, GFP_KERNEL);
+               if (!link->cpus->dai_name) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+       }
 
        link->codecs->name = "snd-soc-dummy";
        link->codecs->dai_name = "snd-soc-dummy-dai";
@@ -2088,7 +2135,9 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
                        _pcm = pcm;
                } else {
                        abi_match = false;
-                       pcm_new_ver(tplg, pcm, &_pcm);
+                       ret = pcm_new_ver(tplg, pcm, &_pcm);
+                       if (ret < 0)
+                               return ret;
                }
 
                /* create the FE DAIs and DAI links */
@@ -2436,13 +2485,17 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg,
        if (d->playback) {
                stream = &dai_drv->playback;
                caps = &d->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
-               set_stream_info(stream, caps);
+               ret = set_stream_info(stream, caps);
+               if (ret < 0)
+                       goto err;
        }
 
        if (d->capture) {
                stream = &dai_drv->capture;
                caps = &d->caps[SND_SOC_TPLG_STREAM_CAPTURE];
-               set_stream_info(stream, caps);
+               ret = set_stream_info(stream, caps);
+               if (ret < 0)
+                       goto err;
        }
 
        if (d->flag_mask)
@@ -2454,10 +2507,15 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg,
        ret = soc_tplg_dai_load(tplg, dai_drv, NULL, dai);
        if (ret < 0) {
                dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
-               return ret;
+               goto err;
        }
 
        return 0;
+
+err:
+       kfree(dai_drv->playback.stream_name);
+       kfree(dai_drv->capture.stream_name);
+       return ret;
 }
 
 /* load physical DAI elements */
@@ -2466,7 +2524,7 @@ static int soc_tplg_dai_elems_load(struct soc_tplg *tplg,
 {
        struct snd_soc_tplg_dai *dai;
        int count;
-       int i;
+       int i, ret;
 
        count = le32_to_cpu(hdr->count);
 
@@ -2481,7 +2539,12 @@ static int soc_tplg_dai_elems_load(struct soc_tplg *tplg,
                        return -EINVAL;
                }
 
-               soc_tplg_dai_config(tplg, dai);
+               ret = soc_tplg_dai_config(tplg, dai);
+               if (ret < 0) {
+                       dev_err(tplg->dev, "ASoC: failed to configure DAI\n");
+                       return ret;
+               }
+
                tplg->pos += (sizeof(*dai) + le32_to_cpu(dai->priv.size));
        }
 
@@ -2589,7 +2652,7 @@ static int soc_valid_header(struct soc_tplg *tplg,
        }
 
        /* big endian firmware objects not supported atm */
-       if (hdr->magic == SOC_TPLG_MAGIC_BIG_ENDIAN) {
+       if (le32_to_cpu(hdr->magic) == SOC_TPLG_MAGIC_BIG_ENDIAN) {
                dev_err(tplg->dev,
                        "ASoC: pass %d big endian not supported header got %x at offset 0x%lx size 0x%zx.\n",
                        tplg->pass, hdr->magic,
index 6c23c57693309dbe4071659d568c87571a90b1a0..a32a3ef78ec5d36ac6f1fba9689ae8b1f2f955ec 100644 (file)
@@ -567,9 +567,25 @@ static void bdw_set_mach_params(const struct snd_soc_acpi_mach *mach,
 static struct snd_soc_dai_driver bdw_dai[] = {
 {
        .name = "ssp0-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
 },
 {
        .name = "ssp1-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
 },
 };
 
index f84391294f12c1f19d21bd526f21dd0378436a9a..29fd1d86156ce40227b7a54660ac555dd9333377 100644 (file)
@@ -459,21 +459,69 @@ static void byt_set_mach_params(const struct snd_soc_acpi_mach *mach,
 static struct snd_soc_dai_driver byt_dai[] = {
 {
        .name = "ssp0-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
 },
 {
        .name = "ssp1-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
 },
 {
        .name = "ssp2-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       }
 },
 {
        .name = "ssp3-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
 },
 {
        .name = "ssp4-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
 },
 {
        .name = "ssp5-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
 },
 };
 
index 0d0c9afd8791f46dafd9b11f448fb9f01efdd007..41f01c3e639eeb9a57333e513b0119051ec0e554 100644 (file)
@@ -837,7 +837,7 @@ static int stm32_sai_set_config(struct snd_soc_dai *cpu_dai,
                cr1 = SAI_XCR1_DS_SET(SAI_DATASIZE_32);
                break;
        default:
-               dev_err(cpu_dai->dev, "Data format not supported");
+               dev_err(cpu_dai->dev, "Data format not supported\n");
                return -EINVAL;
        }
 
@@ -1547,6 +1547,9 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
                return ret;
        }
 
+       if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
+               conf = &stm32_sai_pcm_config_spdif;
+
        ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
        if (ret) {
                if (ret != -EPROBE_DEFER)
@@ -1556,15 +1559,10 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
 
        ret = snd_soc_register_component(&pdev->dev, &stm32_component,
                                         &sai->cpu_dai_drv, 1);
-       if (ret) {
+       if (ret)
                snd_dmaengine_pcm_unregister(&pdev->dev);
-               return ret;
-       }
-
-       if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
-               conf = &stm32_sai_pcm_config_spdif;
 
-       return 0;
+       return ret;
 }
 
 static int stm32_sai_sub_remove(struct platform_device *pdev)
index 50e1874c847c68d98166daea260088d0e69de53c..5ffb457cc88cf0b0a1062589f808f6edb50d512f 100644 (file)
@@ -277,6 +277,52 @@ static bool s1810c_valid_sample_rate(struct audioformat *fp,
        return false;
 }
 
+/*
+ * Many Focusrite devices supports a limited set of sampling rates per
+ * altsetting. Maximum rate is exposed in the last 4 bytes of Format Type
+ * descriptor which has a non-standard bLength = 10.
+ */
+static bool focusrite_valid_sample_rate(struct snd_usb_audio *chip,
+                                       struct audioformat *fp,
+                                       unsigned int rate)
+{
+       struct usb_interface *iface;
+       struct usb_host_interface *alts;
+       unsigned char *fmt;
+       unsigned int max_rate;
+
+       iface = usb_ifnum_to_if(chip->dev, fp->iface);
+       if (!iface)
+               return true;
+
+       alts = &iface->altsetting[fp->altset_idx];
+       fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen,
+                                     NULL, UAC_FORMAT_TYPE);
+       if (!fmt)
+               return true;
+
+       if (fmt[0] == 10) { /* bLength */
+               max_rate = combine_quad(&fmt[6]);
+
+               /* Validate max rate */
+               if (max_rate != 48000 &&
+                   max_rate != 96000 &&
+                   max_rate != 192000 &&
+                   max_rate != 384000) {
+
+                       usb_audio_info(chip,
+                               "%u:%d : unexpected max rate: %u\n",
+                               fp->iface, fp->altsetting, max_rate);
+
+                       return true;
+               }
+
+               return rate <= max_rate;
+       }
+
+       return true;
+}
+
 /*
  * Helper function to walk the array of sample rate triplets reported by
  * the device. The problem is that we need to parse whole array first to
@@ -319,6 +365,11 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip,
                            !s1810c_valid_sample_rate(fp, rate))
                                goto skip_rate;
 
+                       /* Filter out invalid rates on Focusrite devices */
+                       if (USB_ID_VENDOR(chip->usb_id) == 0x1235 &&
+                           !focusrite_valid_sample_rate(chip, fp, rate))
+                               goto skip_rate;
+
                        if (fp->rate_table)
                                fp->rate_table[nr_rates] = rate;
                        if (!fp->rate_min || rate < fp->rate_min)
index d37db32ecd3b736fe737a94ef25ddedeaa9a826d..e39dc85c355a0c8828100854634a0ee85683f127 100644 (file)
@@ -21,8 +21,7 @@
 enum {
        LINE6_PODHD300,
        LINE6_PODHD400,
-       LINE6_PODHD500_0,
-       LINE6_PODHD500_1,
+       LINE6_PODHD500,
        LINE6_PODX3,
        LINE6_PODX3LIVE,
        LINE6_PODHD500X,
@@ -318,8 +317,7 @@ static const struct usb_device_id podhd_id_table[] = {
        /* TODO: no need to alloc data interfaces when only audio is used */
        { LINE6_DEVICE(0x5057),    .driver_info = LINE6_PODHD300 },
        { LINE6_DEVICE(0x5058),    .driver_info = LINE6_PODHD400 },
-       { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 },
-       { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 },
+       { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500 },
        { LINE6_IF_NUM(0x414A, 0), .driver_info = LINE6_PODX3 },
        { LINE6_IF_NUM(0x414B, 0), .driver_info = LINE6_PODX3LIVE },
        { LINE6_IF_NUM(0x4159, 0), .driver_info = LINE6_PODHD500X },
@@ -352,23 +350,13 @@ static const struct line6_properties podhd_properties_table[] = {
                .ep_audio_r = 0x82,
                .ep_audio_w = 0x01,
        },
-       [LINE6_PODHD500_0] = {
+       [LINE6_PODHD500] = {
                .id = "PODHD500",
                .name = "POD HD500",
-               .capabilities   = LINE6_CAP_PCM
+               .capabilities   = LINE6_CAP_PCM | LINE6_CAP_CONTROL
                                | LINE6_CAP_HWMON,
                .altsetting = 1,
-               .ep_ctrl_r = 0x81,
-               .ep_ctrl_w = 0x01,
-               .ep_audio_r = 0x86,
-               .ep_audio_w = 0x02,
-       },
-       [LINE6_PODHD500_1] = {
-               .id = "PODHD500",
-               .name = "POD HD500",
-               .capabilities   = LINE6_CAP_PCM
-                               | LINE6_CAP_HWMON,
-               .altsetting = 0,
+               .ctrl_if = 1,
                .ep_ctrl_r = 0x81,
                .ep_ctrl_w = 0x01,
                .ep_audio_r = 0x86,
index 721d12130d0cb4aae2b943e8fb75153212032331..a88d7854513b96ff7dc3f44ccaebfeea2b12ee35 100644 (file)
@@ -1457,7 +1457,7 @@ error:
                usb_audio_err(chip,
                        "cannot get connectors status: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
                        UAC_GET_CUR, validx, idx, cval->val_type);
-               return ret;
+               return filter_error(cval, ret);
        }
 
        ucontrol->value.integer.value[0] = val;
@@ -1771,10 +1771,16 @@ static void get_connector_control_name(struct usb_mixer_interface *mixer,
 
 /* Build a mixer control for a UAC connector control (jack-detect) */
 static void build_connector_control(struct usb_mixer_interface *mixer,
+                                   const struct usbmix_name_map *imap,
                                    struct usb_audio_term *term, bool is_input)
 {
        struct snd_kcontrol *kctl;
        struct usb_mixer_elem_info *cval;
+       const struct usbmix_name_map *map;
+
+       map = find_map(imap, term->id, 0);
+       if (check_ignored_ctl(map))
+               return;
 
        cval = kzalloc(sizeof(*cval), GFP_KERNEL);
        if (!cval)
@@ -1805,8 +1811,12 @@ static void build_connector_control(struct usb_mixer_interface *mixer,
                usb_mixer_elem_info_free(cval);
                return;
        }
-       get_connector_control_name(mixer, term, is_input, kctl->id.name,
-                                  sizeof(kctl->id.name));
+
+       if (check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)))
+               strlcat(kctl->id.name, " Jack", sizeof(kctl->id.name));
+       else
+               get_connector_control_name(mixer, term, is_input, kctl->id.name,
+                                          sizeof(kctl->id.name));
        kctl->private_free = snd_usb_mixer_elem_free;
        snd_usb_mixer_add_control(&cval->head, kctl);
 }
@@ -2109,8 +2119,9 @@ static int parse_audio_input_terminal(struct mixer_build *state, int unitid,
        check_input_term(state, term_id, &iterm);
 
        /* Check for jack detection. */
-       if (uac_v2v3_control_is_readable(bmctls, control))
-               build_connector_control(state->mixer, &iterm, true);
+       if ((iterm.type & 0xff00) != 0x0100 &&
+           uac_v2v3_control_is_readable(bmctls, control))
+               build_connector_control(state->mixer, state->map, &iterm, true);
 
        return 0;
 }
@@ -3071,13 +3082,13 @@ static int snd_usb_mixer_controls_badd(struct usb_mixer_interface *mixer,
                memset(&iterm, 0, sizeof(iterm));
                iterm.id = UAC3_BADD_IT_ID4;
                iterm.type = UAC_BIDIR_TERMINAL_HEADSET;
-               build_connector_control(mixer, &iterm, true);
+               build_connector_control(mixer, map->map, &iterm, true);
 
                /* Output Term - Insertion control */
                memset(&oterm, 0, sizeof(oterm));
                oterm.id = UAC3_BADD_OT_ID3;
                oterm.type = UAC_BIDIR_TERMINAL_HEADSET;
-               build_connector_control(mixer, &oterm, false);
+               build_connector_control(mixer, map->map, &oterm, false);
        }
 
        return 0;
@@ -3106,7 +3117,8 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
                if (map->id == state.chip->usb_id) {
                        state.map = map->map;
                        state.selector_map = map->selector_map;
-                       mixer->ignore_ctl_error = map->ignore_ctl_error;
+                       mixer->connector_map = map->connector_map;
+                       mixer->ignore_ctl_error |= map->ignore_ctl_error;
                        break;
                }
        }
@@ -3149,10 +3161,11 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
                        if (err < 0 && err != -EINVAL)
                                return err;
 
-                       if (uac_v2v3_control_is_readable(le16_to_cpu(desc->bmControls),
+                       if ((state.oterm.type & 0xff00) != 0x0100 &&
+                           uac_v2v3_control_is_readable(le16_to_cpu(desc->bmControls),
                                                         UAC2_TE_CONNECTOR)) {
-                               build_connector_control(state.mixer, &state.oterm,
-                                                       false);
+                               build_connector_control(state.mixer, state.map,
+                                                       &state.oterm, false);
                        }
                } else {  /* UAC_VERSION_3 */
                        struct uac3_output_terminal_descriptor *desc = p;
@@ -3174,10 +3187,11 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
                        if (err < 0 && err != -EINVAL)
                                return err;
 
-                       if (uac_v2v3_control_is_readable(le32_to_cpu(desc->bmControls),
+                       if ((state.oterm.type & 0xff00) != 0x0100 &&
+                           uac_v2v3_control_is_readable(le32_to_cpu(desc->bmControls),
                                                         UAC3_TE_INSERTION)) {
-                               build_connector_control(state.mixer, &state.oterm,
-                                                       false);
+                               build_connector_control(state.mixer, state.map,
+                                                       &state.oterm, false);
                        }
                }
        }
@@ -3185,10 +3199,32 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
        return 0;
 }
 
+static int delegate_notify(struct usb_mixer_interface *mixer, int unitid,
+                          u8 *control, u8 *channel)
+{
+       const struct usbmix_connector_map *map = mixer->connector_map;
+
+       if (!map)
+               return unitid;
+
+       for (; map->id; map++) {
+               if (map->id == unitid) {
+                       if (control && map->control)
+                               *control = map->control;
+                       if (channel && map->channel)
+                               *channel = map->channel;
+                       return map->delegated_id;
+               }
+       }
+       return unitid;
+}
+
 void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
 {
        struct usb_mixer_elem_list *list;
 
+       unitid = delegate_notify(mixer, unitid, NULL, NULL);
+
        for_each_mixer_elem(list, mixer, unitid) {
                struct usb_mixer_elem_info *info =
                        mixer_elem_list_to_info(list);
@@ -3258,6 +3294,8 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
                return;
        }
 
+       unitid = delegate_notify(mixer, unitid, &control, &channel);
+
        for_each_mixer_elem(list, mixer, unitid)
                count++;
 
index 65d6d08c96f53e6f67686d20a85ba85c7ca6809b..41ec9dc4139bbec3512ccd2bc2cc04124a451543 100644 (file)
@@ -6,6 +6,13 @@
 
 struct media_mixer_ctl;
 
+struct usbmix_connector_map {
+       u8 id;
+       u8 delegated_id;
+       u8 control;
+       u8 channel;
+};
+
 struct usb_mixer_interface {
        struct snd_usb_audio *chip;
        struct usb_host_interface *hostif;
@@ -18,6 +25,9 @@ struct usb_mixer_interface {
        /* the usb audio specification version this interface complies to */
        int protocol;
 
+       /* optional connector delegation map */
+       const struct usbmix_connector_map *connector_map;
+
        /* Sound Blaster remote control stuff */
        const struct rc_config *rc_cfg;
        u32 rc_code;
index 72b575c348605aaf91511eeb590bcaea4a88f26b..0260c750e15693267b1b16095e124f6fb60cbeb6 100644 (file)
@@ -27,6 +27,7 @@ struct usbmix_ctl_map {
        u32 id;
        const struct usbmix_name_map *map;
        const struct usbmix_selector_map *selector_map;
+       const struct usbmix_connector_map *connector_map;
        int ignore_ctl_error;
 };
 
@@ -360,13 +361,42 @@ static const struct usbmix_name_map corsair_virtuoso_map[] = {
 };
 
 /* Some mobos shipped with a dummy HD-audio show the invalid GET_MIN/GET_MAX
- * response for Input Gain Pad (id=19, control=12).  Skip it.
+ * response for Input Gain Pad (id=19, control=12) and the connector status
+ * for SPDIF terminal (id=18).  Skip them.
  */
 static const struct usbmix_name_map asus_rog_map[] = {
+       { 18, NULL }, /* OT, connector control */
        { 19, NULL, 12 }, /* FU, Input Gain Pad */
        {}
 };
 
+/* TRX40 mobos with Realtek ALC1220-VB */
+static const struct usbmix_name_map trx40_mobo_map[] = {
+       { 18, NULL }, /* OT, IEC958 - broken response, disabled */
+       { 19, NULL, 12 }, /* FU, Input Gain Pad - broken response, disabled */
+       { 16, "Speaker" },              /* OT */
+       { 22, "Speaker Playback" },     /* FU */
+       { 7, "Line" },                  /* IT */
+       { 19, "Line Capture" },         /* FU */
+       { 17, "Front Headphone" },      /* OT */
+       { 23, "Front Headphone Playback" },     /* FU */
+       { 8, "Mic" },                   /* IT */
+       { 20, "Mic Capture" },          /* FU */
+       { 9, "Front Mic" },             /* IT */
+       { 21, "Front Mic Capture" },    /* FU */
+       { 24, "IEC958 Playback" },      /* FU */
+       {}
+};
+
+static const struct usbmix_connector_map trx40_mobo_connector_map[] = {
+       { 10, 16 },     /* (Back) Speaker */
+       { 11, 17 },     /* Front Headphone */
+       { 13, 7 },      /* Line */
+       { 14, 8 },      /* Mic */
+       { 15, 9 },      /* Front Mic */
+       {}
+};
+
 /*
  * Control map entries
  */
@@ -498,7 +528,8 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
        },
        {       /* Gigabyte TRX40 Aorus Pro WiFi */
                .id = USB_ID(0x0414, 0xa002),
-               .map = asus_rog_map,
+               .map = trx40_mobo_map,
+               .connector_map = trx40_mobo_connector_map,
        },
        {       /* ASUS ROG Zenith II */
                .id = USB_ID(0x0b05, 0x1916),
@@ -510,11 +541,13 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
        },
        {       /* MSI TRX40 Creator */
                .id = USB_ID(0x0db0, 0x0d64),
-               .map = asus_rog_map,
+               .map = trx40_mobo_map,
+               .connector_map = trx40_mobo_connector_map,
        },
        {       /* MSI TRX40 */
                .id = USB_ID(0x0db0, 0x543d),
-               .map = asus_rog_map,
+               .map = trx40_mobo_map,
+               .connector_map = trx40_mobo_connector_map,
        },
        { 0 } /* terminator */
 };
index 02b036b2aefbd6a85c134c4f4e5f2822c3249065..a5f65a9a02546bd83dfd5e68f7d4433eed79518e 100644 (file)
@@ -1509,11 +1509,15 @@ static int snd_microii_spdif_default_get(struct snd_kcontrol *kcontrol,
 
        /* use known values for that card: interface#1 altsetting#1 */
        iface = usb_ifnum_to_if(chip->dev, 1);
-       if (!iface || iface->num_altsetting < 2)
-               return -EINVAL;
+       if (!iface || iface->num_altsetting < 2) {
+               err = -EINVAL;
+               goto end;
+       }
        alts = &iface->altsetting[1];
-       if (get_iface_desc(alts)->bNumEndpoints < 1)
-               return -EINVAL;
+       if (get_iface_desc(alts)->bNumEndpoints < 1) {
+               err = -EINVAL;
+               goto end;
+       }
        ep = get_endpoint(alts, 0)->bEndpointAddress;
 
        err = snd_usb_ctl_msg(chip->dev,
index e009d584e7d08aaed05dda6ad10a145488b5a133..a1df4c5b4f8cbf9ae6c63f95fe759897a41dda43 100644 (file)
@@ -2756,90 +2756,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                .type = QUIRK_MIDI_NOVATION
        }
 },
-{
-       /*
-        * Focusrite Scarlett Solo 2nd generation
-        * Reports that playback should use Synch: Synchronous
-        * while still providing a feedback endpoint. Synchronous causes
-        * snapping on some sample rates.
-        * Force it to use Synch: Asynchronous.
-        */
-       USB_DEVICE(0x1235, 0x8205),
-       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-               .ifnum = QUIRK_ANY_INTERFACE,
-               .type = QUIRK_COMPOSITE,
-               .data = (const struct snd_usb_audio_quirk[]) {
-                       {
-                               .ifnum = 1,
-                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
-                               .data = & (const struct audioformat) {
-                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
-                                       .channels = 2,
-                                       .iface = 1,
-                                       .altsetting = 1,
-                                       .altset_idx = 1,
-                                       .attributes = 0,
-                                       .endpoint = 0x01,
-                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
-                                                  USB_ENDPOINT_SYNC_ASYNC,
-                                       .protocol = UAC_VERSION_2,
-                                       .rates = SNDRV_PCM_RATE_44100 |
-                                                SNDRV_PCM_RATE_48000 |
-                                                SNDRV_PCM_RATE_88200 |
-                                                SNDRV_PCM_RATE_96000 |
-                                                SNDRV_PCM_RATE_176400 |
-                                                SNDRV_PCM_RATE_192000,
-                                       .rate_min = 44100,
-                                       .rate_max = 192000,
-                                       .nr_rates = 6,
-                                       .rate_table = (unsigned int[]) {
-                                               44100, 48000, 88200,
-                                               96000, 176400, 192000
-                                       },
-                                       .clock = 41
-                               }
-                       },
-                       {
-                               .ifnum = 2,
-                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
-                               .data = & (const struct audioformat) {
-                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
-                                       .channels = 2,
-                                       .iface = 2,
-                                       .altsetting = 1,
-                                       .altset_idx = 1,
-                                       .attributes = 0,
-                                       .endpoint = 0x82,
-                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
-                                                  USB_ENDPOINT_SYNC_ASYNC |
-                                                  USB_ENDPOINT_USAGE_IMPLICIT_FB,
-                                       .protocol = UAC_VERSION_2,
-                                       .rates = SNDRV_PCM_RATE_44100 |
-                                                SNDRV_PCM_RATE_48000 |
-                                                SNDRV_PCM_RATE_88200 |
-                                                SNDRV_PCM_RATE_96000 |
-                                                SNDRV_PCM_RATE_176400 |
-                                                SNDRV_PCM_RATE_192000,
-                                       .rate_min = 44100,
-                                       .rate_max = 192000,
-                                       .nr_rates = 6,
-                                       .rate_table = (unsigned int[]) {
-                                               44100, 48000, 88200,
-                                               96000, 176400, 192000
-                                       },
-                                       .clock = 41
-                               }
-                       },
-                       {
-                               .ifnum = 3,
-                               .type = QUIRK_IGNORE_INTERFACE
-                       },
-                       {
-                               .ifnum = -1
-                       }
-               }
-       }
-},
 
 /* Access Music devices */
 {
@@ -3635,4 +3551,18 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
        }
 },
 
+#define ALC1220_VB_DESKTOP(vend, prod) { \
+       USB_DEVICE(vend, prod), \
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \
+               .vendor_name = "Realtek", \
+               .product_name = "ALC1220-VB-DT", \
+               .profile_name = "Realtek-ALC1220-VB-Desktop", \
+               .ifnum = QUIRK_NO_INTERFACE \
+       } \
+}
+ALC1220_VB_DESKTOP(0x0414, 0xa002), /* Gigabyte TRX40 Aorus Pro WiFi */
+ALC1220_VB_DESKTOP(0x0db0, 0x0d64), /* MSI TRX40 Creator */
+ALC1220_VB_DESKTOP(0x0db0, 0x543d), /* MSI TRX40 */
+#undef ALC1220_VB_DESKTOP
+
 #undef USB_DEVICE_VENDOR_SPEC
index a8ece17010686da6628b6961970ed1fda27cd4d2..848a4cc25bed727a7eebf0e6f52bda39f53bd991 100644 (file)
@@ -1687,7 +1687,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
 
        case USB_ID(0x0d8c, 0x0316): /* Hegel HD12 DSD */
        case USB_ID(0x10cb, 0x0103): /* The Bit Opus #3; with fp->dsd_raw */
-       case USB_ID(0x16b0, 0x06b2): /* NuPrime DAC-10 */
+       case USB_ID(0x16d0, 0x06b2): /* NuPrime DAC-10 */
        case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
        case USB_ID(0x16d0, 0x0733): /* Furutech ADL Stratos */
        case USB_ID(0x16d0, 0x09db): /* NuPrime Audio DAC-9 */
@@ -1806,6 +1806,20 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip,
                 */
                fp->attributes &= ~UAC_EP_CS_ATTR_FILL_MAX;
                break;
+       case USB_ID(0x1235, 0x8200):  /* Focusrite Scarlett 2i4 2nd gen */
+       case USB_ID(0x1235, 0x8202):  /* Focusrite Scarlett 2i2 2nd gen */
+       case USB_ID(0x1235, 0x8205):  /* Focusrite Scarlett Solo 2nd gen */
+               /*
+                * Reports that playback should use Synch: Synchronous
+                * while still providing a feedback endpoint.
+                * Synchronous causes snapping on some sample rates.
+                * Force it to use Synch: Asynchronous.
+                */
+               if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE;
+                       fp->ep_attr |= USB_ENDPOINT_SYNC_ASYNC;
+               }
+               break;
        }
 }
 
index 37d290fe9d4350caad5ddea7ea7432dd566ff85b..ecaf41265dcd0d61889130558694541288f117ef 100644 (file)
@@ -681,6 +681,8 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate)
                        us->submitted = 2*NOOF_SETRATE_URBS;
                        for (i = 0; i < NOOF_SETRATE_URBS; ++i) {
                                struct urb *urb = us->urb[i];
+                               if (!urb)
+                                       continue;
                                if (urb->status) {
                                        if (!err)
                                                err = -ENODEV;
index f3327cb56edfe163d1a8fc0a45b89fb324573243..db189945e9b0c599b4bda0e44f2372f7140e2085 100644 (file)
 #define X86_FEATURE_IBRS               ( 7*32+25) /* Indirect Branch Restricted Speculation */
 #define X86_FEATURE_IBPB               ( 7*32+26) /* Indirect Branch Prediction Barrier */
 #define X86_FEATURE_STIBP              ( 7*32+27) /* Single Thread Indirect Branch Predictors */
-#define X86_FEATURE_ZEN                        ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */
+#define X86_FEATURE_ZEN                        ( 7*32+28) /* "" CPU is AMD family 0x17 or above (Zen) */
 #define X86_FEATURE_L1TF_PTEINV                ( 7*32+29) /* "" L1TF workaround PTE inversion */
 #define X86_FEATURE_IBRS_ENHANCED      ( 7*32+30) /* Enhanced IBRS */
 #define X86_FEATURE_MSR_IA32_FEAT_CTL  ( 7*32+31) /* "" MSR IA32_FEAT_CTL configured */
 #define X86_FEATURE_CQM_MBM_LOCAL      (11*32+ 3) /* LLC Local MBM monitoring */
 #define X86_FEATURE_FENCE_SWAPGS_USER  (11*32+ 4) /* "" LFENCE in user entry SWAPGS path */
 #define X86_FEATURE_FENCE_SWAPGS_KERNEL        (11*32+ 5) /* "" LFENCE in kernel entry SWAPGS path */
+#define X86_FEATURE_SPLIT_LOCK_DETECT  (11*32+ 6) /* #AC for split lock */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
 #define X86_FEATURE_AVX512_BF16                (12*32+ 5) /* AVX512 BFLOAT16 instructions */
 #define X86_FEATURE_AMD_IBRS           (13*32+14) /* "" Indirect Branch Restricted Speculation */
 #define X86_FEATURE_AMD_STIBP          (13*32+15) /* "" Single Thread Indirect Branch Predictors */
 #define X86_FEATURE_AMD_STIBP_ALWAYS_ON        (13*32+17) /* "" Single Thread Indirect Branch Predictors always-on preferred */
+#define X86_FEATURE_AMD_PPIN           (13*32+23) /* Protected Processor Inventory Number */
 #define X86_FEATURE_AMD_SSBD           (13*32+24) /* "" Speculative Store Bypass Disable */
 #define X86_FEATURE_VIRT_SSBD          (13*32+25) /* Virtualized Speculative Store Bypass Disable */
 #define X86_FEATURE_AMD_SSB_NO         (13*32+26) /* "" Speculative Store Bypass is fixed in hardware. */
 #define X86_FEATURE_INTEL_STIBP                (18*32+27) /* "" Single Thread Indirect Branch Predictors */
 #define X86_FEATURE_FLUSH_L1D          (18*32+28) /* Flush L1D cache */
 #define X86_FEATURE_ARCH_CAPABILITIES  (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */
+#define X86_FEATURE_CORE_CAPABILITIES  (18*32+30) /* "" IA32_CORE_CAPABILITIES MSR */
 #define X86_FEATURE_SPEC_CTRL_SSBD     (18*32+31) /* "" Speculative Store Bypass Disable */
 
 /*
index d5e517d1c3ddc5c9ac6e594500d87524168b143d..12c9684d59ba6fea4df36257c7f1b8eb89ab5943 100644 (file)
 
 /* Intel MSRs. Some also available on other CPUs */
 
+#define MSR_TEST_CTRL                          0x00000033
+#define MSR_TEST_CTRL_SPLIT_LOCK_DETECT_BIT    29
+#define MSR_TEST_CTRL_SPLIT_LOCK_DETECT                BIT(MSR_TEST_CTRL_SPLIT_LOCK_DETECT_BIT)
+
 #define MSR_IA32_SPEC_CTRL             0x00000048 /* Speculation Control */
 #define SPEC_CTRL_IBRS                 BIT(0)     /* Indirect Branch Restricted Speculation */
 #define SPEC_CTRL_STIBP_SHIFT          1          /* Single Thread Indirect Branch Predictor (STIBP) bit */
  */
 #define MSR_IA32_UMWAIT_CONTROL_TIME_MASK      (~0x03U)
 
+/* Abbreviated from Intel SDM name IA32_CORE_CAPABILITIES */
+#define MSR_IA32_CORE_CAPS                       0x000000cf
+#define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT  5
+#define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT     BIT(MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT)
+
 #define MSR_PKG_CST_CONFIG_CONTROL     0x000000e2
 #define NHM_C3_AUTO_DEMOTE             (1UL << 25)
 #define NHM_C1_AUTO_DEMOTE             (1UL << 26)
index 16b9a420e6fd325bee88ed3ff53c2eb245f98746..001076c517125541a0c12ddfa5053ed0c4cf0285 100644 (file)
@@ -314,6 +314,7 @@ int apply_xbc(const char *path, const char *xbc_path)
        ret = delete_xbc(path);
        if (ret < 0) {
                pr_err("Failed to delete previous boot config: %d\n", ret);
+               free(data);
                return ret;
        }
 
@@ -321,24 +322,26 @@ int apply_xbc(const char *path, const char *xbc_path)
        fd = open(path, O_RDWR | O_APPEND);
        if (fd < 0) {
                pr_err("Failed to open %s: %d\n", path, fd);
+               free(data);
                return fd;
        }
        /* TODO: Ensure the @path is initramfs/initrd image */
        ret = write(fd, data, size + 8);
        if (ret < 0) {
                pr_err("Failed to apply a boot config: %d\n", ret);
-               return ret;
+               goto out;
        }
        /* 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;
+               goto out;
        }
+out:
        close(fd);
        free(data);
 
-       return 0;
+       return ret;
 }
 
 int usage(void)
index 2a7befbd11ad54de08160cf47dd970c7a6175e81..e17738479edcc01c94d9669611f2c706869dec71 100644 (file)
@@ -479,6 +479,7 @@ static int do_unregister(int argc, char **argv)
 
 static int do_register(int argc, char **argv)
 {
+       struct bpf_object_load_attr load_attr = {};
        const struct bpf_map_def *def;
        struct bpf_map_info info = {};
        __u32 info_len = sizeof(info);
@@ -499,7 +500,12 @@ static int do_register(int argc, char **argv)
 
        set_max_rlimit();
 
-       if (bpf_object__load(obj)) {
+       load_attr.obj = obj;
+       if (verifier_logs)
+               /* log_level1 + log_level2 + stats, but not stable UAPI */
+               load_attr.log_level = 1 + 2 + 4;
+
+       if (bpf_object__load_xattr(&load_attr)) {
                bpf_object__close(obj);
                return -1;
        }
@@ -591,6 +597,8 @@ int do_struct_ops(int argc, char **argv)
 
        err = cmd_select(cmds, argc, argv, do_help);
 
-       btf__free(btf_vmlinux);
+       if (!IS_ERR(btf_vmlinux))
+               btf__free(btf_vmlinux);
+
        return err;
 }
index 39edd68afa8e08be1ea3adf9da188b56b9648e24..8a6f82e56a249af134cdb9261720a891f1fa1f4d 100644 (file)
@@ -8,7 +8,7 @@ BPFTOOL ?= $(DEFAULT_BPFTOOL)
 LIBBPF_SRC := $(abspath ../../lib/bpf)
 BPFOBJ := $(OUTPUT)/libbpf.a
 BPF_INCLUDE := $(OUTPUT)
-INCLUDES := -I$(BPF_INCLUDE) -I$(OUTPUT) -I$(abspath ../../lib)
+INCLUDES := -I$(OUTPUT) -I$(BPF_INCLUDE) -I$(abspath ../../lib)
 CFLAGS := -g -Wall
 
 # Try to detect best kernel BTF source
index 1e38d1930a972a3a442c314eb1cf5a611bbe472d..3bc6b0768a53170d486b497fe87d51cfee9a626c 100644 (file)
@@ -7,7 +7,7 @@ int main(int argc, char *argv[])
 {
        uint64_t old, new = argc;
 
-       argv = argv;
+       (void)argv;
        do {
                old = __sync_val_compare_and_swap(&x, 0, 0);
        } while (!__sync_bool_compare_and_swap(&x, old, new));
index 7427a5ee761b3757feaf04ff76bf3afd7a91a90c..9d8e9613008a99c4998db7d9bfd8ac4c88cf0575 100644 (file)
@@ -159,7 +159,12 @@ class IocgStat:
         else:
             self.inflight_pct = 0
 
-        self.debt_ms = iocg.abs_vdebt.counter.value_() / VTIME_PER_USEC / 1000
+        # vdebt used to be an atomic64_t and is now u64, support both
+        try:
+            self.debt_ms = iocg.abs_vdebt.counter.value_() / VTIME_PER_USEC / 1000
+        except:
+            self.debt_ms = iocg.abs_vdebt.value_() / VTIME_PER_USEC / 1000
+
         self.use_delay = blkg.use_delay.counter.value_()
         self.delay_ms = blkg.delay_nsec.counter.value_() / 1_000_000
 
index 669d69441a625c1639d0699671b9ee41405e84a1..4671fbf28842718fa74c9664dee74f8e129dbb7e 100644 (file)
@@ -3,9 +3,9 @@
 #define __LINUX_BITS_H
 
 #include <linux/const.h>
+#include <vdso/bits.h>
 #include <asm/bitsperlong.h>
 
-#define BIT(nr)                        (UL(1) << (nr))
 #define BIT_ULL(nr)            (ULL(1) << (nr))
 #define BIT_MASK(nr)           (UL(1) << ((nr) % BITS_PER_LONG))
 #define BIT_WORD(nr)           ((nr) / BITS_PER_LONG)
  * position @h. For example
  * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
  */
-#define GENMASK(h, l) \
+#if !defined(__ASSEMBLY__) && \
+       (!defined(CONFIG_CC_IS_GCC) || CONFIG_GCC_VERSION >= 49000)
+#include <linux/build_bug.h>
+#define GENMASK_INPUT_CHECK(h, l) \
+       (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
+               __builtin_constant_p((l) > (h)), (l) > (h), 0)))
+#else
+/*
+ * BUILD_BUG_ON_ZERO is not available in h files included from asm files,
+ * disable the input check if that is the case.
+ */
+#define GENMASK_INPUT_CHECK(h, l) 0
+#endif
+
+#define __GENMASK(h, l) \
        (((~UL(0)) - (UL(1) << (l)) + 1) & \
         (~UL(0) >> (BITS_PER_LONG - 1 - (h))))
+#define GENMASK(h, l) \
+       (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
 
-#define GENMASK_ULL(h, l) \
+#define __GENMASK_ULL(h, l) \
        (((~ULL(0)) - (ULL(1) << (l)) + 1) & \
         (~ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h))))
+#define GENMASK_ULL(h, l) \
+       (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
 
 #endif /* __LINUX_BITS_H */
diff --git a/tools/include/linux/build_bug.h b/tools/include/linux/build_bug.h
new file mode 100644 (file)
index 0000000..cc7070c
--- /dev/null
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_BUILD_BUG_H
+#define _LINUX_BUILD_BUG_H
+
+#include <linux/compiler.h>
+
+#ifdef __CHECKER__
+#define BUILD_BUG_ON_ZERO(e) (0)
+#else /* __CHECKER__ */
+/*
+ * Force a compilation error if condition is true, but also produce a
+ * result (of value 0 and type int), so the expression can be used
+ * e.g. in a structure initializer (or where-ever else comma expressions
+ * aren't permitted).
+ */
+#define BUILD_BUG_ON_ZERO(e) ((int)(sizeof(struct { int:(-!!(e)); })))
+#endif /* __CHECKER__ */
+
+/* Force a compilation error if a constant expression is not a power of 2 */
+#define __BUILD_BUG_ON_NOT_POWER_OF_2(n)       \
+       BUILD_BUG_ON(((n) & ((n) - 1)) != 0)
+#define BUILD_BUG_ON_NOT_POWER_OF_2(n)                 \
+       BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0))
+
+/*
+ * BUILD_BUG_ON_INVALID() permits the compiler to check the validity of the
+ * expression but avoids the generation of any code, even if that expression
+ * has side-effects.
+ */
+#define BUILD_BUG_ON_INVALID(e) ((void)(sizeof((__force long)(e))))
+
+/**
+ * BUILD_BUG_ON_MSG - break compile if a condition is true & emit supplied
+ *                   error message.
+ * @condition: the condition which the compiler should know is false.
+ *
+ * See BUILD_BUG_ON for description.
+ */
+#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
+
+/**
+ * BUILD_BUG_ON - break compile if a condition is true.
+ * @condition: the condition which the compiler should know is false.
+ *
+ * If you have some code which relies on certain constants being equal, or
+ * some other compile-time-evaluated condition, you should use BUILD_BUG_ON to
+ * detect if someone changes it.
+ */
+#define BUILD_BUG_ON(condition) \
+       BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
+
+/**
+ * BUILD_BUG - break compile if used.
+ *
+ * If you have some code that you expect the compiler to eliminate at
+ * build time, you should use BUILD_BUG to detect if it is
+ * unexpectedly used.
+ */
+#define BUILD_BUG() BUILD_BUG_ON_MSG(1, "BUILD_BUG failed")
+
+/**
+ * static_assert - check integer constant expression at build time
+ *
+ * static_assert() is a wrapper for the C11 _Static_assert, with a
+ * little macro magic to make the message optional (defaulting to the
+ * stringification of the tested expression).
+ *
+ * Contrary to BUILD_BUG_ON(), static_assert() can be used at global
+ * scope, but requires the expression to be an integer constant
+ * expression (i.e., it is not enough that __builtin_constant_p() is
+ * true for expr).
+ *
+ * Also note that BUILD_BUG_ON() fails the build if the condition is
+ * true, while static_assert() fails the build if the expression is
+ * false.
+ */
+#ifndef static_assert
+#define static_assert(expr, ...) __static_assert(expr, ##__VA_ARGS__, #expr)
+#define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
+#endif // static_assert
+
+#endif /* _LINUX_BUILD_BUG_H */
index 1827c2f973f93c533ca9a3e12ced636d13319556..180f7714a5f10c75e53ffd883b0b6f680cdb6a37 100644 (file)
 # define __compiletime_error(message)
 #endif
 
+#ifdef __OPTIMIZE__
+# define __compiletime_assert(condition, msg, prefix, suffix)          \
+       do {                                                            \
+               extern void prefix ## suffix(void) __compiletime_error(msg); \
+               if (!(condition))                                       \
+                       prefix ## suffix();                             \
+       } while (0)
+#else
+# define __compiletime_assert(condition, msg, prefix, suffix) do { } while (0)
+#endif
+
+#define _compiletime_assert(condition, msg, prefix, suffix) \
+       __compiletime_assert(condition, msg, prefix, suffix)
+
+/**
+ * compiletime_assert - break build and emit msg if condition is false
+ * @condition: a compile-time constant condition to check
+ * @msg:       a message to emit if condition is false
+ *
+ * In tradition of POSIX assert, this macro will break the build if the
+ * supplied condition is *false*, emitting the supplied error message if the
+ * compiler has support to do so.
+ */
+#define compiletime_assert(condition, msg) \
+       _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
+
 /* Optimization barrier */
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
index 7b55a55f59112ccaec93486899f42b8619be8729..81b8aae5a8559c9fabf0665c48d8e8659db4f239 100644 (file)
@@ -1,9 +1,6 @@
 #ifndef _LINUX_CONST_H
 #define _LINUX_CONST_H
 
-#include <uapi/linux/const.h>
-
-#define UL(x)          (_UL(x))
-#define ULL(x)         (_ULL(x))
+#include <vdso/const.h>
 
 #endif /* _LINUX_CONST_H */
index cba226948a0cec1794a5756c25c4f75c5d7dde76..a7e54a08fb54c41b7b5da231119caab66d5431cc 100644 (file)
@@ -5,6 +5,7 @@
 #include <stdarg.h>
 #include <stddef.h>
 #include <assert.h>
+#include <linux/build_bug.h>
 #include <linux/compiler.h>
 #include <endian.h>
 #include <byteswap.h>
@@ -35,9 +36,6 @@
        (type *)((char *)__mptr - offsetof(type, member)); })
 #endif
 
-#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
-#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
-
 #ifndef max
 #define max(x, y) ({                           \
        typeof(x) _max1 = (x);                  \
index 868bf7996c0f8920e589b58b192528c5a602a9fe..808b48a93330bad83759a3cd81331f812296a12a 100644 (file)
@@ -948,6 +948,8 @@ extern "C" {
 #define DRM_IOCTL_SYNCOBJ_TRANSFER     DRM_IOWR(0xCC, struct drm_syncobj_transfer)
 #define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL      DRM_IOWR(0xCD, struct drm_syncobj_timeline_array)
 
+#define DRM_IOCTL_MODE_GETFB2          DRM_IOWR(0xCE, struct drm_mode_fb_cmd2)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x9f.
index 829c0a48577f8b942b7efbf4d7a6438c7d72a670..2813e579b480cc5e6c10e85663b64ac7dafe9102 100644 (file)
@@ -1619,6 +1619,27 @@ struct drm_i915_gem_context_param {
  * By default, new contexts allow persistence.
  */
 #define I915_CONTEXT_PARAM_PERSISTENCE 0xb
+
+/*
+ * I915_CONTEXT_PARAM_RINGSIZE:
+ *
+ * Sets the size of the CS ringbuffer to use for logical ring contexts. This
+ * applies a limit of how many batches can be queued to HW before the caller
+ * is blocked due to lack of space for more commands.
+ *
+ * Only reliably possible to be set prior to first use, i.e. during
+ * construction. At any later point, the current execution must be flushed as
+ * the ring can only be changed while the context is idle. Note, the ringsize
+ * can be specified as a constructor property, see
+ * I915_CONTEXT_CREATE_EXT_SETPARAM, but can also be set later if required.
+ *
+ * Only applies to the current set of engine and lost when those engines
+ * are replaced by a new mapping (see I915_CONTEXT_PARAM_ENGINES).
+ *
+ * Must be between 4 - 512 KiB, in intervals of page size [4 KiB].
+ * Default is 16 KiB.
+ */
+#define I915_CONTEXT_PARAM_RINGSIZE    0xc
 /* Must be kept compact -- no holes and well documented */
 
        __u64 value;
index 2e29a671d67eb96a3139c893158aa0fc69466213..7bbf1b65be10bf26c5a9309dbeddc34de8072272 100644 (file)
@@ -1642,7 +1642,7 @@ union bpf_attr {
  *             ifindex, but doesn't require a map to do so.
  *     Return
  *             **XDP_REDIRECT** on success, or the value of the two lower bits
- *             of the **flags* argument on error.
+ *             of the *flags* argument on error.
  *
  * int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags)
  *     Description
index 0d8a6f47711c32eef4701ad9d9d6936f3a01d9c9..a10e3cdc283948980c5dfa0b3bc050eddc9cd2ec 100644 (file)
@@ -163,6 +163,7 @@ struct fscrypt_get_key_status_arg {
 #define FS_IOC_REMOVE_ENCRYPTION_KEY           _IOWR('f', 24, struct fscrypt_remove_key_arg)
 #define FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS _IOWR('f', 25, struct fscrypt_remove_key_arg)
 #define FS_IOC_GET_ENCRYPTION_KEY_STATUS       _IOWR('f', 26, struct fscrypt_get_key_status_arg)
+#define FS_IOC_GET_ENCRYPTION_NONCE            _IOR('f', 27, __u8[16])
 
 /**********************************************************************/
 
index 4b95f9a31a2f5e227f57f4cbba907c0508c5e3a9..428c7dde6b4b3761f9df65ed9181b50e1c9f7165 100644 (file)
@@ -474,12 +474,17 @@ struct kvm_s390_mem_op {
        __u32 size;             /* amount of bytes */
        __u32 op;               /* type of operation */
        __u64 buf;              /* buffer in userspace */
-       __u8 ar;                /* the access register number */
-       __u8 reserved[31];      /* should be set to 0 */
+       union {
+               __u8 ar;        /* the access register number */
+               __u32 sida_offset; /* offset into the sida */
+               __u8 reserved[32]; /* should be set to 0 */
+       };
 };
 /* types for kvm_s390_mem_op->op */
 #define KVM_S390_MEMOP_LOGICAL_READ    0
 #define KVM_S390_MEMOP_LOGICAL_WRITE   1
+#define KVM_S390_MEMOP_SIDA_READ       2
+#define KVM_S390_MEMOP_SIDA_WRITE      3
 /* flags for kvm_s390_mem_op->flags */
 #define KVM_S390_MEMOP_F_CHECK_ONLY            (1ULL << 0)
 #define KVM_S390_MEMOP_F_INJECT_EXCEPTION      (1ULL << 1)
@@ -1010,6 +1015,8 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_ARM_NISV_TO_USER 177
 #define KVM_CAP_ARM_INJECT_EXT_DABT 178
 #define KVM_CAP_S390_VCPU_RESETS 179
+#define KVM_CAP_S390_PROTECTED 180
+#define KVM_CAP_PPC_SECURE_GUEST 181
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1478,6 +1485,39 @@ struct kvm_enc_region {
 #define KVM_S390_NORMAL_RESET  _IO(KVMIO,   0xc3)
 #define KVM_S390_CLEAR_RESET   _IO(KVMIO,   0xc4)
 
+struct kvm_s390_pv_sec_parm {
+       __u64 origin;
+       __u64 length;
+};
+
+struct kvm_s390_pv_unp {
+       __u64 addr;
+       __u64 size;
+       __u64 tweak;
+};
+
+enum pv_cmd_id {
+       KVM_PV_ENABLE,
+       KVM_PV_DISABLE,
+       KVM_PV_SET_SEC_PARMS,
+       KVM_PV_UNPACK,
+       KVM_PV_VERIFY,
+       KVM_PV_PREP_RESET,
+       KVM_PV_UNSHARE_ALL,
+};
+
+struct kvm_pv_cmd {
+       __u32 cmd;      /* Command to be executed */
+       __u16 rc;       /* Ultravisor return code */
+       __u16 rrc;      /* Ultravisor return reason code */
+       __u64 data;     /* Data or address */
+       __u32 flags;    /* flags for future extensions. Must be 0 for now */
+       __u32 reserved[3];
+};
+
+/* Available with KVM_CAP_S390_PROTECTED */
+#define KVM_S390_PV_COMMAND            _IOWR(KVMIO, 0xc5, struct kvm_pv_cmd)
+
 /* Secure Encrypted Virtualization command */
 enum sev_cmd_id {
        /* Guest initialization commands */
@@ -1628,4 +1668,7 @@ struct kvm_hyperv_eventfd {
 #define KVM_HYPERV_CONN_ID_MASK                0x00ffffff
 #define KVM_HYPERV_EVENTFD_DEASSIGN    (1 << 0)
 
+#define KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE    (1 << 0)
+#define KVM_DIRTY_LOG_INITIALLY_SET            (1 << 1)
+
 #endif /* __LINUX_KVM_H */
index fc1a64c3447bf6e329bba5e155053332794a0187..923cc162609c016dd6360d834b34abfe6e1ba459 100644 (file)
@@ -5,8 +5,9 @@
 #include <asm/mman.h>
 #include <asm-generic/hugetlb_encode.h>
 
-#define MREMAP_MAYMOVE 1
-#define MREMAP_FIXED   2
+#define MREMAP_MAYMOVE         1
+#define MREMAP_FIXED           2
+#define MREMAP_DONTUNMAP       4
 
 #define OVERCOMMIT_GUESS               0
 #define OVERCOMMIT_ALWAYS              1
index 2e3bc22c6f202f6280ef7279de60fa966b84d3ed..3bac0a8ceab26ee78c37b425a76115aa21c20c06 100644 (file)
@@ -35,6 +35,7 @@
 
 /* Flags for the clone3() syscall. */
 #define CLONE_CLEAR_SIGHAND 0x100000000ULL /* Clear any signal handler and reset to SIG_DFL. */
+#define CLONE_INTO_CGROUP 0x200000000ULL /* Clone into a specific cgroup given the right permissions. */
 
 /*
  * cloning flags intersect with CSIGNAL so can be used with unshare and clone3
@@ -81,6 +82,8 @@
  * @set_tid_size: This defines the size of the array referenced
  *                in @set_tid. This cannot be larger than the
  *                kernel's limit of nested PID namespaces.
+ * @cgroup:       If CLONE_INTO_CGROUP is specified set this to
+ *                a file descriptor for the cgroup.
  *
  * The structure is versioned by size and thus extensible.
  * New struct members must go at the end of the struct and
@@ -97,11 +100,13 @@ struct clone_args {
        __aligned_u64 tls;
        __aligned_u64 set_tid;
        __aligned_u64 set_tid_size;
+       __aligned_u64 cgroup;
 };
 #endif
 
 #define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */
 #define CLONE_ARGS_SIZE_VER1 80 /* sizeof second published struct */
+#define CLONE_ARGS_SIZE_VER2 88 /* sizeof third published struct */
 
 /*
  * Scheduling policies
index 40d028eed645954cbc3e4699aa2c353be371ce7f..9fe72e4b1373165d7a7aeff6141082dd0e8269e6 100644 (file)
 #define VHOST_VSOCK_SET_GUEST_CID      _IOW(VHOST_VIRTIO, 0x60, __u64)
 #define VHOST_VSOCK_SET_RUNNING                _IOW(VHOST_VIRTIO, 0x61, int)
 
+/* VHOST_VDPA specific defines */
+
+/* Get the device id. The device ids follow the same definition of
+ * the device id defined in virtio-spec.
+ */
+#define VHOST_VDPA_GET_DEVICE_ID       _IOR(VHOST_VIRTIO, 0x70, __u32)
+/* Get and set the status. The status bits follow the same definition
+ * of the device status defined in virtio-spec.
+ */
+#define VHOST_VDPA_GET_STATUS          _IOR(VHOST_VIRTIO, 0x71, __u8)
+#define VHOST_VDPA_SET_STATUS          _IOW(VHOST_VIRTIO, 0x72, __u8)
+/* Get and set the device config. The device config follows the same
+ * definition of the device config defined in virtio-spec.
+ */
+#define VHOST_VDPA_GET_CONFIG          _IOR(VHOST_VIRTIO, 0x73, \
+                                            struct vhost_vdpa_config)
+#define VHOST_VDPA_SET_CONFIG          _IOW(VHOST_VIRTIO, 0x74, \
+                                            struct vhost_vdpa_config)
+/* Enable/disable the ring. */
+#define VHOST_VDPA_SET_VRING_ENABLE    _IOW(VHOST_VIRTIO, 0x75, \
+                                            struct vhost_vring_state)
+/* Get the max ring size. */
+#define VHOST_VDPA_GET_VRING_NUM       _IOR(VHOST_VIRTIO, 0x76, __u16)
+
 #endif
diff --git a/tools/include/vdso/bits.h b/tools/include/vdso/bits.h
new file mode 100644 (file)
index 0000000..6d005a1
--- /dev/null
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __VDSO_BITS_H
+#define __VDSO_BITS_H
+
+#include <vdso/const.h>
+
+#define BIT(nr)                        (UL(1) << (nr))
+
+#endif /* __VDSO_BITS_H */
diff --git a/tools/include/vdso/const.h b/tools/include/vdso/const.h
new file mode 100644 (file)
index 0000000..94b385a
--- /dev/null
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __VDSO_CONST_H
+#define __VDSO_CONST_H
+
+#include <uapi/linux/const.h>
+
+#define UL(x)          (_UL(x))
+#define ULL(x)         (_ULL(x))
+
+#endif /* __VDSO_CONST_H */
index ff9174282a8c6afdfeb79015a7ccbe0c7b33ac7b..8f480e29a6b07734edbb1f54f6fd7458d79b4220 100644 (file)
@@ -178,6 +178,8 @@ struct bpf_capabilities {
        __u32 array_mmap:1;
        /* BTF_FUNC_GLOBAL is supported */
        __u32 btf_func_global:1;
+       /* kernel support for expected_attach_type in BPF_PROG_LOAD */
+       __u32 exp_attach_type:1;
 };
 
 enum reloc_type {
@@ -194,6 +196,22 @@ struct reloc_desc {
        int sym_off;
 };
 
+struct bpf_sec_def;
+
+typedef struct bpf_link *(*attach_fn_t)(const struct bpf_sec_def *sec,
+                                       struct bpf_program *prog);
+
+struct bpf_sec_def {
+       const char *sec;
+       size_t len;
+       enum bpf_prog_type prog_type;
+       enum bpf_attach_type expected_attach_type;
+       bool is_exp_attach_type_optional;
+       bool is_attachable;
+       bool is_attach_btf;
+       attach_fn_t attach_fn;
+};
+
 /*
  * bpf_prog should be a better name but it has been used in
  * linux/filter.h.
@@ -204,6 +222,7 @@ struct bpf_program {
        char *name;
        int prog_ifindex;
        char *section_name;
+       const struct bpf_sec_def *sec_def;
        /* section_name with / replaced by _; makes recursive pinning
         * in bpf_object__pin_programs easier
         */
@@ -3315,6 +3334,37 @@ static int bpf_object__probe_array_mmap(struct bpf_object *obj)
        return 0;
 }
 
+static int
+bpf_object__probe_exp_attach_type(struct bpf_object *obj)
+{
+       struct bpf_load_program_attr attr;
+       struct bpf_insn insns[] = {
+               BPF_MOV64_IMM(BPF_REG_0, 0),
+               BPF_EXIT_INSN(),
+       };
+       int fd;
+
+       memset(&attr, 0, sizeof(attr));
+       /* use any valid combination of program type and (optional)
+        * non-zero expected attach type (i.e., not a BPF_CGROUP_INET_INGRESS)
+        * to see if kernel supports expected_attach_type field for
+        * BPF_PROG_LOAD command
+        */
+       attr.prog_type = BPF_PROG_TYPE_CGROUP_SOCK;
+       attr.expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE;
+       attr.insns = insns;
+       attr.insns_cnt = ARRAY_SIZE(insns);
+       attr.license = "GPL";
+
+       fd = bpf_load_program_xattr(&attr, NULL, 0);
+       if (fd >= 0) {
+               obj->caps.exp_attach_type = 1;
+               close(fd);
+               return 1;
+       }
+       return 0;
+}
+
 static int
 bpf_object__probe_caps(struct bpf_object *obj)
 {
@@ -3325,6 +3375,7 @@ bpf_object__probe_caps(struct bpf_object *obj)
                bpf_object__probe_btf_func_global,
                bpf_object__probe_btf_datasec,
                bpf_object__probe_array_mmap,
+               bpf_object__probe_exp_attach_type,
        };
        int i, ret;
 
@@ -4861,7 +4912,12 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
 
        memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
        load_attr.prog_type = prog->type;
-       load_attr.expected_attach_type = prog->expected_attach_type;
+       /* old kernels might not support specifying expected_attach_type */
+       if (!prog->caps->exp_attach_type && prog->sec_def &&
+           prog->sec_def->is_exp_attach_type_optional)
+               load_attr.expected_attach_type = 0;
+       else
+               load_attr.expected_attach_type = prog->expected_attach_type;
        if (prog->caps->name)
                load_attr.name = prog->name;
        load_attr.insns = insns;
@@ -5062,6 +5118,8 @@ bpf_object__load_progs(struct bpf_object *obj, int log_level)
        return 0;
 }
 
+static const struct bpf_sec_def *find_sec_def(const char *sec_name);
+
 static struct bpf_object *
 __bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz,
                   const struct bpf_object_open_opts *opts)
@@ -5117,24 +5175,17 @@ __bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz,
        bpf_object__elf_finish(obj);
 
        bpf_object__for_each_program(prog, obj) {
-               enum bpf_prog_type prog_type;
-               enum bpf_attach_type attach_type;
-
-               if (prog->type != BPF_PROG_TYPE_UNSPEC)
-                       continue;
-
-               err = libbpf_prog_type_by_name(prog->section_name, &prog_type,
-                                              &attach_type);
-               if (err == -ESRCH)
+               prog->sec_def = find_sec_def(prog->section_name);
+               if (!prog->sec_def)
                        /* couldn't guess, but user might manually specify */
                        continue;
-               if (err)
-                       goto out;
 
-               bpf_program__set_type(prog, prog_type);
-               bpf_program__set_expected_attach_type(prog, attach_type);
-               if (prog_type == BPF_PROG_TYPE_TRACING ||
-                   prog_type == BPF_PROG_TYPE_EXT)
+               bpf_program__set_type(prog, prog->sec_def->prog_type);
+               bpf_program__set_expected_attach_type(prog,
+                               prog->sec_def->expected_attach_type);
+
+               if (prog->sec_def->prog_type == BPF_PROG_TYPE_TRACING ||
+                   prog->sec_def->prog_type == BPF_PROG_TYPE_EXT)
                        prog->attach_prog_fd = OPTS_GET(opts, attach_prog_fd, 0);
        }
 
@@ -6223,23 +6274,32 @@ void bpf_program__set_expected_attach_type(struct bpf_program *prog,
        prog->expected_attach_type = type;
 }
 
-#define BPF_PROG_SEC_IMPL(string, ptype, eatype, is_attachable, btf, atype) \
-       { string, sizeof(string) - 1, ptype, eatype, is_attachable, btf, atype }
+#define BPF_PROG_SEC_IMPL(string, ptype, eatype, eatype_optional,          \
+                         attachable, attach_btf)                           \
+       {                                                                   \
+               .sec = string,                                              \
+               .len = sizeof(string) - 1,                                  \
+               .prog_type = ptype,                                         \
+               .expected_attach_type = eatype,                             \
+               .is_exp_attach_type_optional = eatype_optional,             \
+               .is_attachable = attachable,                                \
+               .is_attach_btf = attach_btf,                                \
+       }
 
 /* Programs that can NOT be attached. */
 #define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_IMPL(string, ptype, 0, 0, 0, 0)
 
 /* Programs that can be attached. */
 #define BPF_APROG_SEC(string, ptype, atype) \
-       BPF_PROG_SEC_IMPL(string, ptype, 0, 1, 0, atype)
+       BPF_PROG_SEC_IMPL(string, ptype, atype, true, 1, 0)
 
 /* Programs that must specify expected attach type at load time. */
 #define BPF_EAPROG_SEC(string, ptype, eatype) \
-       BPF_PROG_SEC_IMPL(string, ptype, eatype, 1, 0, eatype)
+       BPF_PROG_SEC_IMPL(string, ptype, eatype, false, 1, 0)
 
 /* Programs that use BTF to identify attach point */
 #define BPF_PROG_BTF(string, ptype, eatype) \
-       BPF_PROG_SEC_IMPL(string, ptype, eatype, 0, 1, 0)
+       BPF_PROG_SEC_IMPL(string, ptype, eatype, false, 0, 1)
 
 /* Programs that can be attached but attach type can't be identified by section
  * name. Kept for backward compatibility.
@@ -6253,11 +6313,6 @@ void bpf_program__set_expected_attach_type(struct bpf_program *prog,
        __VA_ARGS__                                                         \
 }
 
-struct bpf_sec_def;
-
-typedef struct bpf_link *(*attach_fn_t)(const struct bpf_sec_def *sec,
-                                       struct bpf_program *prog);
-
 static struct bpf_link *attach_kprobe(const struct bpf_sec_def *sec,
                                      struct bpf_program *prog);
 static struct bpf_link *attach_tp(const struct bpf_sec_def *sec,
@@ -6269,17 +6324,6 @@ static struct bpf_link *attach_trace(const struct bpf_sec_def *sec,
 static struct bpf_link *attach_lsm(const struct bpf_sec_def *sec,
                                   struct bpf_program *prog);
 
-struct bpf_sec_def {
-       const char *sec;
-       size_t len;
-       enum bpf_prog_type prog_type;
-       enum bpf_attach_type expected_attach_type;
-       bool is_attachable;
-       bool is_attach_btf;
-       enum bpf_attach_type attach_type;
-       attach_fn_t attach_fn;
-};
-
 static const struct bpf_sec_def section_defs[] = {
        BPF_PROG_SEC("socket",                  BPF_PROG_TYPE_SOCKET_FILTER),
        BPF_PROG_SEC("sk_reuseport",            BPF_PROG_TYPE_SK_REUSEPORT),
@@ -6713,7 +6757,7 @@ int libbpf_attach_type_by_name(const char *name,
                        continue;
                if (!section_defs[i].is_attachable)
                        return -EINVAL;
-               *attach_type = section_defs[i].attach_type;
+               *attach_type = section_defs[i].expected_attach_type;
                return 0;
        }
        pr_debug("failed to guess attach type based on ELF section name '%s'\n", name);
@@ -7542,7 +7586,6 @@ static struct bpf_link *attach_lsm(const struct bpf_sec_def *sec,
 struct bpf_link *
 bpf_program__attach_cgroup(struct bpf_program *prog, int cgroup_fd)
 {
-       const struct bpf_sec_def *sec_def;
        enum bpf_attach_type attach_type;
        char errmsg[STRERR_BUFSIZE];
        struct bpf_link *link;
@@ -7561,11 +7604,6 @@ bpf_program__attach_cgroup(struct bpf_program *prog, int cgroup_fd)
        link->detach = &bpf_link__detach_fd;
 
        attach_type = bpf_program__get_expected_attach_type(prog);
-       if (!attach_type) {
-               sec_def = find_sec_def(bpf_program__title(prog, false));
-               if (sec_def)
-                       attach_type = sec_def->attach_type;
-       }
        link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, NULL);
        if (link_fd < 0) {
                link_fd = -errno;
index 44df1d3e7287fbae5f84eb248ee9ca14e66e403c..f1dacecb1619fe02768f2ea94d2eed2b4e1367f6 100644 (file)
@@ -458,7 +458,7 @@ struct xdp_link_info {
 
 struct bpf_xdp_set_link_opts {
        size_t sz;
-       __u32 old_fd;
+       int old_fd;
 };
 #define bpf_xdp_set_link_opts__last_field old_fd
 
index 18b5319025e1986de84050d55b0e579d44173b48..312f887570b21441b526a2559cc9f61447200a6b 100644 (file)
@@ -142,7 +142,7 @@ static int __bpf_set_link_xdp_fd_replace(int ifindex, int fd, int old_fd,
                struct ifinfomsg ifinfo;
                char             attrbuf[64];
        } req;
-       __u32 nl_pid;
+       __u32 nl_pid = 0;
 
        sock = libbpf_netlink_open(&nl_pid);
        if (sock < 0)
@@ -288,7 +288,7 @@ int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
 {
        struct xdp_id_md xdp_id = {};
        int sock, ret;
-       __u32 nl_pid;
+       __u32 nl_pid = 0;
        __u32 mask;
 
        if (flags & ~XDP_FLAGS_MASK || !info_size)
@@ -321,7 +321,9 @@ int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
 
 static __u32 get_xdp_id(struct xdp_link_info *info, __u32 flags)
 {
-       if (info->attach_mode != XDP_ATTACHED_MULTI)
+       flags &= XDP_FLAGS_MODES;
+
+       if (info->attach_mode != XDP_ATTACHED_MULTI && !flags)
                return info->prog_id;
        if (flags & XDP_FLAGS_DRV_MODE)
                return info->drv_prog_id;
index 8dd01f986fbb5867ce4b24ebd0950eca401a01b5..3c6da70e6084144505fd7016b3568d2d951f615d 100644 (file)
@@ -72,6 +72,17 @@ static struct instruction *next_insn_same_func(struct objtool_file *file,
        return find_insn(file, func->cfunc->sec, func->cfunc->offset);
 }
 
+static struct instruction *prev_insn_same_sym(struct objtool_file *file,
+                                              struct instruction *insn)
+{
+       struct instruction *prev = list_prev_entry(insn, list);
+
+       if (&prev->list != &file->insn_list && prev->func == insn->func)
+               return prev;
+
+       return NULL;
+}
+
 #define func_for_each_insn(file, func, insn)                           \
        for (insn = find_insn(file, func->sec, func->offset);           \
             insn;                                                      \
@@ -1050,11 +1061,8 @@ static struct rela *find_jump_table(struct objtool_file *file,
         * it.
         */
        for (;
-            &insn->list != &file->insn_list &&
-            insn->sec == func->sec &&
-            insn->offset >= func->offset;
-
-            insn = insn->first_jump_src ?: list_prev_entry(insn, list)) {
+            insn && insn->func && insn->func->pfunc == func;
+            insn = insn->first_jump_src ?: prev_insn_same_sym(file, insn)) {
 
                if (insn != orig_insn && insn->type == INSN_JUMP_DYNAMIC)
                        break;
@@ -1452,7 +1460,7 @@ static int update_insn_state_regs(struct instruction *insn, struct insn_state *s
        struct cfi_reg *cfa = &state->cfa;
        struct stack_op *op = &insn->stack_op;
 
-       if (cfa->base != CFI_SP)
+       if (cfa->base != CFI_SP && cfa->base != CFI_SP_INDIRECT)
                return 0;
 
        /* push */
@@ -2008,8 +2016,8 @@ static int validate_return(struct symbol *func, struct instruction *insn, struct
        }
 
        if (state->bp_scratch) {
-               WARN("%s uses BP as a scratch register",
-                    func->name);
+               WARN_FUNC("BP used as a scratch register",
+                         insn->sec, insn->offset);
                return 1;
        }
 
@@ -2364,14 +2372,27 @@ static bool ignore_unreachable_insn(struct instruction *insn)
            !strcmp(insn->sec->name, ".altinstr_aux"))
                return true;
 
+       if (!insn->func)
+               return false;
+
+       /*
+        * CONFIG_UBSAN_TRAP inserts a UD2 when it sees
+        * __builtin_unreachable().  The BUG() macro has an unreachable() after
+        * the UD2, which causes GCC's undefined trap logic to emit another UD2
+        * (or occasionally a JMP to UD2).
+        */
+       if (list_prev_entry(insn, list)->dead_end &&
+           (insn->type == INSN_BUG ||
+            (insn->type == INSN_JUMP_UNCONDITIONAL &&
+             insn->jump_dest && insn->jump_dest->type == INSN_BUG)))
+               return true;
+
        /*
         * Check if this (or a subsequent) instruction is related to
         * CONFIG_UBSAN or CONFIG_KASAN.
         *
         * End the search at 5 instructions to avoid going into the weeds.
         */
-       if (!insn->func)
-               return false;
        for (i = 0; i < 5; i++) {
 
                if (is_kasan_insn(insn) || is_ubsan_insn(insn))
index 09ddc8f1def3cf328d3b5531391b4fc00a43804a..c4857fa3f1d18537c2bcbbc37c6f40b966ffd7e1 100644 (file)
@@ -105,7 +105,7 @@ static int symbol_by_offset(const void *key, const struct rb_node *node)
 
        if (*o < s->offset)
                return -1;
-       if (*o > s->offset + s->len)
+       if (*o >= s->offset + s->len)
                return 1;
 
        return 0;
index ebbb10c61e246743e3b2be05f4b9098e02013600..12e01ac190ec1179b81216edc5e72df9c9c17edc 100644 (file)
@@ -87,9 +87,10 @@ struct elf {
 #define OFFSET_STRIDE          (1UL << OFFSET_STRIDE_BITS)
 #define OFFSET_STRIDE_MASK     (~(OFFSET_STRIDE - 1))
 
-#define for_offset_range(_offset, _start, _end)                \
-       for (_offset = ((_start) & OFFSET_STRIDE_MASK); \
-            _offset <= ((_end) & OFFSET_STRIDE_MASK);  \
+#define for_offset_range(_offset, _start, _end)                        \
+       for (_offset = ((_start) & OFFSET_STRIDE_MASK);         \
+            _offset >= ((_start) & OFFSET_STRIDE_MASK) &&      \
+            _offset <= ((_end) & OFFSET_STRIDE_MASK);          \
             _offset += OFFSET_STRIDE)
 
 static inline u32 sec_offset_hash(struct section *sec, unsigned long offset)
@@ -99,7 +100,7 @@ static inline u32 sec_offset_hash(struct section *sec, unsigned long offset)
        offset &= OFFSET_STRIDE_MASK;
 
        ol = offset;
-       oh = offset >> 32;
+       oh = (offset >> 16) >> 16;
 
        __jhash_mix(ol, oh, idx);
 
index 13ccf775a83a462e66da0f15dae47471262419ba..ba4cbb1cdd632413aa7b4ca3603b6c2543674908 100644 (file)
@@ -66,7 +66,7 @@ int orc_dump(const char *_objname)
        char *name;
        size_t nr_sections;
        Elf64_Addr orc_ip_addr = 0;
-       size_t shstrtab_idx;
+       size_t shstrtab_idx, strtab_idx = 0;
        Elf *elf;
        Elf_Scn *scn;
        GElf_Shdr sh;
@@ -127,6 +127,8 @@ int orc_dump(const char *_objname)
 
                if (!strcmp(name, ".symtab")) {
                        symtab = data;
+               } else if (!strcmp(name, ".strtab")) {
+                       strtab_idx = i;
                } else if (!strcmp(name, ".orc_unwind")) {
                        orc = data->d_buf;
                        orc_size = sh.sh_size;
@@ -138,7 +140,7 @@ int orc_dump(const char *_objname)
                }
        }
 
-       if (!symtab || !orc || !orc_ip)
+       if (!symtab || !strtab_idx || !orc || !orc_ip)
                return 0;
 
        if (orc_size % sizeof(*orc) != 0) {
@@ -159,21 +161,29 @@ int orc_dump(const char *_objname)
                                return -1;
                        }
 
-                       scn = elf_getscn(elf, sym.st_shndx);
-                       if (!scn) {
-                               WARN_ELF("elf_getscn");
-                               return -1;
-                       }
-
-                       if (!gelf_getshdr(scn, &sh)) {
-                               WARN_ELF("gelf_getshdr");
-                               return -1;
-                       }
-
-                       name = elf_strptr(elf, shstrtab_idx, sh.sh_name);
-                       if (!name || !*name) {
-                               WARN_ELF("elf_strptr");
-                               return -1;
+                       if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) {
+                               scn = elf_getscn(elf, sym.st_shndx);
+                               if (!scn) {
+                                       WARN_ELF("elf_getscn");
+                                       return -1;
+                               }
+
+                               if (!gelf_getshdr(scn, &sh)) {
+                                       WARN_ELF("gelf_getshdr");
+                                       return -1;
+                               }
+
+                               name = elf_strptr(elf, shstrtab_idx, sh.sh_name);
+                               if (!name) {
+                                       WARN_ELF("elf_strptr");
+                                       return -1;
+                               }
+                       } else {
+                               name = elf_strptr(elf, strtab_idx, sym.st_name);
+                               if (!name) {
+                                       WARN_ELF("elf_strptr");
+                                       return -1;
+                               }
                        }
 
                        printf("%s+%llx:", name, (unsigned long long)rela.r_addend);
index 41e4a2754da4a2e2a96992f4df5e0c3a755c9562..4c0dabd280002771f8d28675088d230ed9b70e60 100644 (file)
@@ -88,11 +88,6 @@ static int create_orc_entry(struct elf *elf, struct section *u_sec, struct secti
        struct orc_entry *orc;
        struct rela *rela;
 
-       if (!insn_sec->sym) {
-               WARN("missing symbol for section %s", insn_sec->name);
-               return -1;
-       }
-
        /* populate ORC data */
        orc = (struct orc_entry *)u_sec->data->d_buf + idx;
        memcpy(orc, o, sizeof(*orc));
@@ -105,8 +100,32 @@ static int create_orc_entry(struct elf *elf, struct section *u_sec, struct secti
        }
        memset(rela, 0, sizeof(*rela));
 
-       rela->sym = insn_sec->sym;
-       rela->addend = insn_off;
+       if (insn_sec->sym) {
+               rela->sym = insn_sec->sym;
+               rela->addend = insn_off;
+       } else {
+               /*
+                * The Clang assembler doesn't produce section symbols, so we
+                * have to reference the function symbol instead:
+                */
+               rela->sym = find_symbol_containing(insn_sec, insn_off);
+               if (!rela->sym) {
+                       /*
+                        * Hack alert.  This happens when we need to reference
+                        * the NOP pad insn immediately after the function.
+                        */
+                       rela->sym = find_symbol_containing(insn_sec,
+                                                          insn_off - 1);
+               }
+               if (!rela->sym) {
+                       WARN("missing symbol for insn at offset 0x%lx\n",
+                            insn_off);
+                       return -1;
+               }
+
+               rela->addend = insn_off - rela->sym->offset;
+       }
+
        rela->type = R_X86_64_PC32;
        rela->offset = idx * sizeof(int);
        rela->sec = ip_relasec;
index 44d510bc9b7877a18c082ceb168f01e94db0417b..37b844f839bc4f4b07f292a26ee5d5987ccdcd1c 100644 (file)
 #
 # The abi is "common", "64" or "x32" for this file.
 #
-0      common  read                    __x64_sys_read
-1      common  write                   __x64_sys_write
-2      common  open                    __x64_sys_open
-3      common  close                   __x64_sys_close
-4      common  stat                    __x64_sys_newstat
-5      common  fstat                   __x64_sys_newfstat
-6      common  lstat                   __x64_sys_newlstat
-7      common  poll                    __x64_sys_poll
-8      common  lseek                   __x64_sys_lseek
-9      common  mmap                    __x64_sys_mmap
-10     common  mprotect                __x64_sys_mprotect
-11     common  munmap                  __x64_sys_munmap
-12     common  brk                     __x64_sys_brk
-13     64      rt_sigaction            __x64_sys_rt_sigaction
-14     common  rt_sigprocmask          __x64_sys_rt_sigprocmask
-15     64      rt_sigreturn            __x64_sys_rt_sigreturn/ptregs
-16     64      ioctl                   __x64_sys_ioctl
-17     common  pread64                 __x64_sys_pread64
-18     common  pwrite64                __x64_sys_pwrite64
-19     64      readv                   __x64_sys_readv
-20     64      writev                  __x64_sys_writev
-21     common  access                  __x64_sys_access
-22     common  pipe                    __x64_sys_pipe
-23     common  select                  __x64_sys_select
-24     common  sched_yield             __x64_sys_sched_yield
-25     common  mremap                  __x64_sys_mremap
-26     common  msync                   __x64_sys_msync
-27     common  mincore                 __x64_sys_mincore
-28     common  madvise                 __x64_sys_madvise
-29     common  shmget                  __x64_sys_shmget
-30     common  shmat                   __x64_sys_shmat
-31     common  shmctl                  __x64_sys_shmctl
-32     common  dup                     __x64_sys_dup
-33     common  dup2                    __x64_sys_dup2
-34     common  pause                   __x64_sys_pause
-35     common  nanosleep               __x64_sys_nanosleep
-36     common  getitimer               __x64_sys_getitimer
-37     common  alarm                   __x64_sys_alarm
-38     common  setitimer               __x64_sys_setitimer
-39     common  getpid                  __x64_sys_getpid
-40     common  sendfile                __x64_sys_sendfile64
-41     common  socket                  __x64_sys_socket
-42     common  connect                 __x64_sys_connect
-43     common  accept                  __x64_sys_accept
-44     common  sendto                  __x64_sys_sendto
-45     64      recvfrom                __x64_sys_recvfrom
-46     64      sendmsg                 __x64_sys_sendmsg
-47     64      recvmsg                 __x64_sys_recvmsg
-48     common  shutdown                __x64_sys_shutdown
-49     common  bind                    __x64_sys_bind
-50     common  listen                  __x64_sys_listen
-51     common  getsockname             __x64_sys_getsockname
-52     common  getpeername             __x64_sys_getpeername
-53     common  socketpair              __x64_sys_socketpair
-54     64      setsockopt              __x64_sys_setsockopt
-55     64      getsockopt              __x64_sys_getsockopt
-56     common  clone                   __x64_sys_clone/ptregs
-57     common  fork                    __x64_sys_fork/ptregs
-58     common  vfork                   __x64_sys_vfork/ptregs
-59     64      execve                  __x64_sys_execve/ptregs
-60     common  exit                    __x64_sys_exit
-61     common  wait4                   __x64_sys_wait4
-62     common  kill                    __x64_sys_kill
-63     common  uname                   __x64_sys_newuname
-64     common  semget                  __x64_sys_semget
-65     common  semop                   __x64_sys_semop
-66     common  semctl                  __x64_sys_semctl
-67     common  shmdt                   __x64_sys_shmdt
-68     common  msgget                  __x64_sys_msgget
-69     common  msgsnd                  __x64_sys_msgsnd
-70     common  msgrcv                  __x64_sys_msgrcv
-71     common  msgctl                  __x64_sys_msgctl
-72     common  fcntl                   __x64_sys_fcntl
-73     common  flock                   __x64_sys_flock
-74     common  fsync                   __x64_sys_fsync
-75     common  fdatasync               __x64_sys_fdatasync
-76     common  truncate                __x64_sys_truncate
-77     common  ftruncate               __x64_sys_ftruncate
-78     common  getdents                __x64_sys_getdents
-79     common  getcwd                  __x64_sys_getcwd
-80     common  chdir                   __x64_sys_chdir
-81     common  fchdir                  __x64_sys_fchdir
-82     common  rename                  __x64_sys_rename
-83     common  mkdir                   __x64_sys_mkdir
-84     common  rmdir                   __x64_sys_rmdir
-85     common  creat                   __x64_sys_creat
-86     common  link                    __x64_sys_link
-87     common  unlink                  __x64_sys_unlink
-88     common  symlink                 __x64_sys_symlink
-89     common  readlink                __x64_sys_readlink
-90     common  chmod                   __x64_sys_chmod
-91     common  fchmod                  __x64_sys_fchmod
-92     common  chown                   __x64_sys_chown
-93     common  fchown                  __x64_sys_fchown
-94     common  lchown                  __x64_sys_lchown
-95     common  umask                   __x64_sys_umask
-96     common  gettimeofday            __x64_sys_gettimeofday
-97     common  getrlimit               __x64_sys_getrlimit
-98     common  getrusage               __x64_sys_getrusage
-99     common  sysinfo                 __x64_sys_sysinfo
-100    common  times                   __x64_sys_times
-101    64      ptrace                  __x64_sys_ptrace
-102    common  getuid                  __x64_sys_getuid
-103    common  syslog                  __x64_sys_syslog
-104    common  getgid                  __x64_sys_getgid
-105    common  setuid                  __x64_sys_setuid
-106    common  setgid                  __x64_sys_setgid
-107    common  geteuid                 __x64_sys_geteuid
-108    common  getegid                 __x64_sys_getegid
-109    common  setpgid                 __x64_sys_setpgid
-110    common  getppid                 __x64_sys_getppid
-111    common  getpgrp                 __x64_sys_getpgrp
-112    common  setsid                  __x64_sys_setsid
-113    common  setreuid                __x64_sys_setreuid
-114    common  setregid                __x64_sys_setregid
-115    common  getgroups               __x64_sys_getgroups
-116    common  setgroups               __x64_sys_setgroups
-117    common  setresuid               __x64_sys_setresuid
-118    common  getresuid               __x64_sys_getresuid
-119    common  setresgid               __x64_sys_setresgid
-120    common  getresgid               __x64_sys_getresgid
-121    common  getpgid                 __x64_sys_getpgid
-122    common  setfsuid                __x64_sys_setfsuid
-123    common  setfsgid                __x64_sys_setfsgid
-124    common  getsid                  __x64_sys_getsid
-125    common  capget                  __x64_sys_capget
-126    common  capset                  __x64_sys_capset
-127    64      rt_sigpending           __x64_sys_rt_sigpending
-128    64      rt_sigtimedwait         __x64_sys_rt_sigtimedwait
-129    64      rt_sigqueueinfo         __x64_sys_rt_sigqueueinfo
-130    common  rt_sigsuspend           __x64_sys_rt_sigsuspend
-131    64      sigaltstack             __x64_sys_sigaltstack
-132    common  utime                   __x64_sys_utime
-133    common  mknod                   __x64_sys_mknod
+0      common  read                    sys_read
+1      common  write                   sys_write
+2      common  open                    sys_open
+3      common  close                   sys_close
+4      common  stat                    sys_newstat
+5      common  fstat                   sys_newfstat
+6      common  lstat                   sys_newlstat
+7      common  poll                    sys_poll
+8      common  lseek                   sys_lseek
+9      common  mmap                    sys_mmap
+10     common  mprotect                sys_mprotect
+11     common  munmap                  sys_munmap
+12     common  brk                     sys_brk
+13     64      rt_sigaction            sys_rt_sigaction
+14     common  rt_sigprocmask          sys_rt_sigprocmask
+15     64      rt_sigreturn            sys_rt_sigreturn
+16     64      ioctl                   sys_ioctl
+17     common  pread64                 sys_pread64
+18     common  pwrite64                sys_pwrite64
+19     64      readv                   sys_readv
+20     64      writev                  sys_writev
+21     common  access                  sys_access
+22     common  pipe                    sys_pipe
+23     common  select                  sys_select
+24     common  sched_yield             sys_sched_yield
+25     common  mremap                  sys_mremap
+26     common  msync                   sys_msync
+27     common  mincore                 sys_mincore
+28     common  madvise                 sys_madvise
+29     common  shmget                  sys_shmget
+30     common  shmat                   sys_shmat
+31     common  shmctl                  sys_shmctl
+32     common  dup                     sys_dup
+33     common  dup2                    sys_dup2
+34     common  pause                   sys_pause
+35     common  nanosleep               sys_nanosleep
+36     common  getitimer               sys_getitimer
+37     common  alarm                   sys_alarm
+38     common  setitimer               sys_setitimer
+39     common  getpid                  sys_getpid
+40     common  sendfile                sys_sendfile64
+41     common  socket                  sys_socket
+42     common  connect                 sys_connect
+43     common  accept                  sys_accept
+44     common  sendto                  sys_sendto
+45     64      recvfrom                sys_recvfrom
+46     64      sendmsg                 sys_sendmsg
+47     64      recvmsg                 sys_recvmsg
+48     common  shutdown                sys_shutdown
+49     common  bind                    sys_bind
+50     common  listen                  sys_listen
+51     common  getsockname             sys_getsockname
+52     common  getpeername             sys_getpeername
+53     common  socketpair              sys_socketpair
+54     64      setsockopt              sys_setsockopt
+55     64      getsockopt              sys_getsockopt
+56     common  clone                   sys_clone
+57     common  fork                    sys_fork
+58     common  vfork                   sys_vfork
+59     64      execve                  sys_execve
+60     common  exit                    sys_exit
+61     common  wait4                   sys_wait4
+62     common  kill                    sys_kill
+63     common  uname                   sys_newuname
+64     common  semget                  sys_semget
+65     common  semop                   sys_semop
+66     common  semctl                  sys_semctl
+67     common  shmdt                   sys_shmdt
+68     common  msgget                  sys_msgget
+69     common  msgsnd                  sys_msgsnd
+70     common  msgrcv                  sys_msgrcv
+71     common  msgctl                  sys_msgctl
+72     common  fcntl                   sys_fcntl
+73     common  flock                   sys_flock
+74     common  fsync                   sys_fsync
+75     common  fdatasync               sys_fdatasync
+76     common  truncate                sys_truncate
+77     common  ftruncate               sys_ftruncate
+78     common  getdents                sys_getdents
+79     common  getcwd                  sys_getcwd
+80     common  chdir                   sys_chdir
+81     common  fchdir                  sys_fchdir
+82     common  rename                  sys_rename
+83     common  mkdir                   sys_mkdir
+84     common  rmdir                   sys_rmdir
+85     common  creat                   sys_creat
+86     common  link                    sys_link
+87     common  unlink                  sys_unlink
+88     common  symlink                 sys_symlink
+89     common  readlink                sys_readlink
+90     common  chmod                   sys_chmod
+91     common  fchmod                  sys_fchmod
+92     common  chown                   sys_chown
+93     common  fchown                  sys_fchown
+94     common  lchown                  sys_lchown
+95     common  umask                   sys_umask
+96     common  gettimeofday            sys_gettimeofday
+97     common  getrlimit               sys_getrlimit
+98     common  getrusage               sys_getrusage
+99     common  sysinfo                 sys_sysinfo
+100    common  times                   sys_times
+101    64      ptrace                  sys_ptrace
+102    common  getuid                  sys_getuid
+103    common  syslog                  sys_syslog
+104    common  getgid                  sys_getgid
+105    common  setuid                  sys_setuid
+106    common  setgid                  sys_setgid
+107    common  geteuid                 sys_geteuid
+108    common  getegid                 sys_getegid
+109    common  setpgid                 sys_setpgid
+110    common  getppid                 sys_getppid
+111    common  getpgrp                 sys_getpgrp
+112    common  setsid                  sys_setsid
+113    common  setreuid                sys_setreuid
+114    common  setregid                sys_setregid
+115    common  getgroups               sys_getgroups
+116    common  setgroups               sys_setgroups
+117    common  setresuid               sys_setresuid
+118    common  getresuid               sys_getresuid
+119    common  setresgid               sys_setresgid
+120    common  getresgid               sys_getresgid
+121    common  getpgid                 sys_getpgid
+122    common  setfsuid                sys_setfsuid
+123    common  setfsgid                sys_setfsgid
+124    common  getsid                  sys_getsid
+125    common  capget                  sys_capget
+126    common  capset                  sys_capset
+127    64      rt_sigpending           sys_rt_sigpending
+128    64      rt_sigtimedwait         sys_rt_sigtimedwait
+129    64      rt_sigqueueinfo         sys_rt_sigqueueinfo
+130    common  rt_sigsuspend           sys_rt_sigsuspend
+131    64      sigaltstack             sys_sigaltstack
+132    common  utime                   sys_utime
+133    common  mknod                   sys_mknod
 134    64      uselib
-135    common  personality             __x64_sys_personality
-136    common  ustat                   __x64_sys_ustat
-137    common  statfs                  __x64_sys_statfs
-138    common  fstatfs                 __x64_sys_fstatfs
-139    common  sysfs                   __x64_sys_sysfs
-140    common  getpriority             __x64_sys_getpriority
-141    common  setpriority             __x64_sys_setpriority
-142    common  sched_setparam          __x64_sys_sched_setparam
-143    common  sched_getparam          __x64_sys_sched_getparam
-144    common  sched_setscheduler      __x64_sys_sched_setscheduler
-145    common  sched_getscheduler      __x64_sys_sched_getscheduler
-146    common  sched_get_priority_max  __x64_sys_sched_get_priority_max
-147    common  sched_get_priority_min  __x64_sys_sched_get_priority_min
-148    common  sched_rr_get_interval   __x64_sys_sched_rr_get_interval
-149    common  mlock                   __x64_sys_mlock
-150    common  munlock                 __x64_sys_munlock
-151    common  mlockall                __x64_sys_mlockall
-152    common  munlockall              __x64_sys_munlockall
-153    common  vhangup                 __x64_sys_vhangup
-154    common  modify_ldt              __x64_sys_modify_ldt
-155    common  pivot_root              __x64_sys_pivot_root
-156    64      _sysctl                 __x64_sys_sysctl
-157    common  prctl                   __x64_sys_prctl
-158    common  arch_prctl              __x64_sys_arch_prctl
-159    common  adjtimex                __x64_sys_adjtimex
-160    common  setrlimit               __x64_sys_setrlimit
-161    common  chroot                  __x64_sys_chroot
-162    common  sync                    __x64_sys_sync
-163    common  acct                    __x64_sys_acct
-164    common  settimeofday            __x64_sys_settimeofday
-165    common  mount                   __x64_sys_mount
-166    common  umount2                 __x64_sys_umount
-167    common  swapon                  __x64_sys_swapon
-168    common  swapoff                 __x64_sys_swapoff
-169    common  reboot                  __x64_sys_reboot
-170    common  sethostname             __x64_sys_sethostname
-171    common  setdomainname           __x64_sys_setdomainname
-172    common  iopl                    __x64_sys_iopl/ptregs
-173    common  ioperm                  __x64_sys_ioperm
+135    common  personality             sys_personality
+136    common  ustat                   sys_ustat
+137    common  statfs                  sys_statfs
+138    common  fstatfs                 sys_fstatfs
+139    common  sysfs                   sys_sysfs
+140    common  getpriority             sys_getpriority
+141    common  setpriority             sys_setpriority
+142    common  sched_setparam          sys_sched_setparam
+143    common  sched_getparam          sys_sched_getparam
+144    common  sched_setscheduler      sys_sched_setscheduler
+145    common  sched_getscheduler      sys_sched_getscheduler
+146    common  sched_get_priority_max  sys_sched_get_priority_max
+147    common  sched_get_priority_min  sys_sched_get_priority_min
+148    common  sched_rr_get_interval   sys_sched_rr_get_interval
+149    common  mlock                   sys_mlock
+150    common  munlock                 sys_munlock
+151    common  mlockall                sys_mlockall
+152    common  munlockall              sys_munlockall
+153    common  vhangup                 sys_vhangup
+154    common  modify_ldt              sys_modify_ldt
+155    common  pivot_root              sys_pivot_root
+156    64      _sysctl                 sys_sysctl
+157    common  prctl                   sys_prctl
+158    common  arch_prctl              sys_arch_prctl
+159    common  adjtimex                sys_adjtimex
+160    common  setrlimit               sys_setrlimit
+161    common  chroot                  sys_chroot
+162    common  sync                    sys_sync
+163    common  acct                    sys_acct
+164    common  settimeofday            sys_settimeofday
+165    common  mount                   sys_mount
+166    common  umount2                 sys_umount
+167    common  swapon                  sys_swapon
+168    common  swapoff                 sys_swapoff
+169    common  reboot                  sys_reboot
+170    common  sethostname             sys_sethostname
+171    common  setdomainname           sys_setdomainname
+172    common  iopl                    sys_iopl
+173    common  ioperm                  sys_ioperm
 174    64      create_module
-175    common  init_module             __x64_sys_init_module
-176    common  delete_module           __x64_sys_delete_module
+175    common  init_module             sys_init_module
+176    common  delete_module           sys_delete_module
 177    64      get_kernel_syms
 178    64      query_module
-179    common  quotactl                __x64_sys_quotactl
+179    common  quotactl                sys_quotactl
 180    64      nfsservctl
 181    common  getpmsg
 182    common  putpmsg
 183    common  afs_syscall
 184    common  tuxcall
 185    common  security
-186    common  gettid                  __x64_sys_gettid
-187    common  readahead               __x64_sys_readahead
-188    common  setxattr                __x64_sys_setxattr
-189    common  lsetxattr               __x64_sys_lsetxattr
-190    common  fsetxattr               __x64_sys_fsetxattr
-191    common  getxattr                __x64_sys_getxattr
-192    common  lgetxattr               __x64_sys_lgetxattr
-193    common  fgetxattr               __x64_sys_fgetxattr
-194    common  listxattr               __x64_sys_listxattr
-195    common  llistxattr              __x64_sys_llistxattr
-196    common  flistxattr              __x64_sys_flistxattr
-197    common  removexattr             __x64_sys_removexattr
-198    common  lremovexattr            __x64_sys_lremovexattr
-199    common  fremovexattr            __x64_sys_fremovexattr
-200    common  tkill                   __x64_sys_tkill
-201    common  time                    __x64_sys_time
-202    common  futex                   __x64_sys_futex
-203    common  sched_setaffinity       __x64_sys_sched_setaffinity
-204    common  sched_getaffinity       __x64_sys_sched_getaffinity
+186    common  gettid                  sys_gettid
+187    common  readahead               sys_readahead
+188    common  setxattr                sys_setxattr
+189    common  lsetxattr               sys_lsetxattr
+190    common  fsetxattr               sys_fsetxattr
+191    common  getxattr                sys_getxattr
+192    common  lgetxattr               sys_lgetxattr
+193    common  fgetxattr               sys_fgetxattr
+194    common  listxattr               sys_listxattr
+195    common  llistxattr              sys_llistxattr
+196    common  flistxattr              sys_flistxattr
+197    common  removexattr             sys_removexattr
+198    common  lremovexattr            sys_lremovexattr
+199    common  fremovexattr            sys_fremovexattr
+200    common  tkill                   sys_tkill
+201    common  time                    sys_time
+202    common  futex                   sys_futex
+203    common  sched_setaffinity       sys_sched_setaffinity
+204    common  sched_getaffinity       sys_sched_getaffinity
 205    64      set_thread_area
-206    64      io_setup                __x64_sys_io_setup
-207    common  io_destroy              __x64_sys_io_destroy
-208    common  io_getevents            __x64_sys_io_getevents
-209    64      io_submit               __x64_sys_io_submit
-210    common  io_cancel               __x64_sys_io_cancel
+206    64      io_setup                sys_io_setup
+207    common  io_destroy              sys_io_destroy
+208    common  io_getevents            sys_io_getevents
+209    64      io_submit               sys_io_submit
+210    common  io_cancel               sys_io_cancel
 211    64      get_thread_area
-212    common  lookup_dcookie          __x64_sys_lookup_dcookie
-213    common  epoll_create            __x64_sys_epoll_create
+212    common  lookup_dcookie          sys_lookup_dcookie
+213    common  epoll_create            sys_epoll_create
 214    64      epoll_ctl_old
 215    64      epoll_wait_old
-216    common  remap_file_pages        __x64_sys_remap_file_pages
-217    common  getdents64              __x64_sys_getdents64
-218    common  set_tid_address         __x64_sys_set_tid_address
-219    common  restart_syscall         __x64_sys_restart_syscall
-220    common  semtimedop              __x64_sys_semtimedop
-221    common  fadvise64               __x64_sys_fadvise64
-222    64      timer_create            __x64_sys_timer_create
-223    common  timer_settime           __x64_sys_timer_settime
-224    common  timer_gettime           __x64_sys_timer_gettime
-225    common  timer_getoverrun        __x64_sys_timer_getoverrun
-226    common  timer_delete            __x64_sys_timer_delete
-227    common  clock_settime           __x64_sys_clock_settime
-228    common  clock_gettime           __x64_sys_clock_gettime
-229    common  clock_getres            __x64_sys_clock_getres
-230    common  clock_nanosleep         __x64_sys_clock_nanosleep
-231    common  exit_group              __x64_sys_exit_group
-232    common  epoll_wait              __x64_sys_epoll_wait
-233    common  epoll_ctl               __x64_sys_epoll_ctl
-234    common  tgkill                  __x64_sys_tgkill
-235    common  utimes                  __x64_sys_utimes
+216    common  remap_file_pages        sys_remap_file_pages
+217    common  getdents64              sys_getdents64
+218    common  set_tid_address         sys_set_tid_address
+219    common  restart_syscall         sys_restart_syscall
+220    common  semtimedop              sys_semtimedop
+221    common  fadvise64               sys_fadvise64
+222    64      timer_create            sys_timer_create
+223    common  timer_settime           sys_timer_settime
+224    common  timer_gettime           sys_timer_gettime
+225    common  timer_getoverrun        sys_timer_getoverrun
+226    common  timer_delete            sys_timer_delete
+227    common  clock_settime           sys_clock_settime
+228    common  clock_gettime           sys_clock_gettime
+229    common  clock_getres            sys_clock_getres
+230    common  clock_nanosleep         sys_clock_nanosleep
+231    common  exit_group              sys_exit_group
+232    common  epoll_wait              sys_epoll_wait
+233    common  epoll_ctl               sys_epoll_ctl
+234    common  tgkill                  sys_tgkill
+235    common  utimes                  sys_utimes
 236    64      vserver
-237    common  mbind                   __x64_sys_mbind
-238    common  set_mempolicy           __x64_sys_set_mempolicy
-239    common  get_mempolicy           __x64_sys_get_mempolicy
-240    common  mq_open                 __x64_sys_mq_open
-241    common  mq_unlink               __x64_sys_mq_unlink
-242    common  mq_timedsend            __x64_sys_mq_timedsend
-243    common  mq_timedreceive         __x64_sys_mq_timedreceive
-244    64      mq_notify               __x64_sys_mq_notify
-245    common  mq_getsetattr           __x64_sys_mq_getsetattr
-246    64      kexec_load              __x64_sys_kexec_load
-247    64      waitid                  __x64_sys_waitid
-248    common  add_key                 __x64_sys_add_key
-249    common  request_key             __x64_sys_request_key
-250    common  keyctl                  __x64_sys_keyctl
-251    common  ioprio_set              __x64_sys_ioprio_set
-252    common  ioprio_get              __x64_sys_ioprio_get
-253    common  inotify_init            __x64_sys_inotify_init
-254    common  inotify_add_watch       __x64_sys_inotify_add_watch
-255    common  inotify_rm_watch        __x64_sys_inotify_rm_watch
-256    common  migrate_pages           __x64_sys_migrate_pages
-257    common  openat                  __x64_sys_openat
-258    common  mkdirat                 __x64_sys_mkdirat
-259    common  mknodat                 __x64_sys_mknodat
-260    common  fchownat                __x64_sys_fchownat
-261    common  futimesat               __x64_sys_futimesat
-262    common  newfstatat              __x64_sys_newfstatat
-263    common  unlinkat                __x64_sys_unlinkat
-264    common  renameat                __x64_sys_renameat
-265    common  linkat                  __x64_sys_linkat
-266    common  symlinkat               __x64_sys_symlinkat
-267    common  readlinkat              __x64_sys_readlinkat
-268    common  fchmodat                __x64_sys_fchmodat
-269    common  faccessat               __x64_sys_faccessat
-270    common  pselect6                __x64_sys_pselect6
-271    common  ppoll                   __x64_sys_ppoll
-272    common  unshare                 __x64_sys_unshare
-273    64      set_robust_list         __x64_sys_set_robust_list
-274    64      get_robust_list         __x64_sys_get_robust_list
-275    common  splice                  __x64_sys_splice
-276    common  tee                     __x64_sys_tee
-277    common  sync_file_range         __x64_sys_sync_file_range
-278    64      vmsplice                __x64_sys_vmsplice
-279    64      move_pages              __x64_sys_move_pages
-280    common  utimensat               __x64_sys_utimensat
-281    common  epoll_pwait             __x64_sys_epoll_pwait
-282    common  signalfd                __x64_sys_signalfd
-283    common  timerfd_create          __x64_sys_timerfd_create
-284    common  eventfd                 __x64_sys_eventfd
-285    common  fallocate               __x64_sys_fallocate
-286    common  timerfd_settime         __x64_sys_timerfd_settime
-287    common  timerfd_gettime         __x64_sys_timerfd_gettime
-288    common  accept4                 __x64_sys_accept4
-289    common  signalfd4               __x64_sys_signalfd4
-290    common  eventfd2                __x64_sys_eventfd2
-291    common  epoll_create1           __x64_sys_epoll_create1
-292    common  dup3                    __x64_sys_dup3
-293    common  pipe2                   __x64_sys_pipe2
-294    common  inotify_init1           __x64_sys_inotify_init1
-295    64      preadv                  __x64_sys_preadv
-296    64      pwritev                 __x64_sys_pwritev
-297    64      rt_tgsigqueueinfo       __x64_sys_rt_tgsigqueueinfo
-298    common  perf_event_open         __x64_sys_perf_event_open
-299    64      recvmmsg                __x64_sys_recvmmsg
-300    common  fanotify_init           __x64_sys_fanotify_init
-301    common  fanotify_mark           __x64_sys_fanotify_mark
-302    common  prlimit64               __x64_sys_prlimit64
-303    common  name_to_handle_at       __x64_sys_name_to_handle_at
-304    common  open_by_handle_at       __x64_sys_open_by_handle_at
-305    common  clock_adjtime           __x64_sys_clock_adjtime
-306    common  syncfs                  __x64_sys_syncfs
-307    64      sendmmsg                __x64_sys_sendmmsg
-308    common  setns                   __x64_sys_setns
-309    common  getcpu                  __x64_sys_getcpu
-310    64      process_vm_readv        __x64_sys_process_vm_readv
-311    64      process_vm_writev       __x64_sys_process_vm_writev
-312    common  kcmp                    __x64_sys_kcmp
-313    common  finit_module            __x64_sys_finit_module
-314    common  sched_setattr           __x64_sys_sched_setattr
-315    common  sched_getattr           __x64_sys_sched_getattr
-316    common  renameat2               __x64_sys_renameat2
-317    common  seccomp                 __x64_sys_seccomp
-318    common  getrandom               __x64_sys_getrandom
-319    common  memfd_create            __x64_sys_memfd_create
-320    common  kexec_file_load         __x64_sys_kexec_file_load
-321    common  bpf                     __x64_sys_bpf
-322    64      execveat                __x64_sys_execveat/ptregs
-323    common  userfaultfd             __x64_sys_userfaultfd
-324    common  membarrier              __x64_sys_membarrier
-325    common  mlock2                  __x64_sys_mlock2
-326    common  copy_file_range         __x64_sys_copy_file_range
-327    64      preadv2                 __x64_sys_preadv2
-328    64      pwritev2                __x64_sys_pwritev2
-329    common  pkey_mprotect           __x64_sys_pkey_mprotect
-330    common  pkey_alloc              __x64_sys_pkey_alloc
-331    common  pkey_free               __x64_sys_pkey_free
-332    common  statx                   __x64_sys_statx
-333    common  io_pgetevents           __x64_sys_io_pgetevents
-334    common  rseq                    __x64_sys_rseq
+237    common  mbind                   sys_mbind
+238    common  set_mempolicy           sys_set_mempolicy
+239    common  get_mempolicy           sys_get_mempolicy
+240    common  mq_open                 sys_mq_open
+241    common  mq_unlink               sys_mq_unlink
+242    common  mq_timedsend            sys_mq_timedsend
+243    common  mq_timedreceive         sys_mq_timedreceive
+244    64      mq_notify               sys_mq_notify
+245    common  mq_getsetattr           sys_mq_getsetattr
+246    64      kexec_load              sys_kexec_load
+247    64      waitid                  sys_waitid
+248    common  add_key                 sys_add_key
+249    common  request_key             sys_request_key
+250    common  keyctl                  sys_keyctl
+251    common  ioprio_set              sys_ioprio_set
+252    common  ioprio_get              sys_ioprio_get
+253    common  inotify_init            sys_inotify_init
+254    common  inotify_add_watch       sys_inotify_add_watch
+255    common  inotify_rm_watch        sys_inotify_rm_watch
+256    common  migrate_pages           sys_migrate_pages
+257    common  openat                  sys_openat
+258    common  mkdirat                 sys_mkdirat
+259    common  mknodat                 sys_mknodat
+260    common  fchownat                sys_fchownat
+261    common  futimesat               sys_futimesat
+262    common  newfstatat              sys_newfstatat
+263    common  unlinkat                sys_unlinkat
+264    common  renameat                sys_renameat
+265    common  linkat                  sys_linkat
+266    common  symlinkat               sys_symlinkat
+267    common  readlinkat              sys_readlinkat
+268    common  fchmodat                sys_fchmodat
+269    common  faccessat               sys_faccessat
+270    common  pselect6                sys_pselect6
+271    common  ppoll                   sys_ppoll
+272    common  unshare                 sys_unshare
+273    64      set_robust_list         sys_set_robust_list
+274    64      get_robust_list         sys_get_robust_list
+275    common  splice                  sys_splice
+276    common  tee                     sys_tee
+277    common  sync_file_range         sys_sync_file_range
+278    64      vmsplice                sys_vmsplice
+279    64      move_pages              sys_move_pages
+280    common  utimensat               sys_utimensat
+281    common  epoll_pwait             sys_epoll_pwait
+282    common  signalfd                sys_signalfd
+283    common  timerfd_create          sys_timerfd_create
+284    common  eventfd                 sys_eventfd
+285    common  fallocate               sys_fallocate
+286    common  timerfd_settime         sys_timerfd_settime
+287    common  timerfd_gettime         sys_timerfd_gettime
+288    common  accept4                 sys_accept4
+289    common  signalfd4               sys_signalfd4
+290    common  eventfd2                sys_eventfd2
+291    common  epoll_create1           sys_epoll_create1
+292    common  dup3                    sys_dup3
+293    common  pipe2                   sys_pipe2
+294    common  inotify_init1           sys_inotify_init1
+295    64      preadv                  sys_preadv
+296    64      pwritev                 sys_pwritev
+297    64      rt_tgsigqueueinfo       sys_rt_tgsigqueueinfo
+298    common  perf_event_open         sys_perf_event_open
+299    64      recvmmsg                sys_recvmmsg
+300    common  fanotify_init           sys_fanotify_init
+301    common  fanotify_mark           sys_fanotify_mark
+302    common  prlimit64               sys_prlimit64
+303    common  name_to_handle_at       sys_name_to_handle_at
+304    common  open_by_handle_at       sys_open_by_handle_at
+305    common  clock_adjtime           sys_clock_adjtime
+306    common  syncfs                  sys_syncfs
+307    64      sendmmsg                sys_sendmmsg
+308    common  setns                   sys_setns
+309    common  getcpu                  sys_getcpu
+310    64      process_vm_readv        sys_process_vm_readv
+311    64      process_vm_writev       sys_process_vm_writev
+312    common  kcmp                    sys_kcmp
+313    common  finit_module            sys_finit_module
+314    common  sched_setattr           sys_sched_setattr
+315    common  sched_getattr           sys_sched_getattr
+316    common  renameat2               sys_renameat2
+317    common  seccomp                 sys_seccomp
+318    common  getrandom               sys_getrandom
+319    common  memfd_create            sys_memfd_create
+320    common  kexec_file_load         sys_kexec_file_load
+321    common  bpf                     sys_bpf
+322    64      execveat                sys_execveat
+323    common  userfaultfd             sys_userfaultfd
+324    common  membarrier              sys_membarrier
+325    common  mlock2                  sys_mlock2
+326    common  copy_file_range         sys_copy_file_range
+327    64      preadv2                 sys_preadv2
+328    64      pwritev2                sys_pwritev2
+329    common  pkey_mprotect           sys_pkey_mprotect
+330    common  pkey_alloc              sys_pkey_alloc
+331    common  pkey_free               sys_pkey_free
+332    common  statx                   sys_statx
+333    common  io_pgetevents           sys_io_pgetevents
+334    common  rseq                    sys_rseq
 # don't use numbers 387 through 423, add new calls after the last
 # 'common' entry
-424    common  pidfd_send_signal       __x64_sys_pidfd_send_signal
-425    common  io_uring_setup          __x64_sys_io_uring_setup
-426    common  io_uring_enter          __x64_sys_io_uring_enter
-427    common  io_uring_register       __x64_sys_io_uring_register
-428    common  open_tree               __x64_sys_open_tree
-429    common  move_mount              __x64_sys_move_mount
-430    common  fsopen                  __x64_sys_fsopen
-431    common  fsconfig                __x64_sys_fsconfig
-432    common  fsmount                 __x64_sys_fsmount
-433    common  fspick                  __x64_sys_fspick
-434    common  pidfd_open              __x64_sys_pidfd_open
-435    common  clone3                  __x64_sys_clone3/ptregs
-437    common  openat2                 __x64_sys_openat2
-438    common  pidfd_getfd             __x64_sys_pidfd_getfd
+424    common  pidfd_send_signal       sys_pidfd_send_signal
+425    common  io_uring_setup          sys_io_uring_setup
+426    common  io_uring_enter          sys_io_uring_enter
+427    common  io_uring_register       sys_io_uring_register
+428    common  open_tree               sys_open_tree
+429    common  move_mount              sys_move_mount
+430    common  fsopen                  sys_fsopen
+431    common  fsconfig                sys_fsconfig
+432    common  fsmount                 sys_fsmount
+433    common  fspick                  sys_fspick
+434    common  pidfd_open              sys_pidfd_open
+435    common  clone3                  sys_clone3
+437    common  openat2                 sys_openat2
+438    common  pidfd_getfd             sys_pidfd_getfd
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
 # on-the-fly for compat_sys_*() compatibility system calls if X86_X32
 # is defined.
 #
-512    x32     rt_sigaction            __x32_compat_sys_rt_sigaction
-513    x32     rt_sigreturn            sys32_x32_rt_sigreturn
-514    x32     ioctl                   __x32_compat_sys_ioctl
-515    x32     readv                   __x32_compat_sys_readv
-516    x32     writev                  __x32_compat_sys_writev
-517    x32     recvfrom                __x32_compat_sys_recvfrom
-518    x32     sendmsg                 __x32_compat_sys_sendmsg
-519    x32     recvmsg                 __x32_compat_sys_recvmsg
-520    x32     execve                  __x32_compat_sys_execve/ptregs
-521    x32     ptrace                  __x32_compat_sys_ptrace
-522    x32     rt_sigpending           __x32_compat_sys_rt_sigpending
-523    x32     rt_sigtimedwait         __x32_compat_sys_rt_sigtimedwait_time64
-524    x32     rt_sigqueueinfo         __x32_compat_sys_rt_sigqueueinfo
-525    x32     sigaltstack             __x32_compat_sys_sigaltstack
-526    x32     timer_create            __x32_compat_sys_timer_create
-527    x32     mq_notify               __x32_compat_sys_mq_notify
-528    x32     kexec_load              __x32_compat_sys_kexec_load
-529    x32     waitid                  __x32_compat_sys_waitid
-530    x32     set_robust_list         __x32_compat_sys_set_robust_list
-531    x32     get_robust_list         __x32_compat_sys_get_robust_list
-532    x32     vmsplice                __x32_compat_sys_vmsplice
-533    x32     move_pages              __x32_compat_sys_move_pages
-534    x32     preadv                  __x32_compat_sys_preadv64
-535    x32     pwritev                 __x32_compat_sys_pwritev64
-536    x32     rt_tgsigqueueinfo       __x32_compat_sys_rt_tgsigqueueinfo
-537    x32     recvmmsg                __x32_compat_sys_recvmmsg_time64
-538    x32     sendmmsg                __x32_compat_sys_sendmmsg
-539    x32     process_vm_readv        __x32_compat_sys_process_vm_readv
-540    x32     process_vm_writev       __x32_compat_sys_process_vm_writev
-541    x32     setsockopt              __x32_compat_sys_setsockopt
-542    x32     getsockopt              __x32_compat_sys_getsockopt
-543    x32     io_setup                __x32_compat_sys_io_setup
-544    x32     io_submit               __x32_compat_sys_io_submit
-545    x32     execveat                __x32_compat_sys_execveat/ptregs
-546    x32     preadv2                 __x32_compat_sys_preadv64v2
-547    x32     pwritev2                __x32_compat_sys_pwritev64v2
+512    x32     rt_sigaction            compat_sys_rt_sigaction
+513    x32     rt_sigreturn            compat_sys_x32_rt_sigreturn
+514    x32     ioctl                   compat_sys_ioctl
+515    x32     readv                   compat_sys_readv
+516    x32     writev                  compat_sys_writev
+517    x32     recvfrom                compat_sys_recvfrom
+518    x32     sendmsg                 compat_sys_sendmsg
+519    x32     recvmsg                 compat_sys_recvmsg
+520    x32     execve                  compat_sys_execve
+521    x32     ptrace                  compat_sys_ptrace
+522    x32     rt_sigpending           compat_sys_rt_sigpending
+523    x32     rt_sigtimedwait         compat_sys_rt_sigtimedwait_time64
+524    x32     rt_sigqueueinfo         compat_sys_rt_sigqueueinfo
+525    x32     sigaltstack             compat_sys_sigaltstack
+526    x32     timer_create            compat_sys_timer_create
+527    x32     mq_notify               compat_sys_mq_notify
+528    x32     kexec_load              compat_sys_kexec_load
+529    x32     waitid                  compat_sys_waitid
+530    x32     set_robust_list         compat_sys_set_robust_list
+531    x32     get_robust_list         compat_sys_get_robust_list
+532    x32     vmsplice                compat_sys_vmsplice
+533    x32     move_pages              compat_sys_move_pages
+534    x32     preadv                  compat_sys_preadv64
+535    x32     pwritev                 compat_sys_pwritev64
+536    x32     rt_tgsigqueueinfo       compat_sys_rt_tgsigqueueinfo
+537    x32     recvmmsg                compat_sys_recvmmsg_time64
+538    x32     sendmmsg                compat_sys_sendmmsg
+539    x32     process_vm_readv        compat_sys_process_vm_readv
+540    x32     process_vm_writev       compat_sys_process_vm_writev
+541    x32     setsockopt              compat_sys_setsockopt
+542    x32     getsockopt              compat_sys_getsockopt
+543    x32     io_setup                compat_sys_io_setup
+544    x32     io_submit               compat_sys_io_submit
+545    x32     execveat                compat_sys_execveat
+546    x32     preadv2                 compat_sys_preadv64v2
+547    x32     pwritev2                compat_sys_pwritev64v2
index bfb21d049e6ce1569c301ac8813c7b3488cd2244..cf147db4e5ca0ea232ce4b9bf0f42e55580f97c0 100755 (executable)
@@ -22,7 +22,9 @@ include/uapi/linux/usbdevice_fs.h
 include/uapi/linux/vhost.h
 include/uapi/sound/asound.h
 include/linux/bits.h
+include/vdso/bits.h
 include/linux/const.h
+include/vdso/const.h
 include/linux/hash.h
 include/uapi/linux/hw_breakpoint.h
 arch/x86/include/asm/disabled-features.h
@@ -115,6 +117,7 @@ check arch/x86/lib/memcpy_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/ex
 check arch/x86/lib/memset_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" -I"^SYM_FUNC_START\(_LOCAL\)*(memset_\(erms\|orig\))"'
 check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman-common\(-tools\)*.h>"'
 check include/uapi/linux/mman.h       '-I "^#include <\(uapi/\)*asm/mman.h>"'
+check include/linux/build_bug.h       '-I "^#\(ifndef\|endif\)\( \/\/\)* static_assert$"'
 check include/linux/ctype.h          '-I "isdigit("'
 check lib/ctype.c                    '-I "^EXPORT_SYMBOL" -I "^#include <linux/export.h>" -B'
 check arch/x86/include/asm/inat.h     '-I "^#include [\"<]\(asm/\)*inat_types.h[\">]"'
index 062ca849c8fda9c0d032c154c380ddf067a34a26..f4db894e0af6d14bb0ead601ae7424d097be019a 100644 (file)
@@ -46,6 +46,7 @@ static size_t clone__scnprintf_flags(unsigned long flags, char *bf, size_t size,
        P_FLAG(NEWNET);
        P_FLAG(IO);
        P_FLAG(CLEAR_SIGHAND);
+       P_FLAG(INTO_CGROUP);
 #undef P_FLAG
 
        if (flags)
index 9fa771a90d79c2aad3c49338a2d7dbca922630ca..862c8331dded677cd9e1fb0563fa272472b4e42b 100644 (file)
@@ -69,6 +69,7 @@ static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
 
        P_MREMAP_FLAG(MAYMOVE);
        P_MREMAP_FLAG(FIXED);
+       P_MREMAP_FLAG(DONTUNMAP);
 #undef P_MREMAP_FLAG
 
        if (flags)
index 347b2c0789e4c05c5b13c3197f7df5521f8257b8..c5e3e9a68162d784287f8837c2c802808df517a0 100644 (file)
@@ -21,6 +21,8 @@ if cc_is_clang:
             vars[var] = sub("-fstack-clash-protection", "", vars[var])
         if not clang_has_option("-fstack-protector-strong"):
             vars[var] = sub("-fstack-protector-strong", "", vars[var])
+        if not clang_has_option("-fno-semantic-interposition"):
+            vars[var] = sub("-fno-semantic-interposition", "", vars[var])
 
 from distutils.core import setup, Extension
 
index 0fd713d3674f611813b4af461474916b991b6e53..03ecb8cd0eeca97c3769d3480575d6d4af13f349 100644 (file)
@@ -803,8 +803,11 @@ static void generic_metric(struct perf_stat_config *config,
                                     out->force_header ?
                                     (metric_name ? metric_name : name) : "", 0);
                }
-       } else
-               print_metric(config, ctxp, NULL, NULL, "", 0);
+       } else {
+               print_metric(config, ctxp, NULL, NULL,
+                            out->force_header ?
+                            (metric_name ? metric_name : name) : "", 0);
+       }
 
        for (i = 1; i < pctx.num_ids; i++)
                zfree(&pctx.ids[i].name);
index 845541544570a3c44ee04a85f84cfc31e5c9f26d..b5310832c19c640496ae92ad8845b92a10e66ef9 100644 (file)
@@ -41,6 +41,10 @@ uninstall :
        if [ -d $(DESTDIR)$(PREFIX)/lib/pm-graph/config ] ; then \
                rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph/config; \
        fi;
+       rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/__pycache__/*
+       if [ -d $(DESTDIR)$(PREFIX)/lib/pm-graph/__pycache__ ] ; then \
+               rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph/__pycache__; \
+       fi;
        rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/*
        if [ -d $(DESTDIR)$(PREFIX)/lib/pm-graph ] ; then \
                rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph; \
index 96259f6e57152bc47ea8b72129471c14ee713371..afe6beb40ad91b6b33590992dc5db5479cf9b186 100644 (file)
@@ -1,7 +1,12 @@
-                     p m - g r a p h
+                                                _
+    _ __  _ __ ___         __ _ _ __ __ _ _ __ | |__
+   | '_ \| '_ ` _ \ _____ / _` | '__/ _` | '_ \| '_ \
+   | |_) | | | | | |_____| (_| | | | (_| | |_) | | | |
+   | .__/|_| |_| |_|      \__, |_|  \__,_| .__/|_| |_|
+   |_|                    |___/          |_|
 
    pm-graph: suspend/resume/boot timing analysis tools
-    Version: 5.5
+    Version: 5.6
      Author: Todd Brandt <todd.e.brandt@intel.com>
   Home Page: https://01.org/pm-graph
 
        - upstream version in git:
          https://github.com/intel/pm-graph/
 
- Requirements:
-       - runs with python2 or python3, choice is made by /usr/bin/python link
-       - python2 now requires python-configparser be installed
-
  Table of Contents
        - Overview
        - Setup
@@ -29,6 +30,8 @@
                - Basic Usage
                - Dev Mode Usage
                - Proc Mode Usage
+       - Endurance Testing
+               - Usage Examples
        - Configuration Files
                - Usage Examples
                - Config File Options
 |                            SETUP                               |
 ------------------------------------------------------------------
 
-    These packages are required to execute the scripts
+    Package Requirements
+       - runs with python2 or python3, choice is made by /usr/bin/python link
        - python
-       - python-requests
+       - python-configparser (for python2 sleepgraph)
+       - python-requests (for googlesheet.py)
+       - linux-tools-common (for turbostat usage in sleepgraph)
 
        Ubuntu:
-          sudo apt-get install python python-requests
+          sudo apt-get install python python-configparser python-requests linux-tools-common
 
        Fedora:
-          sudo dnf install python python-requests
+          sudo dnf install python python-configparser python-requests linux-tools-common
 
     The tools can most easily be installed via git clone and make install
 
@@ -190,6 +196,104 @@ _______________
 
  %> sudo ./sleepgraph.py -config config/suspend-proc.cfg
 
+------------------------------------------------------------------
+|                     ENDURANCE TESTING                          |
+------------------------------------------------------------------
+
+ The best way to gauge the health of a system is to run a series of
+ suspend/resumes over an extended period and analyze the behavior. This can be
+ accomplished with sleepgraph's -multi argument. You specify two numbers: the
+ number of tests to run OR the duration in days, hours, or minutes, and the
+ delay in seconds between them. For instance, -multi 20 5: execute 20 tests with
+ a 5 second delay between each, or -multi 24h 0: execute tests over a 24 hour
+ period with no delay between tests. You can include any other options you like
+ to generate the data you want. It's most useful to collect dev mode timelines
+ as the kprobes don't alter the performance much and you get more insight.
+
+ On completion, the output folder contains a series of folders for the
+ individual test data and a set of summary pages in the root. The summary.html
+ file is a tabular list of the tests with relevant info and links. The
+ summary-issue.html and summary-devices.html files include data taken from
+ all tests on kernel issues and device performance. The folder looks like this:
+
+  suspend-xN-{date}-{time}:
+       summary.html
+       summary-issues.html
+       summary-devices.html
+       suspend-{date}-{time} (1)
+       suspend-{date}-{time} (2)
+       ...
+
+ These are the relevant arguments to use for testing:
+
+  -m mode
+       Mode to initiate for suspend e.g. mem, freeze, standby (default: mem).
+
+  -rtcwake t
+       Use rtcwake to autoresume after t seconds (default: 15).
+
+  -gzip (optional)
+       Gzip the trace and dmesg logs to save space. The tool can also read in
+       gzipped logs for processing. This reduces the multitest folder size.
+
+  -dev (optional)
+       Add kernel source calls and threads to the timeline (default: disabled).
+
+  -multi n d
+       Execute n consecutive tests at d seconds intervals. The outputs will be
+       created in a new subdirectory: suspend-xN-{date}-{time}. When the multitest
+       run is done, the -summary command is called automatically to create summary
+       html files for all the data (unless you use -skiphtml). -skiphtml will
+       speed up the testing by not creating timelines or summary html files. You
+       can then run the tool again at a later time with -summary and -genhtml to
+       create the timelines.
+
+  -skiphtml (optional)
+       Run the test and capture the trace logs, but skip the timeline and summary
+       html generation. This can greatly speed up overall testing. You can then
+       copy the data to a faster host machine and run -summary -genhtml to
+       generate the timelines and summary.
+
+ These are the relevant commands to use after testing is complete:
+
+  -summary indir
+       Generate or regenerate the summary for a -multi test run. Creates three
+       files: summary.html, summary-issues.html, and summary-devices.html in the
+       current folder. summary.html is a table of tests with relevant info sorted
+       by kernel/host/mode, and links to the test html files. summary-issues.html
+       is a list of kernel issues found in dmesg from all the tests.
+       summary-devices.html is a list of devices and times from all the tests.
+
+  -genhtml
+       Used  with -summary to regenerate any missing html timelines from their
+       dmesg and ftrace logs. This will require a significant amount of time if
+       there are thousands of tests.
+
+Usage Examples
+_______________
+
+ A multitest is initiated like this:
+
+  %> sudo ./sleepgraph.py -m mem -rtcwake 10 -dev -gzip -multi 2000 0
+
+       or you can skip timeline generation in order to speed things up
+
+  %> sudo ./sleepgraph.py -m mem -rtcwake 10 -dev -gzip -multi 2000 0 -skiphtml
+
+ The tool will produce an output folder with all the test subfolders inside.
+ Each test subfolder contains the dmesg/ftrace logs and/or the html timeline
+ depending on whether you used the -skiphtml option. The root folder contains
+ the summary.html files.
+
+ The summary for an existing multitest is generated like this:
+
+  %> cd suspend-x2000-{date}-{time}
+  %> sleepgraph.py -summary .
+
+       or if you need to generate the html timelines you can use -genhtml
+
+  %> cd suspend-xN-{date}-{time}
+  %> sleepgraph.py -summary . -genhtml
 
 ------------------------------------------------------------------
 |                    CONFIGURATION FILES                         |
index d3b99a1e92d6f2aa584f695375fa5fd882d2e30a..2823cd3122f7bb325af60d5ea6d6a9528a9ef287 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: GPL-2.0-only
 #
 # Tool for analyzing boot timing
index 43aee64316df06a07d57054c1110934770ecca25..5126271de98a6a29b1c890c0c4187ca2bcbe2e20 100644 (file)
@@ -74,8 +74,10 @@ after the test is complete.
 Switch the display to the requested mode for the test using the xset command.
 This helps maintain the consistency of test data for better comparison.
 .TP
-\fB-skiphtml\fR
-Run the test and capture the trace logs, but skip the timeline generation.
+\fB-wifi\fR
+If a wifi connection is available, check that it reconnects after resume. Include
+the reconnect time in the total resume time calculation and treat wifi timeouts
+as resume failures.
 
 .SS "advanced"
 .TP
@@ -117,8 +119,24 @@ Include \fIt\fR ms delay before 1st suspend (default: 0 ms).
 Include \fIt\fR ms delay after last resume (default: 0 ms).
 .TP
 \fB-multi \fIn d\fR
-Execute \fIn\fR consecutive tests at \fId\fR seconds intervals. The outputs will
-be created in a new subdirectory with a summary page: suspend-xN-{date}-{time}.
+Used for endurance testing. If \fIn\fR is entirely numeric, it's treated as a count:
+Execute \fIn\fR consecutive tests at \fId\fR second intervals.
+If \fIn\fR is an integer followed by a "d", "h", or "m", it's treated as a duration:
+Execute tests continuously over \fIn\fR days, hours, or minutes at \fId\fR second intervals.
+The outputs will be created in a new subdirectory, for count: suspend-{date}-{time}-xN,
+for duration: suspend-{date}-{time}-Nm. When the multitest run is done, the \fI-summary\fR
+command is called automatically to create summary html files for all the data (unless you
+use \fI-skiphtml\fR). \fI-skiphtml\fR will speed up the testing by not creating timelines
+or summary html files. You can then run the tool again at a later time with \fI-summary\fR
+and \fI-genhtml\fR to create the timelines.
+.TP
+\fB-maxfail \fIn\fR
+Abort a -multi run after \fIn\fR consecutive fails. 0 means never abort (default = 0).
+.TP
+\fB-skiphtml\fR
+Run the test and capture the trace logs, but skip the timeline generation.
+You can generate the html timelines later with \fI-dmesg\fR & \fI-ftrace\fR, or
+by running \fI-summary\fR and \fI-genhtml\fR.
 
 .SS "ftrace debug"
 .TP
@@ -173,11 +191,20 @@ Set trace buffer size to N kilo-bytes (default: all of free memory up to 3GB)
 .SH COMMANDS
 .TP
 \fB-summary \fIindir\fR
-Create a summary page of all tests in \fIindir\fR. Creates summary.html
-in the current folder. The output page is a table of tests with
-suspend and resume values sorted by suspend mode, host, and kernel.
-Includes test averages by mode and links to the test html files.
-Use -genhtml to include tests with missing html.
+Create a set of summary pages for all tests in \fIindir\fR recursively.
+Creates summary.html, summary-issues.html, and summary-devices.html in the current folder.
+summary.html is a table of tests with relevant info sorted by kernel/host/mode,
+and links to the test html files. It identifies the minimum, maximum, and median
+suspend and resume times for you with highlights and links in the header.
+summary-issues.html is a list of kernel issues found in dmesg from all the tests.
+summary-devices.html is a list of devices and times from all the tests.
+
+Use \fI-genhtml\fR to regenerate any tests with missing html.
+.TP
+\fB-genhtml\fR
+Used with \fI-summary\fR to regenerate any missing html timelines from their
+dmesg and ftrace logs. This will require a significant amount of time if there
+are thousands of tests.
 .TP
 \fB-modes\fR
 List available suspend modes.
@@ -189,10 +216,7 @@ with any options you intend to use to see if they will work.
 \fB-fpdt\fR
 Print out the contents of the ACPI Firmware Performance Data Table.
 .TP
-\fB-battery\fR
-Print out battery status and current charge.
-.TP
-\fB-wifi\fR
+\fB-wificheck\fR
 Print out wifi status and connection details.
 .TP
 \fB-xon/-xoff/-xstandby/-xsuspend\fR
@@ -208,6 +232,9 @@ Print out system info extracted from BIOS. Reads /dev/mem directly instead of go
 \fB-devinfo\fR
 Print out the pm settings of all devices which support runtime suspend.
 .TP
+\fB-cmdinfo\fR
+Print out all the platform data collected from the system that makes it into the logs.
+.TP
 \fB-flist\fR
 Print the list of ftrace functions currently being captured. Functions
 that are not available as symbols in the current kernel are shown in red.
@@ -272,14 +299,20 @@ Run two suspends back to back, include a 500ms delay before, after, and in betwe
 .IP
 \f(CW$ sudo sleepgraph -m mem -rtcwake 15 -x2 -predelay 500 -x2delay 500 -postdelay 500\fR
 .PP
+Execute a suspend using a custom command.
+.IP
+\f(CW$ sudo sleepgraph -cmd "echo mem > /sys/power/state" -rtcwake 15\fR
+.PP
+
+.SS "endurance testing using -multi"
+.PP
 Do a batch run of 10 freezes with 30 seconds delay between runs.
 .IP
 \f(CW$ sudo sleepgraph -m freeze -rtcwake 15 -multi 10 30\fR
 .PP
-Execute a suspend using a custom command.
+Do a batch run of freezes for 24 hours.
 .IP
-\f(CW$ sudo sleepgraph -cmd "echo mem > /sys/power/state" -rtcwake 15\fR
-.PP
+\f(CW$ sudo sleepgraph -m freeze -rtcwake 15 -multi 24h 0\fR
 
 .SS "adding callgraph data"
 Add device callgraphs. Limit the trace depth and only show callgraphs 10ms or larger.
index f7d1c1f62f860b18b37749bdff0aff2e40dc9ec8..9b0404d107686aa5c63a5f9a06dbe76d00b47514 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: GPL-2.0-only
 #
 # Tool for analyzing suspend/resume timing
@@ -58,7 +58,7 @@ import re
 import platform
 import signal
 import codecs
-from datetime import datetime
+from datetime import datetime, timedelta
 import struct
 import configparser
 import gzip
@@ -81,12 +81,13 @@ def ascii(text):
 #       store system values and test parameters
 class SystemValues:
        title = 'SleepGraph'
-       version = '5.5'
+       version = '5.6'
        ansi = False
        rs = 0
        display = ''
        gzip = False
        sync = False
+       wifi = False
        verbose = False
        testlog = True
        dmesglog = True
@@ -97,7 +98,8 @@ class SystemValues:
        cgphase = ''
        cgtest = -1
        cgskip = ''
-       multitest = {'run': False, 'count': 0, 'delay': 0}
+       maxfail = 0
+       multitest = {'run': False, 'count': 1000000, 'delay': 0}
        max_graph_depth = 0
        callloopmaxgap = 0.0001
        callloopmaxlen = 0.005
@@ -148,7 +150,7 @@ class SystemValues:
        x2delay = 0
        skiphtml = False
        usecallgraph = False
-       ftopfunc = 'suspend_devices_and_enter'
+       ftopfunc = 'pm_suspend'
        ftop = False
        usetraceevents = False
        usetracemarkers = True
@@ -164,6 +166,8 @@ class SystemValues:
        predelay = 0
        postdelay = 0
        pmdebug = ''
+       tmstart = 'SUSPEND START %Y%m%d-%H:%M:%S.%f'
+       tmend = 'RESUME COMPLETE %Y%m%d-%H:%M:%S.%f'
        tracefuncs = {
                'sys_sync': {},
                'ksys_sync': {},
@@ -183,9 +187,11 @@ class SystemValues:
                'acpi_s2idle_sync': {},
                'acpi_s2idle_begin': {},
                'acpi_s2idle_prepare': {},
+               'acpi_s2idle_prepare_late': {},
                'acpi_s2idle_wake': {},
                'acpi_s2idle_wakeup': {},
                'acpi_s2idle_restore': {},
+               'acpi_s2idle_restore_early': {},
                'hibernate_preallocate_memory': {},
                'create_basic_memory_bitmaps': {},
                'swsusp_write': {},
@@ -270,12 +276,23 @@ class SystemValues:
                'intel_opregion_init': {},
                'intel_fbdev_set_suspend': {},
        }
+       infocmds = [
+               [0, 'kparams', 'cat', '/proc/cmdline'],
+               [0, 'mcelog', 'mcelog'],
+               [0, 'pcidevices', 'lspci', '-tv'],
+               [0, 'usbdevices', 'lsusb', '-t'],
+               [1, 'interrupts', 'cat', '/proc/interrupts'],
+               [1, 'wakeups', 'cat', '/sys/kernel/debug/wakeup_sources'],
+               [2, 'gpecounts', 'sh', '-c', 'grep -v invalid /sys/firmware/acpi/interrupts/*'],
+               [2, 'suspendstats', 'sh', '-c', 'grep -v invalid /sys/power/suspend_stats/*'],
+               [2, 'cpuidle', 'sh', '-c', 'grep -v invalid /sys/devices/system/cpu/cpu*/cpuidle/state*/s2idle/*'],
+               [2, 'battery', 'sh', '-c', 'grep -v invalid /sys/class/power_supply/*/*'],
+       ]
        cgblacklist = []
        kprobes = dict()
        timeformat = '%.3f'
        cmdline = '%s %s' % \
                        (os.path.basename(sys.argv[0]), ' '.join(sys.argv[1:]))
-       kparams = ''
        sudouser = ''
        def __init__(self):
                self.archargs = 'args_'+platform.machine()
@@ -295,6 +312,9 @@ class SystemValues:
                if os.getuid() == 0 and 'SUDO_USER' in os.environ and \
                        os.environ['SUDO_USER']:
                        self.sudouser = os.environ['SUDO_USER']
+       def resetlog(self):
+               self.logmsg = ''
+               self.platinfo = []
        def vprint(self, msg):
                self.logmsg += msg+'\n'
                if self.verbose or msg.startswith('WARNING:'):
@@ -304,11 +324,11 @@ class SystemValues:
                        return
                signame = self.signames[signum] if signum in self.signames else 'UNKNOWN'
                msg = 'Signal %s caused a tool exit, line %d' % (signame, frame.f_lineno)
-               sysvals.outputResult({'error':msg})
+               self.outputResult({'error':msg})
                sys.exit(3)
        def signalHandlerInit(self):
                capture = ['BUS', 'SYS', 'XCPU', 'XFSZ', 'PWR', 'HUP', 'INT', 'QUIT',
-                       'ILL', 'ABRT', 'FPE', 'SEGV', 'TERM', 'TSTP']
+                       'ILL', 'ABRT', 'FPE', 'SEGV', 'TERM']
                self.signames = dict()
                for i in capture:
                        s = 'SIG'+i
@@ -336,6 +356,8 @@ class SystemValues:
                        self.outputResult({'error':msg})
                        sys.exit(1)
                return False
+       def usable(self, file):
+               return (os.path.exists(file) and os.path.getsize(file) > 0)
        def getExec(self, cmd):
                try:
                        fp = Popen(['which', cmd], stdout=PIPE, stderr=PIPE).stdout
@@ -389,12 +411,6 @@ class SystemValues:
                r = info['bios-release-date'] if 'bios-release-date' in info else ''
                self.sysstamp = '# sysinfo | man:%s | plat:%s | cpu:%s | bios:%s | biosdate:%s | numcpu:%d | memsz:%d | memfr:%d' % \
                        (m, p, c, b, r, self.cpucount, self.memtotal, self.memfree)
-               try:
-                       kcmd = open('/proc/cmdline', 'r').read().strip()
-               except:
-                       kcmd = ''
-               if kcmd:
-                       self.sysstamp += '\n# kparams | %s' % kcmd
        def printSystemInfo(self, fatal=False):
                self.rootCheck(True)
                out = dmidecode(self.mempath, fatal)
@@ -441,6 +457,7 @@ class SystemValues:
                        self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html'
                if not os.path.isdir(self.testdir):
                        os.makedirs(self.testdir)
+               self.sudoUserchown(self.testdir)
        def getValueList(self, value):
                out = []
                for i in value.split(','):
@@ -486,7 +503,7 @@ class SystemValues:
                fp.close()
                self.dmesgstart = float(ktime)
        def getdmesg(self, testdata):
-               op = self.writeDatafileHeader(sysvals.dmesgfile, testdata)
+               op = self.writeDatafileHeader(self.dmesgfile, testdata)
                # store all new dmesg lines since initdmesg was called
                fp = Popen('dmesg', stdout=PIPE).stdout
                for line in fp:
@@ -716,9 +733,10 @@ class SystemValues:
                        if name == f:
                                return True
                return False
-       def initFtrace(self):
-               self.printSystemInfo(False)
-               pprint('INITIALIZING FTRACE...')
+       def initFtrace(self, quiet=False):
+               if not quiet:
+                       sysvals.printSystemInfo(False)
+                       pprint('INITIALIZING FTRACE...')
                # turn trace off
                self.fsetVal('0', 'tracing_on')
                self.cleanupFtrace()
@@ -746,7 +764,7 @@ class SystemValues:
                        if tgtsize < 65536:
                                tgtsize = int(self.fgetVal('buffer_size_kb')) * cpus
                                break
-               pprint('Setting trace buffers to %d kB (%d kB per cpu)' % (tgtsize, tgtsize/cpus))
+               self.vprint('Setting trace buffers to %d kB (%d kB per cpu)' % (tgtsize, tgtsize/cpus))
                # initialize the callgraph trace
                if(self.usecallgraph):
                        # set trace type
@@ -782,7 +800,8 @@ class SystemValues:
                        if self.usedevsrc:
                                for name in self.dev_tracefuncs:
                                        self.defaultKprobe(name, self.dev_tracefuncs[name])
-                       pprint('INITIALIZING KPROBES...')
+                       if not quiet:
+                               pprint('INITIALIZING KPROBES...')
                        self.addKprobes(self.verbose)
                if(self.usetraceevents):
                        # turn trace events on
@@ -827,21 +846,10 @@ class SystemValues:
                                fw = test['fw']
                                if(fw):
                                        fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1]))
-                       if 'mcelog' in test:
-                               fp.write('# mcelog %s\n' % test['mcelog'])
                        if 'turbo' in test:
                                fp.write('# turbostat %s\n' % test['turbo'])
-                       if 'bat' in test:
-                               (a1, c1), (a2, c2) = test['bat']
-                               fp.write('# battery %s %d %s %d\n' % (a1, c1, a2, c2))
                        if 'wifi' in test:
-                               wstr = []
-                               for wifi in test['wifi']:
-                                       tmp = []
-                                       for key in sorted(wifi):
-                                               tmp.append('%s:%s' % (key, wifi[key]))
-                                       wstr.append('|'.join(tmp))
-                               fp.write('# wifi %s\n' % (','.join(wstr)))
+                               fp.write('# wifi %s\n' % test['wifi'])
                        if test['error'] or len(testdata) > 1:
                                fp.write('# enter_sleep_error %s\n' % test['error'])
                return fp
@@ -901,23 +909,7 @@ class SystemValues:
        def b64zip(self, data):
                out = base64.b64encode(codecs.encode(data.encode(), 'zlib')).decode()
                return out
-       def mcelog(self, clear=False):
-               cmd = self.getExec('mcelog')
-               if not cmd:
-                       return ''
-               if clear:
-                       call(cmd+' > /dev/null 2>&1', shell=True)
-                       return ''
-               try:
-                       fp = Popen([cmd], stdout=PIPE, stderr=PIPE).stdout
-                       out = ascii(fp.read()).strip()
-                       fp.close()
-               except:
-                       return ''
-               if not out:
-                       return ''
-               return self.b64zip(out)
-       def platforminfo(self):
+       def platforminfo(self, cmdafter):
                # add platform info on to a completed ftrace file
                if not os.path.exists(self.ftracefile):
                        return False
@@ -1001,31 +993,76 @@ class SystemValues:
                footer += '# platform-devinfo: %s\n' % self.b64zip(out)
 
                # add a line for each of these commands with their outputs
-               cmds = [
-                       ['pcidevices', 'lspci', '-tv'],
-                       ['interrupts', 'cat', '/proc/interrupts'],
-                       ['gpecounts', 'sh', '-c', 'grep -v invalid /sys/firmware/acpi/interrupts/gpe*'],
-               ]
-               for cargs in cmds:
-                       name = cargs[0]
-                       cmdline = ' '.join(cargs[1:])
-                       cmdpath = self.getExec(cargs[1])
-                       if not cmdpath:
+               for name, cmdline, info in cmdafter:
+                       footer += '# platform-%s: %s | %s\n' % (name, cmdline, self.b64zip(info))
+
+               with self.openlog(self.ftracefile, 'a') as fp:
+                       fp.write(footer)
+               return True
+       def commonPrefix(self, list):
+               if len(list) < 2:
+                       return ''
+               prefix = list[0]
+               for s in list[1:]:
+                       while s[:len(prefix)] != prefix and prefix:
+                               prefix = prefix[:len(prefix)-1]
+                       if not prefix:
+                               break
+               if '/' in prefix and prefix[-1] != '/':
+                       prefix = prefix[0:prefix.rfind('/')+1]
+               return prefix
+       def dictify(self, text, format):
+               out = dict()
+               header = True if format == 1 else False
+               delim = ' ' if format == 1 else ':'
+               for line in text.split('\n'):
+                       if header:
+                               header, out['@'] = False, line
+                               continue
+                       line = line.strip()
+                       if delim in line:
+                               data = line.split(delim, 1)
+                               num = re.search(r'[\d]+', data[1])
+                               if format == 2 and num:
+                                       out[data[0].strip()] = num.group()
+                               else:
+                                       out[data[0].strip()] = data[1]
+               return out
+       def cmdinfo(self, begin, debug=False):
+               out = []
+               if begin:
+                       self.cmd1 = dict()
+               for cargs in self.infocmds:
+                       delta, name = cargs[0], cargs[1]
+                       cmdline, cmdpath = ' '.join(cargs[2:]), self.getExec(cargs[2])
+                       if not cmdpath or (begin and not delta):
                                continue
-                       cmd = [cmdpath] + cargs[2:]
                        try:
-                               fp = Popen(cmd, stdout=PIPE, stderr=PIPE).stdout
+                               fp = Popen([cmdpath]+cargs[3:], stdout=PIPE, stderr=PIPE).stdout
                                info = ascii(fp.read()).strip()
                                fp.close()
                        except:
                                continue
-                       if not info:
-                               continue
-                       footer += '# platform-%s: %s | %s\n' % (name, cmdline, self.b64zip(info))
-
-               with self.openlog(self.ftracefile, 'a') as fp:
-                       fp.write(footer)
-               return True
+                       if not debug and begin:
+                               self.cmd1[name] = self.dictify(info, delta)
+                       elif not debug and delta and name in self.cmd1:
+                               before, after = self.cmd1[name], self.dictify(info, delta)
+                               dinfo = ('\t%s\n' % before['@']) if '@' in before else ''
+                               prefix = self.commonPrefix(list(before.keys()))
+                               for key in sorted(before):
+                                       if key in after and before[key] != after[key]:
+                                               title = key.replace(prefix, '')
+                                               if delta == 2:
+                                                       dinfo += '\t%s : %s -> %s\n' % \
+                                                               (title, before[key].strip(), after[key].strip())
+                                               else:
+                                                       dinfo += '%10s (start) : %s\n%10s (after) : %s\n' % \
+                                                               (title, before[key], title, after[key])
+                               dinfo = '\tnothing changed' if not dinfo else dinfo.rstrip()
+                               out.append((name, cmdline, dinfo))
+                       else:
+                               out.append((name, cmdline, '\tnothing' if not info else info))
+               return out
        def haveTurbostat(self):
                if not self.tstat:
                        return False
@@ -1035,8 +1072,8 @@ class SystemValues:
                fp = Popen([cmd, '-v'], stdout=PIPE, stderr=PIPE).stderr
                out = ascii(fp.read()).strip()
                fp.close()
-               if re.match('turbostat version [0-9\.]* .*', out):
-                       sysvals.vprint(out)
+               if re.match('turbostat version .*', out):
+                       self.vprint(out)
                        return True
                return False
        def turbostat(self):
@@ -1056,11 +1093,11 @@ class SystemValues:
                fp.close()
                if not keyline or not valline or len(keyline) != len(valline):
                        errmsg = 'unrecognized turbostat output:\n'+rawout.strip()
-                       sysvals.vprint(errmsg)
-                       if not sysvals.verbose:
+                       self.vprint(errmsg)
+                       if not self.verbose:
                                pprint(errmsg)
                        return ''
-               if sysvals.verbose:
+               if self.verbose:
                        pprint(rawout.strip())
                out = []
                for key in keyline:
@@ -1068,30 +1105,36 @@ class SystemValues:
                        val = valline[idx]
                        out.append('%s=%s' % (key, val))
                return '|'.join(out)
-       def checkWifi(self):
-               out = dict()
-               iwcmd, ifcmd = self.getExec('iwconfig'), self.getExec('ifconfig')
-               if not iwcmd or not ifcmd:
-                       return out
-               fp = Popen(iwcmd, stdout=PIPE, stderr=PIPE).stdout
-               for line in fp:
-                       m = re.match('(?P<dev>\S*) .* ESSID:(?P<ess>\S*)', ascii(line))
-                       if not m:
+       def wifiDetails(self, dev):
+               try:
+                       info = open('/sys/class/net/%s/device/uevent' % dev, 'r').read().strip()
+               except:
+                       return dev
+               vals = [dev]
+               for prop in info.split('\n'):
+                       if prop.startswith('DRIVER=') or prop.startswith('PCI_ID='):
+                               vals.append(prop.split('=')[-1])
+               return ':'.join(vals)
+       def checkWifi(self, dev=''):
+               try:
+                       w = open('/proc/net/wireless', 'r').read().strip()
+               except:
+                       return ''
+               for line in reversed(w.split('\n')):
+                       m = re.match(' *(?P<dev>.*): (?P<stat>[0-9a-f]*) .*', w.split('\n')[-1])
+                       if not m or (dev and dev != m.group('dev')):
                                continue
-                       out['device'] = m.group('dev')
-                       if '"' in m.group('ess'):
-                               out['essid'] = m.group('ess').strip('"')
-                               break
-               fp.close()
-               if 'device' in out:
-                       fp = Popen([ifcmd, out['device']], stdout=PIPE, stderr=PIPE).stdout
-                       for line in fp:
-                               m = re.match('.* inet (?P<ip>[0-9\.]*)', ascii(line))
-                               if m:
-                                       out['ip'] = m.group('ip')
-                                       break
-                       fp.close()
-               return out
+                       return m.group('dev')
+               return ''
+       def pollWifi(self, dev, timeout=60):
+               start = time.time()
+               while (time.time() - start) < timeout:
+                       w = self.checkWifi(dev)
+                       if w:
+                               return '%s reconnected %.2f' % \
+                                       (self.wifiDetails(dev), max(0, time.time() - start))
+                       time.sleep(0.01)
+               return '%s timeout %d' % (self.wifiDetails(dev), timeout)
        def errorSummary(self, errinfo, msg):
                found = False
                for entry in errinfo:
@@ -1113,8 +1156,9 @@ class SystemValues:
                                arr[j] = arr[j]\
                                        .replace('\\', '\\\\').replace(']', '\]').replace('[', '\[')\
                                        .replace('.', '\.').replace('+', '\+').replace('*', '\*')\
-                                       .replace('(', '\(').replace(')', '\)')
-               mstr = ' '.join(arr)
+                                       .replace('(', '\(').replace(')', '\)').replace('}', '\}')\
+                                       .replace('{', '\{')
+               mstr = ' *'.join(arr)
                entry = {
                        'line': msg,
                        'match': mstr,
@@ -1122,6 +1166,44 @@ class SystemValues:
                        'urls': {self.hostname: [self.htmlfile]}
                }
                errinfo.append(entry)
+       def multistat(self, start, idx, finish):
+               if 'time' in self.multitest:
+                       id = '%d Duration=%dmin' % (idx+1, self.multitest['time'])
+               else:
+                       id = '%d/%d' % (idx+1, self.multitest['count'])
+               t = time.time()
+               if 'start' not in self.multitest:
+                       self.multitest['start'] = self.multitest['last'] = t
+                       self.multitest['total'] = 0.0
+                       pprint('TEST (%s) START' % id)
+                       return
+               dt = t - self.multitest['last']
+               if not start:
+                       if idx == 0 and self.multitest['delay'] > 0:
+                               self.multitest['total'] += self.multitest['delay']
+                       pprint('TEST (%s) COMPLETE -- Duration %.1fs' % (id, dt))
+                       return
+               self.multitest['total'] += dt
+               self.multitest['last'] = t
+               avg = self.multitest['total'] / idx
+               if 'time' in self.multitest:
+                       left = finish - datetime.now()
+                       left -= timedelta(microseconds=left.microseconds)
+               else:
+                       left = timedelta(seconds=((self.multitest['count'] - idx) * int(avg)))
+               pprint('TEST (%s) START - Avg Duration %.1fs, Time left %s' % \
+                       (id, avg, str(left)))
+       def multiinit(self, c, d):
+               sz, unit = 'count', 'm'
+               if c.endswith('d') or c.endswith('h') or c.endswith('m'):
+                       sz, unit, c = 'time', c[-1], c[:-1]
+               self.multitest['run'] = True
+               self.multitest[sz] = getArgInt('multi: n d (exec count)', c, 1, 1000000, False)
+               self.multitest['delay'] = getArgInt('multi: n d (delay between tests)', d, 0, 3600, False)
+               if unit == 'd':
+                       self.multitest[sz] *= 1440
+               elif unit == 'h':
+                       self.multitest[sz] *= 60
 
 sysvals = SystemValues()
 switchvalues = ['enable', 'disable', 'on', 'off', 'true', 'false', '1', '0']
@@ -1210,25 +1292,30 @@ class Data:
                'resume_complete': {'order': 9, 'color': '#FFFFCC'},
        }
        errlist = {
-               'HWERROR' : '.*\[ *Hardware Error *\].*',
-               'FWBUG'   : '.*\[ *Firmware Bug *\].*',
-               'BUG'     : '.*BUG.*',
-               'ERROR'   : '.*ERROR.*',
-               'WARNING' : '.*WARNING.*',
-               'IRQ'     : '.*genirq: .*',
-               'TASKFAIL': '.*Freezing of tasks *.*',
-               'ACPI'    : '.*ACPI *(?P<b>[A-Za-z]*) *Error[: ].*',
-               'DEVFAIL' : '.* failed to (?P<b>[a-z]*) async: .*',
-               'DISKFULL': '.*No space left on device.*',
-               'USBERR'  : '.*usb .*device .*, error [0-9-]*',
-               'ATAERR'  : ' *ata[0-9\.]*: .*failed.*',
-               'MEIERR'  : ' *mei.*: .*failed.*',
-               'TPMERR'  : '(?i) *tpm *tpm[0-9]*: .*error.*',
+               'HWERROR' : r'.*\[ *Hardware Error *\].*',
+               'FWBUG'   : r'.*\[ *Firmware Bug *\].*',
+               'BUG'     : r'(?i).*\bBUG\b.*',
+               'ERROR'   : r'(?i).*\bERROR\b.*',
+               'WARNING' : r'(?i).*\bWARNING\b.*',
+               'FAULT'   : r'(?i).*\bFAULT\b.*',
+               'FAIL'    : r'(?i).*\bFAILED\b.*',
+               'INVALID' : r'(?i).*\bINVALID\b.*',
+               'CRASH'   : r'(?i).*\bCRASHED\b.*',
+               'IRQ'     : r'.*\bgenirq: .*',
+               'TASKFAIL': r'.*Freezing of tasks *.*',
+               'ACPI'    : r'.*\bACPI *(?P<b>[A-Za-z]*) *Error[: ].*',
+               'DISKFULL': r'.*\bNo space left on device.*',
+               'USBERR'  : r'.*usb .*device .*, error [0-9-]*',
+               'ATAERR'  : r' *ata[0-9\.]*: .*failed.*',
+               'MEIERR'  : r' *mei.*: .*failed.*',
+               'TPMERR'  : r'(?i) *tpm *tpm[0-9]*: .*error.*',
        }
        def __init__(self, num):
                idchar = 'abcdefghij'
                self.start = 0.0 # test start
                self.end = 0.0   # test end
+               self.hwstart = 0 # rtc test start
+               self.hwend = 0   # rtc test end
                self.tSuspended = 0.0 # low-level suspend start
                self.tResumed = 0.0   # low-level resume start
                self.tKernSus = 0.0   # kernel level suspend start
@@ -1240,10 +1327,8 @@ class Data:
                self.stamp = 0
                self.outfile = ''
                self.kerror = False
-               self.battery = 0
-               self.wifi = 0
+               self.wifi = dict()
                self.turbostat = 0
-               self.mcelog = 0
                self.enterfail = ''
                self.currphase = ''
                self.pstl = dict()    # process timeline
@@ -1308,6 +1393,8 @@ class Data:
                                continue
                        dir = 'suspend' if t < self.tSuspended else 'resume'
                        msg = m.group('msg')
+                       if re.match('capability: warning: .*', msg):
+                               continue
                        for err in self.errlist:
                                if re.match(self.errlist[err], msg):
                                        list.append((msg, err, dir, t, i, i))
@@ -1316,17 +1403,26 @@ class Data:
                msglist = []
                for msg, type, dir, t, idx1, idx2 in list:
                        msglist.append(msg)
-                       sysvals.vprint('kernel %s found in %s at %f' % (type, dir, t))
                        self.errorinfo[dir].append((type, t, idx1, idx2))
                if self.kerror:
                        sysvals.dmesglog = True
                if len(self.dmesgtext) < 1 and sysvals.dmesgfile:
                        lf.close()
                return msglist
-       def setStart(self, time):
+       def setStart(self, time, msg=''):
                self.start = time
-       def setEnd(self, time):
+               if msg:
+                       try:
+                               self.hwstart = datetime.strptime(msg, sysvals.tmstart)
+                       except:
+                               self.hwstart = 0
+       def setEnd(self, time, msg=''):
                self.end = time
+               if msg:
+                       try:
+                               self.hwend = datetime.strptime(msg, sysvals.tmend)
+                       except:
+                               self.hwend = 0
        def isTraceEventOutsideDeviceCalls(self, pid, time):
                for phase in self.sortedPhases():
                        list = self.dmesg[phase]['list']
@@ -1546,6 +1642,14 @@ class Data:
                                        self.trimTime(tS, tL, left)
                                        self.tLow.append('%.0f'%(tL*1000))
                        lp = phase
+       def getMemTime(self):
+               if not self.hwstart or not self.hwend:
+                       return
+               stime = (self.tSuspended - self.start) * 1000000
+               rtime = (self.end - self.tResumed) * 1000000
+               hws = self.hwstart + timedelta(microseconds=stime)
+               hwr = self.hwend - timedelta(microseconds=rtime)
+               self.tLow.append('%.0f'%((hwr - hws).total_seconds() * 1000))
        def getTimeValues(self):
                sktime = (self.tSuspended - self.tKernSus) * 1000
                rktime = (self.tKernRes - self.tResumed) * 1000
@@ -1883,9 +1987,9 @@ class Data:
                        c = self.addProcessUsageEvent(ps, tres)
                        if c > 0:
                                sysvals.vprint('%25s (res): %d' % (ps, c))
-       def handleEndMarker(self, time):
+       def handleEndMarker(self, time, msg=''):
                dm = self.dmesg
-               self.setEnd(time)
+               self.setEnd(time, msg)
                self.initDevicegroups()
                # give suspend_prepare an end if needed
                if 'suspend_prepare' in dm and dm['suspend_prepare']['end'] < 0:
@@ -2071,7 +2175,7 @@ class FTraceLine:
                if not self.fevent:
                        return False
                if sysvals.usetracemarkers:
-                       if(self.name == 'SUSPEND START'):
+                       if(self.name.startswith('SUSPEND START')):
                                return True
                        return False
                else:
@@ -2084,7 +2188,7 @@ class FTraceLine:
                if not self.fevent:
                        return False
                if sysvals.usetracemarkers:
-                       if(self.name == 'RESUME COMPLETE'):
+                       if(self.name.startswith('RESUME COMPLETE')):
                                return True
                        return False
                else:
@@ -2444,7 +2548,7 @@ class Timeline:
        def createHeader(self, sv, stamp):
                if(not stamp['time']):
                        return
-               self.html += '<div class="version"><a href="https://01.org/suspendresume">%s v%s</a></div>' \
+               self.html += '<div class="version"><a href="https://01.org/pm-graph">%s v%s</a></div>' \
                        % (sv.title, sv.version)
                if sv.logmsg and sv.testlog:
                        self.html += '<button id="showtest" class="logbtn btnfmt">log</button>'
@@ -2670,14 +2774,11 @@ class TestProps:
        stampfmt = '# [a-z]*-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\
                                '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\
                                ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$'
-       batteryfmt = '^# battery (?P<a1>\w*) (?P<c1>\d*) (?P<a2>\w*) (?P<c2>\d*)'
-       wififmt    = '^# wifi (?P<w>.*)'
+       wififmt    = '^# wifi *(?P<d>\S*) *(?P<s>\S*) *(?P<t>[0-9\.]+).*'
        tstatfmt   = '^# turbostat (?P<t>\S*)'
-       mcelogfmt  = '^# mcelog (?P<m>\S*)'
        testerrfmt = '^# enter_sleep_error (?P<e>.*)'
        sysinfofmt = '^# sysinfo .*'
        cmdlinefmt = '^# command \| (?P<cmd>.*)'
-       kparamsfmt = '^# kparams \| (?P<kp>.*)'
        devpropfmt = '# Device Properties: .*'
        pinfofmt   = '# platform-(?P<val>[a-z,A-Z,0-9]*): (?P<info>.*)'
        tracertypefmt = '# tracer: (?P<t>.*)'
@@ -2695,11 +2796,8 @@ class TestProps:
                self.stamp = ''
                self.sysinfo = ''
                self.cmdline = ''
-               self.kparams = ''
                self.testerror = []
-               self.mcelog = []
                self.turbostat = []
-               self.battery = []
                self.wifi = []
                self.fwdata = []
                self.ftrace_line_fmt = self.ftrace_line_fmt_nop
@@ -2721,21 +2819,12 @@ class TestProps:
                elif re.match(self.sysinfofmt, line):
                        self.sysinfo = line
                        return True
-               elif re.match(self.kparamsfmt, line):
-                       self.kparams = line
-                       return True
                elif re.match(self.cmdlinefmt, line):
                        self.cmdline = line
                        return True
-               elif re.match(self.mcelogfmt, line):
-                       self.mcelog.append(line)
-                       return True
                elif re.match(self.tstatfmt, line):
                        self.turbostat.append(line)
                        return True
-               elif re.match(self.batteryfmt, line):
-                       self.battery.append(line)
-                       return True
                elif re.match(self.wififmt, line):
                        self.wifi.append(line)
                        return True
@@ -2749,6 +2838,8 @@ class TestProps:
        def parseStamp(self, data, sv):
                # global test data
                m = re.match(self.stampfmt, self.stamp)
+               if not self.stamp or not m:
+                       doError('data does not include the expected stamp')
                data.stamp = {'time': '', 'host': '', 'mode': ''}
                dt = datetime(int(m.group('y'))+2000, int(m.group('m')),
                        int(m.group('d')), int(m.group('H')), int(m.group('M')),
@@ -2780,10 +2871,6 @@ class TestProps:
                m = re.match(self.cmdlinefmt, self.cmdline)
                if m:
                        sv.cmdline = m.group('cmd')
-               if self.kparams:
-                       m = re.match(self.kparamsfmt, self.kparams)
-                       if m:
-                               sv.kparams = m.group('kp')
                if not sv.stamp:
                        sv.stamp = data.stamp
                # firmware data
@@ -2793,26 +2880,18 @@ class TestProps:
                                data.fwSuspend, data.fwResume = int(m.group('s')), int(m.group('r'))
                                if(data.fwSuspend > 0 or data.fwResume > 0):
                                        data.fwValid = True
-               # mcelog data
-               if len(self.mcelog) > data.testnumber:
-                       m = re.match(self.mcelogfmt, self.mcelog[data.testnumber])
-                       if m:
-                               data.mcelog = sv.b64unzip(m.group('m'))
                # turbostat data
                if len(self.turbostat) > data.testnumber:
                        m = re.match(self.tstatfmt, self.turbostat[data.testnumber])
                        if m:
                                data.turbostat = m.group('t')
-               # battery data
-               if len(self.battery) > data.testnumber:
-                       m = re.match(self.batteryfmt, self.battery[data.testnumber])
-                       if m:
-                               data.battery = m.groups()
                # wifi data
                if len(self.wifi) > data.testnumber:
                        m = re.match(self.wififmt, self.wifi[data.testnumber])
                        if m:
-                               data.wifi = m.group('w')
+                               data.wifi = {'dev': m.group('d'), 'stat': m.group('s'),
+                                       'time': float(m.group('t'))}
+                               data.stamp['wifi'] = m.group('d')
                # sleep mode enter errors
                if len(self.testerror) > data.testnumber:
                        m = re.match(self.testerrfmt, self.testerror[data.testnumber])
@@ -3012,13 +3091,13 @@ def appendIncompleteTraceLog(testruns):
                if(t.startMarker()):
                        data = testrun[testidx].data
                        tp.parseStamp(data, sysvals)
-                       data.setStart(t.time)
+                       data.setStart(t.time, t.name)
                        continue
                if(not data):
                        continue
                # find the end of resume
                if(t.endMarker()):
-                       data.setEnd(t.time)
+                       data.setEnd(t.time, t.name)
                        testidx += 1
                        if(testidx >= testcnt):
                                break
@@ -3081,7 +3160,7 @@ def parseTraceLog(live=False):
                doError('%s does not exist' % sysvals.ftracefile)
        if not live:
                sysvals.setupAllKprobes()
-       ksuscalls = ['pm_prepare_console']
+       ksuscalls = ['ksys_sync', 'pm_prepare_console']
        krescalls = ['pm_restore_console']
        tracewatch = ['irq_wakeup']
        if sysvals.usekprobes:
@@ -3094,7 +3173,7 @@ def parseTraceLog(live=False):
        testruns = []
        testdata = []
        testrun = 0
-       data = 0
+       data, limbo = 0, True
        tf = sysvals.openlog(sysvals.ftracefile, 'r')
        phase = 'suspend_prepare'
        for line in tf:
@@ -3141,16 +3220,16 @@ def parseTraceLog(live=False):
                        continue
                # find the start of suspend
                if(t.startMarker()):
-                       data = Data(len(testdata))
+                       data, limbo = Data(len(testdata)), False
                        testdata.append(data)
                        testrun = TestRun(data)
                        testruns.append(testrun)
                        tp.parseStamp(data, sysvals)
-                       data.setStart(t.time)
+                       data.setStart(t.time, t.name)
                        data.first_suspend_prepare = True
                        phase = data.setPhase('suspend_prepare', t.time, True)
                        continue
-               if(not data):
+               if(not data or limbo):
                        continue
                # process cpu exec line
                if t.type == 'tracing_mark_write':
@@ -3167,14 +3246,16 @@ def parseTraceLog(live=False):
                                continue
                # find the end of resume
                if(t.endMarker()):
-                       data.handleEndMarker(t.time)
+                       if data.tKernRes == 0:
+                               data.tKernRes = t.time
+                       data.handleEndMarker(t.time, t.name)
                        if(not sysvals.usetracemarkers):
                                # no trace markers? then quit and be sure to finish recording
                                # the event we used to trigger resume end
                                if('thaw_processes' in testrun.ttemp and len(testrun.ttemp['thaw_processes']) > 0):
                                        # if an entry exists, assume this is its end
                                        testrun.ttemp['thaw_processes'][-1]['end'] = t.time
-                               break
+                       limbo = True
                        continue
                # trace event processing
                if(t.fevent):
@@ -3197,7 +3278,7 @@ def parseTraceLog(live=False):
                                # -- phase changes --
                                # start of kernel suspend
                                if(re.match('suspend_enter\[.*', t.name)):
-                                       if(isbegin):
+                                       if(isbegin and data.tKernSus == 0):
                                                data.tKernSus = t.time
                                        continue
                                # suspend_prepare start
@@ -3225,7 +3306,7 @@ def parseTraceLog(live=False):
                                elif(re.match('machine_suspend\[.*', t.name)):
                                        if(isbegin):
                                                lp = data.lastPhase()
-                                               if lp == 'resume_machine':
+                                               if lp.startswith('resume_machine'):
                                                        data.dmesg[lp]['end'] = t.time
                                                phase = data.setPhase('suspend_machine', data.dmesg[lp]['end'], True)
                                                data.setPhase(phase, t.time, False)
@@ -3320,7 +3401,8 @@ def parseTraceLog(live=False):
                                        'proc': m_proc,
                                })
                                # start of kernel resume
-                               if(phase == 'suspend_prepare' and kprobename in ksuscalls):
+                               if(data.tKernSus == 0 and phase == 'suspend_prepare' \
+                                       and kprobename in ksuscalls):
                                        data.tKernSus = t.time
                        elif(t.freturn):
                                if(key not in tp.ktemp) or len(tp.ktemp[key]) < 1:
@@ -3355,7 +3437,7 @@ def parseTraceLog(live=False):
                sysvals.vprint('WARNING: ftrace start marker is missing')
        if data and not data.devicegroups:
                sysvals.vprint('WARNING: ftrace end marker is missing')
-               data.handleEndMarker(t.time)
+               data.handleEndMarker(t.time, t.name)
 
        if sysvals.suspendmode == 'command':
                for test in testruns:
@@ -3476,6 +3558,10 @@ def parseTraceLog(live=False):
                                        data.fwValid = False
                                sysvals.vprint('WARNING: phase "%s" is missing!' % p)
                        lp = p
+               if not terr and 'dev' in data.wifi and data.wifi['stat'] == 'timeout':
+                       terr = '%s%s failed in wifi_resume <i>(%s %.0fs timeout)</i>' % \
+                               (sysvals.suspendmode, tn, data.wifi['dev'], data.wifi['time'])
+                       error.append(terr)
                if not terr and data.enterfail:
                        pprint('test%s FAILED: enter %s failed with %s' % (tn, sysvals.suspendmode, data.enterfail))
                        terr = 'test%s failed to enter %s mode' % (tn, sysvals.suspendmode)
@@ -3933,7 +4019,7 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
        tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [dict(), dict()]
        iMin, iMed, iMax = [0, 0], [0, 0], [0, 0]
        num = 0
-       useturbo = False
+       useturbo = usewifi = False
        lastmode = ''
        cnt = dict()
        for data in sorted(testruns, key=lambda v:(v['mode'], v['host'], v['kernel'], v['time'])):
@@ -3952,17 +4038,17 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
                        tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [dict(), dict()]
                        iMin, iMed, iMax = [0, 0], [0, 0], [0, 0]
                        num = 0
-               pkgpc10 = syslpi = ''
+               pkgpc10 = syslpi = wifi = ''
                if 'pkgpc10' in data and 'syslpi' in data:
-                       pkgpc10 = data['pkgpc10']
-                       syslpi = data['syslpi']
-                       useturbo = True
+                       pkgpc10, syslpi, useturbo = data['pkgpc10'], data['syslpi'], True
+               if 'wifi' in data:
+                       wifi, usewifi = data['wifi'], True
                res = data['result']
                tVal = [float(data['suspend']), float(data['resume'])]
                list[mode]['data'].append([data['host'], data['kernel'],
                        data['time'], tVal[0], tVal[1], data['url'], res,
                        data['issues'], data['sus_worst'], data['sus_worsttime'],
-                       data['res_worst'], data['res_worsttime'], pkgpc10, syslpi])
+                       data['res_worst'], data['res_worsttime'], pkgpc10, syslpi, wifi])
                idx = len(list[mode]['data']) - 1
                if res.startswith('fail in'):
                        res = 'fail'
@@ -4002,7 +4088,12 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
        td = '\t<td>{0}</td>\n'
        tdh = '\t<td{1}>{0}</td>\n'
        tdlink = '\t<td><a href="{0}">html</a></td>\n'
-       colspan = '14' if useturbo else '12'
+       cols = 12
+       if useturbo:
+               cols += 2
+       if usewifi:
+               cols += 1
+       colspan = '%d' % cols
 
        # table header
        html += '<table>\n<tr>\n' + th.format('#') +\
@@ -4013,6 +4104,8 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
                th.format('Worst Resume Device') + th.format('RD Time')
        if useturbo:
                html += th.format('PkgPC10') + th.format('SysLPI')
+       if usewifi:
+               html += th.format('Wifi')
        html += th.format('Detail')+'</tr>\n'
        # export list into html
        head = '<tr class="head"><td>{0}</td><td>{1}</td>'+\
@@ -4076,6 +4169,8 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
                        if useturbo:
                                html += td.format(d[12])                                                                # pkg_pc10
                                html += td.format(d[13])                                                                # syslpi
+                       if usewifi:
+                               html += td.format(d[14])                                                                # wifi
                        html += tdlink.format(d[5]) if d[5] else td.format('')          # url
                        html += '</tr>\n'
                        num += 1
@@ -4224,6 +4319,8 @@ def createHTML(testruns, testfail):
                        kerror = True
                if(sysvals.suspendmode in ['freeze', 'standby']):
                        data.trimFreezeTime(testruns[-1].tSuspended)
+               else:
+                       data.getMemTime()
 
        # html function templates
        html_error = '<div id="{1}" title="kernel error/warning" class="err" style="right:{0}%">{2}&rarr;</div>\n'
@@ -4242,13 +4339,10 @@ def createHTML(testruns, testfail):
                '<td class="green">Execution Time: <b>{0} ms</b></td>'\
                '<td class="yellow">Command: <b>{1}</b></td>'\
                '</tr>\n</table>\n'
-       html_timegroups = '<table class="time2">\n<tr>'\
-               '<td class="green" title="time from kernel enter_state({5}) to firmware mode [kernel time only]">{4}Kernel Suspend: {0} ms</td>'\
-               '<td class="purple">{4}Firmware Suspend: {1} ms</td>'\
-               '<td class="purple">{4}Firmware Resume: {2} ms</td>'\
-               '<td class="yellow" title="time from firmware mode to return from kernel enter_state({5}) [kernel time only]">{4}Kernel Resume: {3} ms</td>'\
-               '</tr>\n</table>\n'
        html_fail = '<table class="testfail"><tr><td>{0}</td></tr></table>\n'
+       html_kdesc = '<td class="{3}" title="time spent in kernel execution">{0}Kernel {2}: {1} ms</td>'
+       html_fwdesc = '<td class="{3}" title="time spent in firmware">{0}Firmware {2}: {1} ms</td>'
+       html_wifdesc = '<td class="yellow" title="time for wifi to reconnect after resume complete ({2})">{0}Wifi Resume: {1}</td>'
 
        # html format variables
        scaleH = 20
@@ -4264,13 +4358,10 @@ def createHTML(testruns, testfail):
        # Generate the header for this timeline
        for data in testruns:
                tTotal = data.end - data.start
-               sktime, rktime = data.getTimeValues()
                if(tTotal == 0):
                        doError('No timeline data')
-               if(len(data.tLow) > 0):
-                       low_time = '+'.join(data.tLow)
                if sysvals.suspendmode == 'command':
-                       run_time = '%.0f'%((data.end-data.start)*1000)
+                       run_time = '%.0f' % (tTotal * 1000)
                        if sysvals.testcommand:
                                testdesc = sysvals.testcommand
                        else:
@@ -4279,43 +4370,55 @@ def createHTML(testruns, testfail):
                                testdesc = ordinal(data.testnumber+1)+' '+testdesc
                        thtml = html_timetotal3.format(run_time, testdesc)
                        devtl.html += thtml
-               elif data.fwValid:
-                       suspend_time = '%.0f'%(sktime + (data.fwSuspend/1000000.0))
-                       resume_time = '%.0f'%(rktime + (data.fwResume/1000000.0))
-                       testdesc1 = 'Total'
-                       testdesc2 = ''
-                       stitle = 'time from kernel enter_state(%s) to low-power mode [kernel & firmware time]' % sysvals.suspendmode
-                       rtitle = 'time from low-power mode to return from kernel enter_state(%s) [firmware & kernel time]' % sysvals.suspendmode
-                       if(len(testruns) > 1):
-                               testdesc1 = testdesc2 = ordinal(data.testnumber+1)
-                               testdesc2 += ' '
-                       if(len(data.tLow) == 0):
-                               thtml = html_timetotal.format(suspend_time, \
-                                       resume_time, testdesc1, stitle, rtitle)
-                       else:
-                               thtml = html_timetotal2.format(suspend_time, low_time, \
-                                       resume_time, testdesc1, stitle, rtitle)
-                       devtl.html += thtml
+                       continue
+               # typical full suspend/resume header
+               stot, rtot = sktime, rktime = data.getTimeValues()
+               ssrc, rsrc, testdesc, testdesc2 = ['kernel'], ['kernel'], 'Kernel', ''
+               if data.fwValid:
+                       stot += (data.fwSuspend/1000000.0)
+                       rtot += (data.fwResume/1000000.0)
+                       ssrc.append('firmware')
+                       rsrc.append('firmware')
+                       testdesc = 'Total'
+               if 'time' in data.wifi and data.wifi['stat'] != 'timeout':
+                       rtot += data.end - data.tKernRes + (data.wifi['time'] * 1000.0)
+                       rsrc.append('wifi')
+                       testdesc = 'Total'
+               suspend_time, resume_time = '%.3f' % stot, '%.3f' % rtot
+               stitle = 'time from kernel suspend start to %s mode [%s time]' % \
+                       (sysvals.suspendmode, ' & '.join(ssrc))
+               rtitle = 'time from %s mode to kernel resume complete [%s time]' % \
+                       (sysvals.suspendmode, ' & '.join(rsrc))
+               if(len(testruns) > 1):
+                       testdesc = testdesc2 = ordinal(data.testnumber+1)
+                       testdesc2 += ' '
+               if(len(data.tLow) == 0):
+                       thtml = html_timetotal.format(suspend_time, \
+                               resume_time, testdesc, stitle, rtitle)
+               else:
+                       low_time = '+'.join(data.tLow)
+                       thtml = html_timetotal2.format(suspend_time, low_time, \
+                               resume_time, testdesc, stitle, rtitle)
+               devtl.html += thtml
+               if not data.fwValid and 'dev' not in data.wifi:
+                       continue
+               # extra detail when the times come from multiple sources
+               thtml = '<table class="time2">\n<tr>'
+               thtml += html_kdesc.format(testdesc2, '%.3f'%sktime, 'Suspend', 'green')
+               if data.fwValid:
                        sftime = '%.3f'%(data.fwSuspend / 1000000.0)
                        rftime = '%.3f'%(data.fwResume / 1000000.0)
-                       devtl.html += html_timegroups.format('%.3f'%sktime, \
-                               sftime, rftime, '%.3f'%rktime, testdesc2, sysvals.suspendmode)
-               else:
-                       suspend_time = '%.3f' % sktime
-                       resume_time = '%.3f' % rktime
-                       testdesc = 'Kernel'
-                       stitle = 'time from kernel enter_state(%s) to firmware mode [kernel time only]' % sysvals.suspendmode
-                       rtitle = 'time from firmware mode to return from kernel enter_state(%s) [kernel time only]' % sysvals.suspendmode
-                       if(len(testruns) > 1):
-                               testdesc = ordinal(data.testnumber+1)+' '+testdesc
-                       if(len(data.tLow) == 0):
-                               thtml = html_timetotal.format(suspend_time, \
-                                       resume_time, testdesc, stitle, rtitle)
+                       thtml += html_fwdesc.format(testdesc2, sftime, 'Suspend', 'green')
+                       thtml += html_fwdesc.format(testdesc2, rftime, 'Resume', 'yellow')
+               thtml += html_kdesc.format(testdesc2, '%.3f'%rktime, 'Resume', 'yellow')
+               if 'time' in data.wifi:
+                       if data.wifi['stat'] != 'timeout':
+                               wtime = '%.0f ms'%(data.end - data.tKernRes + (data.wifi['time'] * 1000.0))
                        else:
-                               thtml = html_timetotal2.format(suspend_time, low_time, \
-                                       resume_time, testdesc, stitle, rtitle)
-                       devtl.html += thtml
-
+                               wtime = 'TIMEOUT'
+                       thtml += html_wifdesc.format(testdesc2, wtime, data.wifi['dev'])
+               thtml += '</tr>\n</table>\n'
+               devtl.html += thtml
        if testfail:
                devtl.html += html_fail.format(testfail)
 
@@ -5082,28 +5185,32 @@ def setRuntimeSuspend(before=True):
 # Description:
 #       Execute system suspend through the sysfs interface, then copy the output
 #       dmesg and ftrace files to the test output directory.
-def executeSuspend():
+def executeSuspend(quiet=False):
        pm = ProcessMonitor()
        tp = sysvals.tpath
-       wifi = sysvals.checkWifi()
+       if sysvals.wifi:
+               wifi = sysvals.checkWifi()
        testdata = []
-       battery = True if getBattery() else False
        # run these commands to prepare the system for suspend
        if sysvals.display:
-               pprint('SET DISPLAY TO %s' % sysvals.display.upper())
+               if not quiet:
+                       pprint('SET DISPLAY TO %s' % sysvals.display.upper())
                displayControl(sysvals.display)
                time.sleep(1)
        if sysvals.sync:
-               pprint('SYNCING FILESYSTEMS')
+               if not quiet:
+                       pprint('SYNCING FILESYSTEMS')
                call('sync', shell=True)
        # mark the start point in the kernel ring buffer just as we start
        sysvals.initdmesg()
        # start ftrace
        if(sysvals.usecallgraph or sysvals.usetraceevents):
-               pprint('START TRACING')
+               if not quiet:
+                       pprint('START TRACING')
                sysvals.fsetVal('1', 'tracing_on')
                if sysvals.useprocmon:
                        pm.start()
+       sysvals.cmdinfo(True)
        # execute however many s/r runs requested
        for count in range(1,sysvals.execcount+1):
                # x2delay in between test runs
@@ -5119,15 +5226,14 @@ def executeSuspend():
                                pprint('SUSPEND START')
                        else:
                                pprint('SUSPEND START (press a key to resume)')
-               sysvals.mcelog(True)
-               bat1 = getBattery() if battery else False
                # set rtcwake
                if(sysvals.rtcwake):
-                       pprint('will issue an rtcwake in %d seconds' % sysvals.rtcwaketime)
+                       if not quiet:
+                               pprint('will issue an rtcwake in %d seconds' % sysvals.rtcwaketime)
                        sysvals.rtcWakeAlarmOn()
                # start of suspend trace marker
                if(sysvals.usecallgraph or sysvals.usetraceevents):
-                       sysvals.fsetVal('SUSPEND START', 'trace_marker')
+                       sysvals.fsetVal(datetime.now().strftime(sysvals.tmstart), 'trace_marker')
                # predelay delay
                if(count == 1 and sysvals.predelay > 0):
                        sysvals.fsetVal('WAIT %d' % sysvals.predelay, 'trace_marker')
@@ -5174,37 +5280,33 @@ def executeSuspend():
                # return from suspend
                pprint('RESUME COMPLETE')
                if(sysvals.usecallgraph or sysvals.usetraceevents):
-                       sysvals.fsetVal('RESUME COMPLETE', 'trace_marker')
+                       sysvals.fsetVal(datetime.now().strftime(sysvals.tmend), 'trace_marker')
+               if sysvals.wifi and wifi:
+                       tdata['wifi'] = sysvals.pollWifi(wifi)
                if(sysvals.suspendmode == 'mem' or sysvals.suspendmode == 'command'):
                        tdata['fw'] = getFPDT(False)
-               mcelog = sysvals.mcelog()
-               if mcelog:
-                       tdata['mcelog'] = mcelog
-               bat2 = getBattery() if battery else False
-               if battery and bat1 and bat2:
-                       tdata['bat'] = (bat1, bat2)
-               if 'device' in wifi and 'ip' in wifi:
-                       tdata['wifi'] = (wifi, sysvals.checkWifi())
                testdata.append(tdata)
+       cmdafter = sysvals.cmdinfo(False)
        # stop ftrace
        if(sysvals.usecallgraph or sysvals.usetraceevents):
                if sysvals.useprocmon:
                        pm.stop()
                sysvals.fsetVal('0', 'tracing_on')
        # grab a copy of the dmesg output
-       pprint('CAPTURING DMESG')
+       if not quiet:
+               pprint('CAPTURING DMESG')
        sysvals.getdmesg(testdata)
        # grab a copy of the ftrace output
        if(sysvals.usecallgraph or sysvals.usetraceevents):
-               pprint('CAPTURING TRACE')
+               if not quiet:
+                       pprint('CAPTURING TRACE')
                op = sysvals.writeDatafileHeader(sysvals.ftracefile, testdata)
                fp = open(tp+'trace', 'r')
                for line in fp:
                        op.write(line)
                op.close()
                sysvals.fsetVal('', 'trace')
-               sysvals.platforminfo()
-       return testdata
+               sysvals.platforminfo(cmdafter)
 
 def readFile(file):
        if os.path.islink(file):
@@ -5447,25 +5549,6 @@ def dmidecode(mempath, fatal=False):
                count += 1
        return out
 
-def getBattery():
-       p, charge, bat = '/sys/class/power_supply', 0, {}
-       if not os.path.exists(p):
-               return False
-       for d in os.listdir(p):
-               type = sysvals.getVal(os.path.join(p, d, 'type')).strip().lower()
-               if type != 'battery':
-                       continue
-               for v in ['status', 'energy_now', 'capacity_now']:
-                       bat[v] = sysvals.getVal(os.path.join(p, d, v)).strip().lower()
-               break
-       if 'status' not in bat:
-               return False
-       ac = False if 'discharging' in bat['status'] else True
-       for v in ['energy_now', 'capacity_now']:
-               if v in bat and bat[v]:
-                       charge = int(bat[v])
-       return (ac, charge)
-
 def displayControl(cmd):
        xset, ret = 'timeout 10 xset -d :0.0 {0}', 0
        if sysvals.sudouser:
@@ -5715,6 +5798,17 @@ def statusCheck(probecheck=False):
                status = 'rtcwake is not properly supported'
        pprint('    is rtcwake supported: %s' % res)
 
+       # check info commands
+       pprint('    optional commands this tool may use for info:')
+       no = sysvals.colorText('MISSING')
+       yes = sysvals.colorText('FOUND', 32)
+       for c in ['turbostat', 'mcelog', 'lspci', 'lsusb']:
+               if c == 'turbostat':
+                       res = yes if sysvals.haveTurbostat() else no
+               else:
+                       res = yes if sysvals.getExec(c) else no
+               pprint('        %s: %s' % (c, res))
+
        if not probecheck:
                return status
 
@@ -5780,8 +5874,9 @@ def getArgFloat(name, args, min, max, main=True):
                doError(name+': value should be between %f and %f' % (min, max), True)
        return val
 
-def processData(live=False):
-       pprint('PROCESSING DATA')
+def processData(live=False, quiet=False):
+       if not quiet:
+               pprint('PROCESSING DATA')
        sysvals.vprint('usetraceevents=%s, usetracemarkers=%s, usekprobes=%s' % \
                (sysvals.usetraceevents, sysvals.usetracemarkers, sysvals.usekprobes))
        error = ''
@@ -5796,20 +5891,17 @@ def processData(live=False):
                        parseKernelLog(data)
                if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)):
                        appendIncompleteTraceLog(testruns)
+       if not sysvals.stamp:
+               pprint('ERROR: data does not include the expected stamp')
+               return (testruns, {'error': 'timeline generation failed'})
        shown = ['bios', 'biosdate', 'cpu', 'host', 'kernel', 'man', 'memfr',
-                       'memsz', 'mode', 'numcpu', 'plat', 'time']
+                       'memsz', 'mode', 'numcpu', 'plat', 'time', 'wifi']
        sysvals.vprint('System Info:')
        for key in sorted(sysvals.stamp):
                if key in shown:
                        sysvals.vprint('    %-8s : %s' % (key.upper(), sysvals.stamp[key]))
-       if sysvals.kparams:
-               sysvals.vprint('Kparams:\n    %s' % sysvals.kparams)
        sysvals.vprint('Command:\n    %s' % sysvals.cmdline)
        for data in testruns:
-               if data.mcelog:
-                       sysvals.vprint('MCELOG Data:')
-                       for line in data.mcelog.split('\n'):
-                               sysvals.vprint('    %s' % line)
                if data.turbostat:
                        idx, s = 0, 'Turbostat:\n    '
                        for val in data.turbostat.split('|'):
@@ -5819,23 +5911,13 @@ def processData(live=False):
                                        s += '\n    '
                                s += val + ' '
                        sysvals.vprint(s)
-               if data.battery:
-                       a1, c1, a2, c2 = data.battery
-                       s = 'Battery:\n    Before - AC: %s, Charge: %d\n     After - AC: %s, Charge: %d' % \
-                               (a1, int(c1), a2, int(c2))
-                       sysvals.vprint(s)
-               if data.wifi:
-                       w = data.wifi.replace('|', ' ').split(',')
-                       s = 'Wifi:\n    Before %s\n     After %s' % \
-                               (w[0], w[1])
-                       sysvals.vprint(s)
                data.printDetails()
-               if len(sysvals.platinfo) > 0:
-                       sysvals.vprint('\nPlatform Info:')
-                       for info in sysvals.platinfo:
-                               sysvals.vprint(info[0]+' - '+info[1])
-                               sysvals.vprint(info[2])
-                       sysvals.vprint('')
+       if len(sysvals.platinfo) > 0:
+               sysvals.vprint('\nPlatform Info:')
+               for info in sysvals.platinfo:
+                       sysvals.vprint('[%s - %s]' % (info[0], info[1]))
+                       sysvals.vprint(info[2])
+               sysvals.vprint('')
        if sysvals.cgdump:
                for data in testruns:
                        data.debugPrint()
@@ -5845,7 +5927,8 @@ def processData(live=False):
                return (testruns, {'error': 'timeline generation failed'})
        sysvals.vprint('Creating the html timeline (%s)...' % sysvals.htmlfile)
        createHTML(testruns, error)
-       pprint('DONE')
+       if not quiet:
+               pprint('DONE')
        data = testruns[0]
        stamp = data.stamp
        stamp['suspend'], stamp['resume'] = data.getTimeValues()
@@ -5872,31 +5955,28 @@ def rerunTest(htmlfile=''):
                        doError('a directory already exists with this name: %s' % sysvals.htmlfile)
                elif not os.access(sysvals.htmlfile, os.W_OK):
                        doError('missing permission to write to %s' % sysvals.htmlfile)
-       testruns, stamp = processData(False)
-       sysvals.logmsg = ''
+       testruns, stamp = processData()
+       sysvals.resetlog()
        return stamp
 
 # Function: runTest
 # Description:
 #       execute a suspend/resume, gather the logs, and generate the output
-def runTest(n=0):
+def runTest(n=0, quiet=False):
        # prepare for the test
-       sysvals.initFtrace()
+       sysvals.initFtrace(quiet)
        sysvals.initTestOutput('suspend')
 
        # execute the test
-       testdata = executeSuspend()
+       executeSuspend(quiet)
        sysvals.cleanupFtrace()
        if sysvals.skiphtml:
+               sysvals.outputResult({}, n)
                sysvals.sudoUserchown(sysvals.testdir)
                return
-       if not testdata[0]['error']:
-               testruns, stamp = processData(True)
-               for data in testruns:
-                       del data
-       else:
-               stamp = testdata[0]
-
+       testruns, stamp = processData(True, quiet)
+       for data in testruns:
+               del data
        sysvals.sudoUserchown(sysvals.testdir)
        sysvals.outputResult(stamp, n)
        if 'error' in stamp:
@@ -5904,13 +5984,14 @@ def runTest(n=0):
        return 0
 
 def find_in_html(html, start, end, firstonly=True):
-       n, out = 0, []
-       while n < len(html):
-               m = re.search(start, html[n:])
+       n, cnt, out = 0, len(html), []
+       while n < cnt:
+               e = cnt if (n + 10000 > cnt or n == 0) else n + 10000
+               m = re.search(start, html[n:e])
                if not m:
                        break
                i = m.end()
-               m = re.search(end, html[n+i:])
+               m = re.search(end, html[n+i:e])
                if not m:
                        break
                j = m.start()
@@ -5945,7 +6026,7 @@ def data_from_html(file, outpath, issues, fulldetail=False):
        tstr = dt.strftime('%Y/%m/%d %H:%M:%S')
        error = find_in_html(html, '<table class="testfail"><tr><td>', '</td>')
        if error:
-               m = re.match('[a-z]* failed in (?P<p>[a-z0-9_]*) phase', error)
+               m = re.match('[a-z0-9]* failed in (?P<p>\S*).*', error)
                if m:
                        result = 'fail in %s' % m.group('p')
                else:
@@ -5974,6 +6055,9 @@ def data_from_html(file, outpath, issues, fulldetail=False):
                                elist[err[0]] += 1
                for i in elist:
                        ilist.append('%sx%d' % (i, elist[i]) if elist[i] > 1 else i)
+       wifi = find_in_html(html, 'Wifi Resume: ', '</td>')
+       if wifi:
+               extra['wifi'] = wifi
        low = find_in_html(html, 'freeze time: <b>', ' ms</b>')
        if low and '|' in low:
                issue = 'FREEZEx%d' % len(low.split('|'))
@@ -6048,13 +6132,15 @@ def genHtml(subdir, force=False):
        for dirname, dirnames, filenames in os.walk(subdir):
                sysvals.dmesgfile = sysvals.ftracefile = sysvals.htmlfile = ''
                for filename in filenames:
-                       if(re.match('.*_dmesg.txt', filename)):
-                               sysvals.dmesgfile = os.path.join(dirname, filename)
-                       elif(re.match('.*_ftrace.txt', filename)):
-                               sysvals.ftracefile = os.path.join(dirname, filename)
+                       file = os.path.join(dirname, filename)
+                       if sysvals.usable(file):
+                               if(re.match('.*_dmesg.txt', filename)):
+                                       sysvals.dmesgfile = file
+                               elif(re.match('.*_ftrace.txt', filename)):
+                                       sysvals.ftracefile = file
                sysvals.setOutputFile()
-               if sysvals.ftracefile and sysvals.htmlfile and \
-                       (force or not os.path.exists(sysvals.htmlfile)):
+               if (sysvals.dmesgfile or sysvals.ftracefile) and sysvals.htmlfile and \
+                       (force or not sysvals.usable(sysvals.htmlfile)):
                        pprint('FTRACE: %s' % sysvals.ftracefile)
                        if sysvals.dmesgfile:
                                pprint('DMESG : %s' % sysvals.dmesgfile)
@@ -6169,9 +6255,9 @@ def configFromFile(file):
                                sysvals.cgtest = getArgInt('cgtest', value, 0, 1, False)
                        elif(option == 'cgphase'):
                                d = Data(0)
-                               if value not in d.sortedPhases():
+                               if value not in d.phasedef:
                                        doError('invalid phase --> (%s: %s), valid phases are %s'\
-                                               % (option, value, d.sortedPhases()), True)
+                                               % (option, value, d.phasedef.keys()), True)
                                sysvals.cgphase = value
                        elif(option == 'fadd'):
                                file = sysvals.configFile(value)
@@ -6184,9 +6270,7 @@ def configFromFile(file):
                                nums = value.split()
                                if len(nums) != 2:
                                        doError('multi requires 2 integers (exec_count and delay)', True)
-                               sysvals.multitest['run'] = True
-                               sysvals.multitest['count'] = getArgInt('multi: n d (exec count)', nums[0], 2, 1000000, False)
-                               sysvals.multitest['delay'] = getArgInt('multi: n d (delay between tests)', nums[1], 0, 3600, False)
+                               sysvals.multiinit(nums[0], nums[1])
                        elif(option == 'devicefilter'):
                                sysvals.setDeviceFilter(value)
                        elif(option == 'expandcg'):
@@ -6342,6 +6426,7 @@ def printHelp():
        '   -srgap       Add a visible gap in the timeline between sus/res (default: disabled)\n'\
        '   -skiphtml    Run the test and capture the trace logs, but skip the timeline (default: disabled)\n'\
        '   -result fn   Export a results table to a text file for parsing.\n'\
+       '   -wifi        If a wifi connection is available, check that it reconnects after resume.\n'\
        '  [testprep]\n'\
        '   -sync        Sync the filesystems before starting the test\n'\
        '   -rs on/off   Enable/disable runtime suspend for all devices, restore all after test\n'\
@@ -6356,8 +6441,10 @@ def printHelp():
        '   -predelay t  Include t ms delay before 1st suspend (default: 0 ms)\n'\
        '   -postdelay t Include t ms delay after last resume (default: 0 ms)\n'\
        '   -mindev ms   Discard all device blocks shorter than ms milliseconds (e.g. 0.001 for us)\n'\
-       '   -multi n d   Execute <n> consecutive tests at <d> seconds intervals. The outputs will\n'\
-       '                be created in a new subdirectory with a summary page.\n'\
+       '   -multi n d   Execute <n> consecutive tests at <d> seconds intervals. If <n> is followed\n'\
+       '                by a "d", "h", or "m" execute for <n> days, hours, or mins instead.\n'\
+       '                The outputs will be created in a new subdirectory with a summary page.\n'\
+       '   -maxfail n   Abort a -multi run after n consecutive fails (default is 0 = never abort)\n'\
        '  [debug]\n'\
        '   -f           Use ftrace to create device callgraphs (default: disabled)\n'\
        '   -ftop        Use ftrace on the top level call: "%s" (default: disabled)\n'\
@@ -6379,11 +6466,11 @@ def printHelp():
        '   -modes       List available suspend modes\n'\
        '   -status      Test to see if the system is enabled to run this tool\n'\
        '   -fpdt        Print out the contents of the ACPI Firmware Performance Data Table\n'\
-       '   -battery     Print out battery info (if available)\n'\
-       '   -wifi        Print out wifi connection info (if wireless-tools and device exists)\n'\
+       '   -wificheck   Print out wifi connection info\n'\
        '   -x<mode>     Test xset by toggling the given mode (on/off/standby/suspend)\n'\
        '   -sysinfo     Print out system info extracted from BIOS\n'\
        '   -devinfo     Print out the pm settings of all devices which support runtime suspend\n'\
+       '   -cmdinfo     Print out all the platform info collected before and after suspend/resume\n'\
        '   -flist       Print the list of functions currently being captured in ftrace\n'\
        '   -flistall    Print all functions capable of being captured in ftrace\n'\
        '   -summary dir Create a summary of tests in this dir [-genhtml builds missing html]\n'\
@@ -6399,8 +6486,8 @@ if __name__ == '__main__':
        genhtml = False
        cmd = ''
        simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall',
-               '-devinfo', '-status', '-battery', '-xon', '-xoff', '-xstandby',
-               '-xsuspend', '-xinit', '-xreset', '-xstat', '-wifi']
+               '-devinfo', '-status', '-xon', '-xoff', '-xstandby', '-xsuspend',
+               '-xinit', '-xreset', '-xstat', '-wificheck', '-cmdinfo']
        if '-f' in sys.argv:
                sysvals.cgskip = sysvals.configFile('cgskip.txt')
        # loop through the command line arguments
@@ -6462,8 +6549,15 @@ if __name__ == '__main__':
                        sysvals.usedevsrc = True
                elif(arg == '-sync'):
                        sysvals.sync = True
+               elif(arg == '-wifi'):
+                       sysvals.wifi = True
                elif(arg == '-gzip'):
                        sysvals.gzip = True
+               elif(arg == '-info'):
+                       try:
+                               val = next(args)
+                       except:
+                               doError('-info requires one string argument', True)
                elif(arg == '-rs'):
                        try:
                                val = next(args)
@@ -6555,10 +6649,14 @@ if __name__ == '__main__':
                        sysvals.cgexp = True
                elif(arg == '-srgap'):
                        sysvals.srgap = 5
+               elif(arg == '-maxfail'):
+                       sysvals.maxfail = getArgInt('-maxfail', args, 0, 1000000)
                elif(arg == '-multi'):
-                       sysvals.multitest['run'] = True
-                       sysvals.multitest['count'] = getArgInt('-multi n d (exec count)', args, 2, 1000000)
-                       sysvals.multitest['delay'] = getArgInt('-multi n d (delay between tests)', args, 0, 3600)
+                       try:
+                               c, d = next(args), next(args)
+                       except:
+                               doError('-multi requires two values', True)
+                       sysvals.multiinit(c, d)
                elif(arg == '-o'):
                        try:
                                val = next(args)
@@ -6655,13 +6753,6 @@ if __name__ == '__main__':
                elif(cmd == 'fpdt'):
                        if not getFPDT(True):
                                ret = 1
-               elif(cmd == 'battery'):
-                       out = getBattery()
-                       if out:
-                               pprint('AC Connect    : %s\nBattery Charge: %d' % out)
-                       else:
-                               pprint('no battery found')
-                               ret = 1
                elif(cmd == 'sysinfo'):
                        sysvals.printSystemInfo(True)
                elif(cmd == 'devinfo'):
@@ -6679,13 +6770,15 @@ if __name__ == '__main__':
                        ret = displayControl(cmd[1:])
                elif(cmd == 'xstat'):
                        pprint('Display Status: %s' % displayControl('stat').upper())
-               elif(cmd == 'wifi'):
-                       out = sysvals.checkWifi()
-                       if 'device' not in out:
-                               pprint('WIFI interface not found')
+               elif(cmd == 'wificheck'):
+                       dev = sysvals.checkWifi()
+                       if dev:
+                               print('%s is connected' % sysvals.wifiDetails(dev))
                        else:
-                               for key in sorted(out):
-                                       pprint('%6s: %s' % (key.upper(), out[key]))
+                               print('No wifi connection found')
+               elif(cmd == 'cmdinfo'):
+                       for out in sysvals.cmdinfo(False, True):
+                               print('[%s - %s]\n%s\n' % out)
                sys.exit(ret)
 
        # if instructed, re-analyze existing data files
@@ -6720,24 +6813,38 @@ if __name__ == '__main__':
        setRuntimeSuspend(True)
        if sysvals.display:
                displayControl('init')
-       ret = 0
+       failcnt, ret = 0, 0
        if sysvals.multitest['run']:
                # run multiple tests in a separate subdirectory
                if not sysvals.outdir:
-                       s = 'suspend-x%d' % sysvals.multitest['count']
-                       sysvals.outdir = datetime.now().strftime(s+'-%y%m%d-%H%M%S')
+                       if 'time' in sysvals.multitest:
+                               s = '-%dm' % sysvals.multitest['time']
+                       else:
+                               s = '-x%d' % sysvals.multitest['count']
+                       sysvals.outdir = datetime.now().strftime('suspend-%y%m%d-%H%M%S'+s)
                if not os.path.isdir(sysvals.outdir):
                        os.makedirs(sysvals.outdir)
+               sysvals.sudoUserchown(sysvals.outdir)
+               finish = datetime.now()
+               if 'time' in sysvals.multitest:
+                       finish += timedelta(minutes=sysvals.multitest['time'])
                for i in range(sysvals.multitest['count']):
-                       if(i != 0):
+                       sysvals.multistat(True, i, finish)
+                       if i != 0 and sysvals.multitest['delay'] > 0:
                                pprint('Waiting %d seconds...' % (sysvals.multitest['delay']))
                                time.sleep(sysvals.multitest['delay'])
-                       pprint('TEST (%d/%d) START' % (i+1, sysvals.multitest['count']))
                        fmt = 'suspend-%y%m%d-%H%M%S'
                        sysvals.testdir = os.path.join(sysvals.outdir, datetime.now().strftime(fmt))
-                       ret = runTest(i+1)
-                       pprint('TEST (%d/%d) COMPLETE' % (i+1, sysvals.multitest['count']))
-                       sysvals.logmsg = ''
+                       ret = runTest(i+1, True)
+                       failcnt = 0 if not ret else failcnt + 1
+                       if sysvals.maxfail > 0 and failcnt >= sysvals.maxfail:
+                               pprint('Maximum fail count of %d reached, aborting multitest' % (sysvals.maxfail))
+                               break
+                       time.sleep(5)
+                       sysvals.resetlog()
+                       sysvals.multistat(False, i, finish)
+                       if 'time' in sysvals.multitest and datetime.now() >= finish:
+                               break
                if not sysvals.skiphtml:
                        runSummary(sysvals.outdir, False, False)
                sysvals.sudoUserchown(sysvals.outdir)
index cde463af70711df168f3799a93e5ef535d81c9f0..c2642517e1d8d6a7bd77dbcdb0410b826e5ff960 100644 (file)
@@ -5,7 +5,8 @@
 static void test_fexit_bpf2bpf_common(const char *obj_file,
                                      const char *target_obj_file,
                                      int prog_cnt,
-                                     const char **prog_name)
+                                     const char **prog_name,
+                                     bool run_prog)
 {
        struct bpf_object *obj = NULL, *pkt_obj;
        int err, pkt_fd, i;
@@ -18,7 +19,8 @@ static void test_fexit_bpf2bpf_common(const char *obj_file,
 
        err = bpf_prog_load(target_obj_file, BPF_PROG_TYPE_UNSPEC,
                            &pkt_obj, &pkt_fd);
-       if (CHECK(err, "prog_load sched cls", "err %d errno %d\n", err, errno))
+       if (CHECK(err, "tgt_prog_load", "file %s err %d errno %d\n",
+                 target_obj_file, err, errno))
                return;
        DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts,
                            .attach_prog_fd = pkt_fd,
@@ -33,7 +35,7 @@ static void test_fexit_bpf2bpf_common(const char *obj_file,
 
        obj = bpf_object__open_file(obj_file, &opts);
        if (CHECK(IS_ERR_OR_NULL(obj), "obj_open",
-                 "failed to open fexit_bpf2bpf: %ld\n",
+                 "failed to open %s: %ld\n", obj_file,
                  PTR_ERR(obj)))
                goto close_prog;
 
@@ -49,6 +51,10 @@ static void test_fexit_bpf2bpf_common(const char *obj_file,
                if (CHECK(IS_ERR(link[i]), "attach_trace", "failed to link\n"))
                        goto close_prog;
        }
+
+       if (!run_prog)
+               goto close_prog;
+
        data_map = bpf_object__find_map_by_name(obj, "fexit_bp.bss");
        if (CHECK(!data_map, "find_data_map", "data map not found\n"))
                goto close_prog;
@@ -89,7 +95,7 @@ static void test_target_no_callees(void)
        test_fexit_bpf2bpf_common("./fexit_bpf2bpf_simple.o",
                                  "./test_pkt_md_access.o",
                                  ARRAY_SIZE(prog_name),
-                                 prog_name);
+                                 prog_name, true);
 }
 
 static void test_target_yes_callees(void)
@@ -103,7 +109,7 @@ static void test_target_yes_callees(void)
        test_fexit_bpf2bpf_common("./fexit_bpf2bpf.o",
                                  "./test_pkt_access.o",
                                  ARRAY_SIZE(prog_name),
-                                 prog_name);
+                                 prog_name, true);
 }
 
 static void test_func_replace(void)
@@ -120,7 +126,18 @@ static void test_func_replace(void)
        test_fexit_bpf2bpf_common("./fexit_bpf2bpf.o",
                                  "./test_pkt_access.o",
                                  ARRAY_SIZE(prog_name),
-                                 prog_name);
+                                 prog_name, true);
+}
+
+static void test_func_replace_verify(void)
+{
+       const char *prog_name[] = {
+               "freplace/do_bind",
+       };
+       test_fexit_bpf2bpf_common("./freplace_connect4.o",
+                                 "./connect4_prog.o",
+                                 ARRAY_SIZE(prog_name),
+                                 prog_name, false);
 }
 
 void test_fexit_bpf2bpf(void)
@@ -128,4 +145,5 @@ void test_fexit_bpf2bpf(void)
        test_target_no_callees();
        test_target_yes_callees();
        test_func_replace();
+       test_func_replace_verify();
 }
index 16a814eb4d6459de76f6cccfcb14d02a2cf44da3..56d80adcf4bdec8d074d1036a87333901e2bfa59 100644 (file)
@@ -19,15 +19,16 @@ void test_mmap(void)
        const size_t map_sz = roundup_page(sizeof(struct map_data));
        const int zero = 0, one = 1, two = 2, far = 1500;
        const long page_size = sysconf(_SC_PAGE_SIZE);
-       int err, duration = 0, i, data_map_fd;
+       int err, duration = 0, i, data_map_fd, data_map_id, tmp_fd;
        struct bpf_map *data_map, *bss_map;
        void *bss_mmaped = NULL, *map_mmaped = NULL, *tmp1, *tmp2;
        struct test_mmap__bss *bss_data;
+       struct bpf_map_info map_info;
+       __u32 map_info_sz = sizeof(map_info);
        struct map_data *map_data;
        struct test_mmap *skel;
        __u64 val = 0;
 
-
        skel = test_mmap__open_and_load();
        if (CHECK(!skel, "skel_open_and_load", "skeleton open/load failed\n"))
                return;
@@ -36,6 +37,14 @@ void test_mmap(void)
        data_map = skel->maps.data_map;
        data_map_fd = bpf_map__fd(data_map);
 
+       /* get map's ID */
+       memset(&map_info, 0, map_info_sz);
+       err = bpf_obj_get_info_by_fd(data_map_fd, &map_info, &map_info_sz);
+       if (CHECK(err, "map_get_info", "failed %d\n", errno))
+               goto cleanup;
+       data_map_id = map_info.id;
+
+       /* mmap BSS map */
        bss_mmaped = mmap(NULL, bss_sz, PROT_READ | PROT_WRITE, MAP_SHARED,
                          bpf_map__fd(bss_map), 0);
        if (CHECK(bss_mmaped == MAP_FAILED, "bss_mmap",
@@ -98,6 +107,10 @@ void test_mmap(void)
                  "data_map freeze succeeded: err=%d, errno=%d\n", err, errno))
                goto cleanup;
 
+       err = mprotect(map_mmaped, map_sz, PROT_READ);
+       if (CHECK(err, "mprotect_ro", "mprotect to r/o failed %d\n", errno))
+               goto cleanup;
+
        /* unmap R/W mapping */
        err = munmap(map_mmaped, map_sz);
        map_mmaped = NULL;
@@ -111,6 +124,12 @@ void test_mmap(void)
                map_mmaped = NULL;
                goto cleanup;
        }
+       err = mprotect(map_mmaped, map_sz, PROT_WRITE);
+       if (CHECK(!err, "mprotect_wr", "mprotect() succeeded unexpectedly!\n"))
+               goto cleanup;
+       err = mprotect(map_mmaped, map_sz, PROT_EXEC);
+       if (CHECK(!err, "mprotect_ex", "mprotect() succeeded unexpectedly!\n"))
+               goto cleanup;
        map_data = map_mmaped;
 
        /* map/unmap in a loop to test ref counting */
@@ -197,6 +216,45 @@ void test_mmap(void)
        CHECK_FAIL(map_data->val[far] != 3 * 321);
 
        munmap(tmp2, 4 * page_size);
+
+       tmp1 = mmap(NULL, map_sz, PROT_READ, MAP_SHARED, data_map_fd, 0);
+       if (CHECK(tmp1 == MAP_FAILED, "last_mmap", "failed %d\n", errno))
+               goto cleanup;
+
+       test_mmap__destroy(skel);
+       skel = NULL;
+       CHECK_FAIL(munmap(bss_mmaped, bss_sz));
+       bss_mmaped = NULL;
+       CHECK_FAIL(munmap(map_mmaped, map_sz));
+       map_mmaped = NULL;
+
+       /* map should be still held by active mmap */
+       tmp_fd = bpf_map_get_fd_by_id(data_map_id);
+       if (CHECK(tmp_fd < 0, "get_map_by_id", "failed %d\n", errno)) {
+               munmap(tmp1, map_sz);
+               goto cleanup;
+       }
+       close(tmp_fd);
+
+       /* this should release data map finally */
+       munmap(tmp1, map_sz);
+
+       /* we need to wait for RCU grace period */
+       for (i = 0; i < 10000; i++) {
+               __u32 id = data_map_id - 1;
+               if (bpf_map_get_next_id(id, &id) || id > data_map_id)
+                       break;
+               usleep(1);
+       }
+
+       /* should fail to get map FD by non-existing ID */
+       tmp_fd = bpf_map_get_fd_by_id(data_map_id);
+       if (CHECK(tmp_fd >= 0, "get_map_by_id_after",
+                 "unexpectedly succeeded %d\n", tmp_fd)) {
+               close(tmp_fd);
+               goto cleanup;
+       }
+
 cleanup:
        if (bss_mmaped)
                CHECK_FAIL(munmap(bss_mmaped, bss_sz));
index 9d9351dc2ded422d92a0b050ae386e192839e1c0..713167449c9898a58264c5a88d913413b03e6f89 100644 (file)
@@ -43,18 +43,18 @@ static struct sec_name_test tests[] = {
        {"lwt_seg6local", {0, BPF_PROG_TYPE_LWT_SEG6LOCAL, 0}, {-EINVAL, 0} },
        {
                "cgroup_skb/ingress",
-               {0, BPF_PROG_TYPE_CGROUP_SKB, 0},
+               {0, BPF_PROG_TYPE_CGROUP_SKB, BPF_CGROUP_INET_INGRESS},
                {0, BPF_CGROUP_INET_INGRESS},
        },
        {
                "cgroup_skb/egress",
-               {0, BPF_PROG_TYPE_CGROUP_SKB, 0},
+               {0, BPF_PROG_TYPE_CGROUP_SKB, BPF_CGROUP_INET_EGRESS},
                {0, BPF_CGROUP_INET_EGRESS},
        },
        {"cgroup/skb", {0, BPF_PROG_TYPE_CGROUP_SKB, 0}, {-EINVAL, 0} },
        {
                "cgroup/sock",
-               {0, BPF_PROG_TYPE_CGROUP_SOCK, 0},
+               {0, BPF_PROG_TYPE_CGROUP_SOCK, BPF_CGROUP_INET_SOCK_CREATE},
                {0, BPF_CGROUP_INET_SOCK_CREATE},
        },
        {
@@ -69,26 +69,38 @@ static struct sec_name_test tests[] = {
        },
        {
                "cgroup/dev",
-               {0, BPF_PROG_TYPE_CGROUP_DEVICE, 0},
+               {0, BPF_PROG_TYPE_CGROUP_DEVICE, BPF_CGROUP_DEVICE},
                {0, BPF_CGROUP_DEVICE},
        },
-       {"sockops", {0, BPF_PROG_TYPE_SOCK_OPS, 0}, {0, BPF_CGROUP_SOCK_OPS} },
+       {
+               "sockops",
+               {0, BPF_PROG_TYPE_SOCK_OPS, BPF_CGROUP_SOCK_OPS},
+               {0, BPF_CGROUP_SOCK_OPS},
+       },
        {
                "sk_skb/stream_parser",
-               {0, BPF_PROG_TYPE_SK_SKB, 0},
+               {0, BPF_PROG_TYPE_SK_SKB, BPF_SK_SKB_STREAM_PARSER},
                {0, BPF_SK_SKB_STREAM_PARSER},
        },
        {
                "sk_skb/stream_verdict",
-               {0, BPF_PROG_TYPE_SK_SKB, 0},
+               {0, BPF_PROG_TYPE_SK_SKB, BPF_SK_SKB_STREAM_VERDICT},
                {0, BPF_SK_SKB_STREAM_VERDICT},
        },
        {"sk_skb", {0, BPF_PROG_TYPE_SK_SKB, 0}, {-EINVAL, 0} },
-       {"sk_msg", {0, BPF_PROG_TYPE_SK_MSG, 0}, {0, BPF_SK_MSG_VERDICT} },
-       {"lirc_mode2", {0, BPF_PROG_TYPE_LIRC_MODE2, 0}, {0, BPF_LIRC_MODE2} },
+       {
+               "sk_msg",
+               {0, BPF_PROG_TYPE_SK_MSG, BPF_SK_MSG_VERDICT},
+               {0, BPF_SK_MSG_VERDICT},
+       },
+       {
+               "lirc_mode2",
+               {0, BPF_PROG_TYPE_LIRC_MODE2, BPF_LIRC_MODE2},
+               {0, BPF_LIRC_MODE2},
+       },
        {
                "flow_dissector",
-               {0, BPF_PROG_TYPE_FLOW_DISSECTOR, 0},
+               {0, BPF_PROG_TYPE_FLOW_DISSECTOR, BPF_FLOW_DISSECTOR},
                {0, BPF_FLOW_DISSECTOR},
        },
        {
@@ -158,17 +170,17 @@ static void test_prog_type_by_name(const struct sec_name_test *test)
                                      &expected_attach_type);
 
        CHECK(rc != test->expected_load.rc, "check_code",
-             "prog: unexpected rc=%d for %s", rc, test->sec_name);
+             "prog: unexpected rc=%d for %s\n", rc, test->sec_name);
 
        if (rc)
                return;
 
        CHECK(prog_type != test->expected_load.prog_type, "check_prog_type",
-             "prog: unexpected prog_type=%d for %s",
+             "prog: unexpected prog_type=%d for %s\n",
              prog_type, test->sec_name);
 
        CHECK(expected_attach_type != test->expected_load.expected_attach_type,
-             "check_attach_type", "prog: unexpected expected_attach_type=%d for %s",
+             "check_attach_type", "prog: unexpected expected_attach_type=%d for %s\n",
              expected_attach_type, test->sec_name);
 }
 
@@ -180,13 +192,13 @@ static void test_attach_type_by_name(const struct sec_name_test *test)
        rc = libbpf_attach_type_by_name(test->sec_name, &attach_type);
 
        CHECK(rc != test->expected_attach.rc, "check_ret",
-             "attach: unexpected rc=%d for %s", rc, test->sec_name);
+             "attach: unexpected rc=%d for %s\n", rc, test->sec_name);
 
        if (rc)
                return;
 
        CHECK(attach_type != test->expected_attach.attach_type,
-             "check_attach_type", "attach: unexpected attach_type=%d for %s",
+             "check_attach_type", "attach: unexpected attach_type=%d for %s\n",
              attach_type, test->sec_name);
 }
 
index 1e4c258de09d976a1ace45b71d8fc555c9414294..b17eb2045c1d1f601d92802318a9c7b73e0bd546 100644 (file)
 
 char *CMD_ARGS[] = {"true", NULL};
 
-int heap_mprotect(void)
+#define GET_PAGE_ADDR(ADDR, PAGE_SIZE)                                 \
+       (char *)(((unsigned long) (ADDR + PAGE_SIZE)) & ~(PAGE_SIZE-1))
+
+int stack_mprotect(void)
 {
        void *buf;
        long sz;
@@ -25,12 +28,9 @@ int heap_mprotect(void)
        if (sz < 0)
                return sz;
 
-       buf = memalign(sz, 2 * sz);
-       if (buf == NULL)
-               return -ENOMEM;
-
-       ret = mprotect(buf, sz, PROT_READ | PROT_WRITE | PROT_EXEC);
-       free(buf);
+       buf = alloca(sz * 3);
+       ret = mprotect(GET_PAGE_ADDR(buf, sz), sz,
+                      PROT_READ | PROT_WRITE | PROT_EXEC);
        return ret;
 }
 
@@ -73,8 +73,8 @@ void test_test_lsm(void)
 
        skel->bss->monitored_pid = getpid();
 
-       err = heap_mprotect();
-       if (CHECK(errno != EPERM, "heap_mprotect", "want errno=EPERM, got %d\n",
+       err = stack_mprotect();
+       if (CHECK(errno != EPERM, "stack_mprotect", "want err=EPERM, got %d\n",
                  errno))
                goto close_prog;
 
index 05b294d6b9239df13819543a2712f2aeb5e3a6af..15ef3531483ef3d5bfb91cc7cf7d044b71f941f8 100644 (file)
@@ -6,19 +6,34 @@
 
 void test_xdp_attach(void)
 {
+       __u32 duration = 0, id1, id2, id0 = 0, len;
        struct bpf_object *obj1, *obj2, *obj3;
        const char *file = "./test_xdp.o";
+       struct bpf_prog_info info = {};
        int err, fd1, fd2, fd3;
-       __u32 duration = 0;
        DECLARE_LIBBPF_OPTS(bpf_xdp_set_link_opts, opts,
                            .old_fd = -1);
 
+       len = sizeof(info);
+
        err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj1, &fd1);
        if (CHECK_FAIL(err))
                return;
+       err = bpf_obj_get_info_by_fd(fd1, &info, &len);
+       if (CHECK_FAIL(err))
+               goto out_1;
+       id1 = info.id;
+
        err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj2, &fd2);
        if (CHECK_FAIL(err))
                goto out_1;
+
+       memset(&info, 0, sizeof(info));
+       err = bpf_obj_get_info_by_fd(fd2, &info, &len);
+       if (CHECK_FAIL(err))
+               goto out_2;
+       id2 = info.id;
+
        err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj3, &fd3);
        if (CHECK_FAIL(err))
                goto out_2;
@@ -28,6 +43,11 @@ void test_xdp_attach(void)
        if (CHECK(err, "load_ok", "initial load failed"))
                goto out_close;
 
+       err = bpf_get_link_xdp_id(IFINDEX_LO, &id0, 0);
+       if (CHECK(err || id0 != id1, "id1_check",
+                 "loaded prog id %u != id1 %u, err %d", id0, id1, err))
+               goto out_close;
+
        err = bpf_set_link_xdp_fd_opts(IFINDEX_LO, fd2, XDP_FLAGS_REPLACE,
                                       &opts);
        if (CHECK(!err, "load_fail", "load with expected id didn't fail"))
@@ -37,6 +57,10 @@ void test_xdp_attach(void)
        err = bpf_set_link_xdp_fd_opts(IFINDEX_LO, fd2, 0, &opts);
        if (CHECK(err, "replace_ok", "replace valid old_fd failed"))
                goto out;
+       err = bpf_get_link_xdp_id(IFINDEX_LO, &id0, 0);
+       if (CHECK(err || id0 != id2, "id2_check",
+                 "loaded prog id %u != id2 %u, err %d", id0, id2, err))
+               goto out_close;
 
        err = bpf_set_link_xdp_fd_opts(IFINDEX_LO, fd3, 0, &opts);
        if (CHECK(!err, "replace_fail", "replace invalid old_fd didn't fail"))
@@ -51,6 +75,10 @@ void test_xdp_attach(void)
        if (CHECK(err, "remove_ok", "remove valid old_fd failed"))
                goto out;
 
+       err = bpf_get_link_xdp_id(IFINDEX_LO, &id0, 0);
+       if (CHECK(err || id0 != 0, "unload_check",
+                 "loaded prog id %u != 0, err %d", id0, err))
+               goto out_close;
 out:
        bpf_set_link_xdp_fd(IFINDEX_LO, -1, 0);
 out_close:
diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_info.c b/tools/testing/selftests/bpf/prog_tests/xdp_info.c
new file mode 100644 (file)
index 0000000..d2d7a28
--- /dev/null
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/if_link.h>
+#include <test_progs.h>
+
+#define IFINDEX_LO 1
+
+void test_xdp_info(void)
+{
+       __u32 len = sizeof(struct bpf_prog_info), duration = 0, prog_id;
+       const char *file = "./xdp_dummy.o";
+       struct bpf_prog_info info = {};
+       struct bpf_object *obj;
+       int err, prog_fd;
+
+       /* Get prog_id for XDP_ATTACHED_NONE mode */
+
+       err = bpf_get_link_xdp_id(IFINDEX_LO, &prog_id, 0);
+       if (CHECK(err, "get_xdp_none", "errno=%d\n", errno))
+               return;
+       if (CHECK(prog_id, "prog_id_none", "unexpected prog_id=%u\n", prog_id))
+               return;
+
+       err = bpf_get_link_xdp_id(IFINDEX_LO, &prog_id, XDP_FLAGS_SKB_MODE);
+       if (CHECK(err, "get_xdp_none_skb", "errno=%d\n", errno))
+               return;
+       if (CHECK(prog_id, "prog_id_none_skb", "unexpected prog_id=%u\n",
+                 prog_id))
+               return;
+
+       /* Setup prog */
+
+       err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
+       if (CHECK_FAIL(err))
+               return;
+
+       err = bpf_obj_get_info_by_fd(prog_fd, &info, &len);
+       if (CHECK(err, "get_prog_info", "errno=%d\n", errno))
+               goto out_close;
+
+       err = bpf_set_link_xdp_fd(IFINDEX_LO, prog_fd, XDP_FLAGS_SKB_MODE);
+       if (CHECK(err, "set_xdp_skb", "errno=%d\n", errno))
+               goto out_close;
+
+       /* Get prog_id for single prog mode */
+
+       err = bpf_get_link_xdp_id(IFINDEX_LO, &prog_id, 0);
+       if (CHECK(err, "get_xdp", "errno=%d\n", errno))
+               goto out;
+       if (CHECK(prog_id != info.id, "prog_id", "prog_id not available\n"))
+               goto out;
+
+       err = bpf_get_link_xdp_id(IFINDEX_LO, &prog_id, XDP_FLAGS_SKB_MODE);
+       if (CHECK(err, "get_xdp_skb", "errno=%d\n", errno))
+               goto out;
+       if (CHECK(prog_id != info.id, "prog_id_skb", "prog_id not available\n"))
+               goto out;
+
+       err = bpf_get_link_xdp_id(IFINDEX_LO, &prog_id, XDP_FLAGS_DRV_MODE);
+       if (CHECK(err, "get_xdp_drv", "errno=%d\n", errno))
+               goto out;
+       if (CHECK(prog_id, "prog_id_drv", "unexpected prog_id=%u\n", prog_id))
+               goto out;
+
+out:
+       bpf_set_link_xdp_fd(IFINDEX_LO, -1, 0);
+out_close:
+       bpf_object__close(obj);
+}
index 75085119c5bbf739d9c6bf9441ab65093fa93e56..ad3c498a8150014f7bcd1c5fe13257563e89bfbb 100644 (file)
 
 int _version SEC("version") = 1;
 
+__attribute__ ((noinline))
+int do_bind(struct bpf_sock_addr *ctx)
+{
+       struct sockaddr_in sa = {};
+
+       sa.sin_family = AF_INET;
+       sa.sin_port = bpf_htons(0);
+       sa.sin_addr.s_addr = bpf_htonl(SRC_REWRITE_IP4);
+
+       if (bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa)) != 0)
+               return 0;
+
+       return 1;
+}
+
 SEC("cgroup/connect4")
 int connect_v4_prog(struct bpf_sock_addr *ctx)
 {
        struct bpf_sock_tuple tuple = {};
-       struct sockaddr_in sa;
        struct bpf_sock *sk;
 
        /* Verify that new destination is available. */
@@ -56,17 +70,7 @@ int connect_v4_prog(struct bpf_sock_addr *ctx)
        ctx->user_ip4 = bpf_htonl(DST_REWRITE_IP4);
        ctx->user_port = bpf_htons(DST_REWRITE_PORT4);
 
-       /* Rewrite source. */
-       memset(&sa, 0, sizeof(sa));
-
-       sa.sin_family = AF_INET;
-       sa.sin_port = bpf_htons(0);
-       sa.sin_addr.s_addr = bpf_htonl(SRC_REWRITE_IP4);
-
-       if (bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa)) != 0)
-               return 0;
-
-       return 1;
+       return do_bind(ctx) ? 1 : 0;
 }
 
 char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/freplace_connect4.c b/tools/testing/selftests/bpf/progs/freplace_connect4.c
new file mode 100644 (file)
index 0000000..a0ae842
--- /dev/null
@@ -0,0 +1,18 @@
+#include <linux/stddef.h>
+#include <linux/ipv6.h>
+#include <linux/bpf.h>
+#include <linux/in.h>
+#include <sys/socket.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_endian.h>
+
+SEC("freplace/do_bind")
+int new_do_bind(struct bpf_sock_addr *ctx)
+{
+  struct sockaddr_in sa = {};
+
+  bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa));
+  return 0;
+}
+
+char _license[] SEC("license") = "GPL";
index a4e3c223028d750613ccac75dce4e00169978fe5..b4598d4bc4f7307bf013bbb75ebf769c1cffa57d 100644 (file)
@@ -23,12 +23,12 @@ int BPF_PROG(test_int_hook, struct vm_area_struct *vma,
                return ret;
 
        __u32 pid = bpf_get_current_pid_tgid() >> 32;
-       int is_heap = 0;
+       int is_stack = 0;
 
-       is_heap = (vma->vm_start >= vma->vm_mm->start_brk &&
-                  vma->vm_end <= vma->vm_mm->brk);
+       is_stack = (vma->vm_start <= vma->vm_mm->start_stack &&
+                   vma->vm_end >= vma->vm_mm->start_stack);
 
-       if (is_heap && monitored_pid == pid) {
+       if (is_stack && monitored_pid == pid) {
                mprotect_count++;
                ret = -EPERM;
        }
index 88b0566da13d2654a5a682089f4f9054b7038a11..31538c9ed1939ca5360d0052086534720de8f67d 100644 (file)
@@ -20,20 +20,12 @@ struct bpf_map_def SEC("maps") btf_map = {
 
 BPF_ANNOTATE_KV_PAIR(btf_map, int, struct ipv_counts);
 
-struct dummy_tracepoint_args {
-       unsigned long long pad;
-       struct sock *sock;
-};
-
 __attribute__((noinline))
-int test_long_fname_2(struct dummy_tracepoint_args *arg)
+int test_long_fname_2(void)
 {
        struct ipv_counts *counts;
        int key = 0;
 
-       if (!arg->sock)
-               return 0;
-
        counts = bpf_map_lookup_elem(&btf_map, &key);
        if (!counts)
                return 0;
@@ -44,15 +36,15 @@ int test_long_fname_2(struct dummy_tracepoint_args *arg)
 }
 
 __attribute__((noinline))
-int test_long_fname_1(struct dummy_tracepoint_args *arg)
+int test_long_fname_1(void)
 {
-       return test_long_fname_2(arg);
+       return test_long_fname_2();
 }
 
 SEC("dummy_tracepoint")
-int _dummy_tracepoint(struct dummy_tracepoint_args *arg)
+int _dummy_tracepoint(void *arg)
 {
-       return test_long_fname_1(arg);
+       return test_long_fname_1();
 }
 
 char _license[] SEC("license") = "GPL";
index a924e53c8e9d8b32ac9f8afa0f19e90fbc1a79fa..6c5560162746b8a336f2086855889ebba388ac85 100644 (file)
@@ -28,20 +28,12 @@ struct {
        __type(value, struct ipv_counts);
 } btf_map SEC(".maps");
 
-struct dummy_tracepoint_args {
-       unsigned long long pad;
-       struct sock *sock;
-};
-
 __attribute__((noinline))
-int test_long_fname_2(struct dummy_tracepoint_args *arg)
+int test_long_fname_2(void)
 {
        struct ipv_counts *counts;
        int key = 0;
 
-       if (!arg->sock)
-               return 0;
-
        counts = bpf_map_lookup_elem(&btf_map, &key);
        if (!counts)
                return 0;
@@ -57,15 +49,15 @@ int test_long_fname_2(struct dummy_tracepoint_args *arg)
 }
 
 __attribute__((noinline))
-int test_long_fname_1(struct dummy_tracepoint_args *arg)
+int test_long_fname_1(void)
 {
-       return test_long_fname_2(arg);
+       return test_long_fname_2();
 }
 
 SEC("dummy_tracepoint")
-int _dummy_tracepoint(struct dummy_tracepoint_args *arg)
+int _dummy_tracepoint(void *arg)
 {
-       return test_long_fname_1(arg);
+       return test_long_fname_1();
 }
 
 char _license[] SEC("license") = "GPL";
index 983aedd1c07252b4b69ae1b100b6dc86cb2c509f..506da7fd2da2376d93605a9ceb49559fb5b9ccc3 100644 (file)
@@ -17,20 +17,12 @@ struct bpf_map_def SEC("maps") btf_map = {
        .max_entries = 4,
 };
 
-struct dummy_tracepoint_args {
-       unsigned long long pad;
-       struct sock *sock;
-};
-
 __attribute__((noinline))
-int test_long_fname_2(struct dummy_tracepoint_args *arg)
+int test_long_fname_2(void)
 {
        struct ipv_counts *counts;
        int key = 0;
 
-       if (!arg->sock)
-               return 0;
-
        counts = bpf_map_lookup_elem(&btf_map, &key);
        if (!counts)
                return 0;
@@ -41,15 +33,15 @@ int test_long_fname_2(struct dummy_tracepoint_args *arg)
 }
 
 __attribute__((noinline))
-int test_long_fname_1(struct dummy_tracepoint_args *arg)
+int test_long_fname_1(void)
 {
-       return test_long_fname_2(arg);
+       return test_long_fname_2();
 }
 
 SEC("dummy_tracepoint")
-int _dummy_tracepoint(struct dummy_tracepoint_args *arg)
+int _dummy_tracepoint(void *arg)
 {
-       return test_long_fname_1(arg);
+       return test_long_fname_1();
 }
 
 char _license[] SEC("license") = "GPL";
index 8da77cda5f4a578c449c567f6f1477c35bbda6e9..305fae8f80a98acc6709c60f5fd9407098775f09 100644 (file)
@@ -2854,7 +2854,7 @@ static struct btf_raw_test raw_tests[] = {
        .value_type_id = 1,
        .max_entries = 4,
        .btf_load_err = true,
-       .err_str = "vlen != 0",
+       .err_str = "Invalid func linkage",
 },
 
 {
index 4d0d09574bf4bb4a1ed42267821c0040771d1f5c..a253a064e6e059056d6389b87c5540e5cc37ebfe 100644 (file)
        .result = REJECT
 },
 {
-       "bounds check mixed 32bit and 64bit arithmatic. test1",
+       "bounds check mixed 32bit and 64bit arithmetic. test1",
        .insns = {
        BPF_MOV64_IMM(BPF_REG_0, 0),
        BPF_MOV64_IMM(BPF_REG_1, -1),
        .result = ACCEPT
 },
 {
-       "bounds check mixed 32bit and 64bit arithmatic. test2",
+       "bounds check mixed 32bit and 64bit arithmetic. test2",
        .insns = {
        BPF_MOV64_IMM(BPF_REG_0, 0),
        BPF_MOV64_IMM(BPF_REG_1, -1),
index 7276620ef242a4b3ae40eea1b2288d0b5e78c4d7..8bfeb77c60bd364649a00bc604a76c9a4488c45b 100644 (file)
        },
        .result = ACCEPT,
 },
+{
+       "store PTR_TO_STACK in R10 to array map using BPF_B",
+       .insns = {
+       /* Load pointer to map. */
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+       BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
+       BPF_MOV64_IMM(BPF_REG_0, 2),
+       BPF_EXIT_INSN(),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       /* Copy R10 to R9. */
+       BPF_MOV64_REG(BPF_REG_9, BPF_REG_10),
+       /* Pollute other registers with unaligned values. */
+       BPF_MOV64_IMM(BPF_REG_2, -1),
+       BPF_MOV64_IMM(BPF_REG_3, -1),
+       BPF_MOV64_IMM(BPF_REG_4, -1),
+       BPF_MOV64_IMM(BPF_REG_5, -1),
+       BPF_MOV64_IMM(BPF_REG_6, -1),
+       BPF_MOV64_IMM(BPF_REG_7, -1),
+       BPF_MOV64_IMM(BPF_REG_8, -1),
+       /* Store both R9 and R10 with BPF_B and read back. */
+       BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_10, 0),
+       BPF_LDX_MEM(BPF_B, BPF_REG_2, BPF_REG_1, 0),
+       BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_9, 0),
+       BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_1, 0),
+       /* Should read back as same value. */
+       BPF_JMP_REG(BPF_JEQ, BPF_REG_2, BPF_REG_3, 2),
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_EXIT_INSN(),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_map_array_48b = { 3 },
+       .result = ACCEPT,
+       .retval = 42,
+       .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+},
index 7f6c232cd8423e4b5cb17ec01554a964be795e69..ed1c2cea1dea66c06083c7b41ce0280ce7dd7b54 100644 (file)
@@ -88,6 +88,7 @@
        BPF_EXIT_INSN(),
        },
        .fixup_map_hash_48b = { 3 },
+       .errstr_unpriv = "leaking pointer from stack off -8",
        .errstr = "R0 invalid mem access 'inv'",
        .result = REJECT,
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
index 11eee0b600407e2f83a036ae8d422acf0c744a56..d979ff14775ad87a3a3077c487c6ca08906261c6 100644 (file)
@@ -3,6 +3,7 @@
 #define _GNU_SOURCE
 #include <poll.h>
 #include <unistd.h>
+#include <assert.h>
 #include <signal.h>
 #include <pthread.h>
 #include <sys/epoll.h>
@@ -3136,4 +3137,149 @@ TEST(epoll59)
        close(ctx.sfd[0]);
 }
 
+enum {
+       EPOLL60_EVENTS_NR = 10,
+};
+
+struct epoll60_ctx {
+       volatile int stopped;
+       int ready;
+       int waiters;
+       int epfd;
+       int evfd[EPOLL60_EVENTS_NR];
+};
+
+static void *epoll60_wait_thread(void *ctx_)
+{
+       struct epoll60_ctx *ctx = ctx_;
+       struct epoll_event e;
+       sigset_t sigmask;
+       uint64_t v;
+       int ret;
+
+       /* Block SIGUSR1 */
+       sigemptyset(&sigmask);
+       sigaddset(&sigmask, SIGUSR1);
+       sigprocmask(SIG_SETMASK, &sigmask, NULL);
+
+       /* Prepare empty mask for epoll_pwait() */
+       sigemptyset(&sigmask);
+
+       while (!ctx->stopped) {
+               /* Mark we are ready */
+               __atomic_fetch_add(&ctx->ready, 1, __ATOMIC_ACQUIRE);
+
+               /* Start when all are ready */
+               while (__atomic_load_n(&ctx->ready, __ATOMIC_ACQUIRE) &&
+                      !ctx->stopped);
+
+               /* Account this waiter */
+               __atomic_fetch_add(&ctx->waiters, 1, __ATOMIC_ACQUIRE);
+
+               ret = epoll_pwait(ctx->epfd, &e, 1, 2000, &sigmask);
+               if (ret != 1) {
+                       /* We expect only signal delivery on stop */
+                       assert(ret < 0 && errno == EINTR && "Lost wakeup!\n");
+                       assert(ctx->stopped);
+                       break;
+               }
+
+               ret = read(e.data.fd, &v, sizeof(v));
+               /* Since we are on ET mode, thus each thread gets its own fd. */
+               assert(ret == sizeof(v));
+
+               __atomic_fetch_sub(&ctx->waiters, 1, __ATOMIC_RELEASE);
+       }
+
+       return NULL;
+}
+
+static inline unsigned long long msecs(void)
+{
+       struct timespec ts;
+       unsigned long long msecs;
+
+       clock_gettime(CLOCK_REALTIME, &ts);
+       msecs = ts.tv_sec * 1000ull;
+       msecs += ts.tv_nsec / 1000000ull;
+
+       return msecs;
+}
+
+static inline int count_waiters(struct epoll60_ctx *ctx)
+{
+       return __atomic_load_n(&ctx->waiters, __ATOMIC_ACQUIRE);
+}
+
+TEST(epoll60)
+{
+       struct epoll60_ctx ctx = { 0 };
+       pthread_t waiters[ARRAY_SIZE(ctx.evfd)];
+       struct epoll_event e;
+       int i, n, ret;
+
+       signal(SIGUSR1, signal_handler);
+
+       ctx.epfd = epoll_create1(0);
+       ASSERT_GE(ctx.epfd, 0);
+
+       /* Create event fds */
+       for (i = 0; i < ARRAY_SIZE(ctx.evfd); i++) {
+               ctx.evfd[i] = eventfd(0, EFD_NONBLOCK);
+               ASSERT_GE(ctx.evfd[i], 0);
+
+               e.events = EPOLLIN | EPOLLET;
+               e.data.fd = ctx.evfd[i];
+               ASSERT_EQ(epoll_ctl(ctx.epfd, EPOLL_CTL_ADD, ctx.evfd[i], &e), 0);
+       }
+
+       /* Create waiter threads */
+       for (i = 0; i < ARRAY_SIZE(waiters); i++)
+               ASSERT_EQ(pthread_create(&waiters[i], NULL,
+                                        epoll60_wait_thread, &ctx), 0);
+
+       for (i = 0; i < 300; i++) {
+               uint64_t v = 1, ms;
+
+               /* Wait for all to be ready */
+               while (__atomic_load_n(&ctx.ready, __ATOMIC_ACQUIRE) !=
+                      ARRAY_SIZE(ctx.evfd))
+                       ;
+
+               /* Steady, go */
+               __atomic_fetch_sub(&ctx.ready, ARRAY_SIZE(ctx.evfd),
+                                  __ATOMIC_ACQUIRE);
+
+               /* Wait all have gone to kernel */
+               while (count_waiters(&ctx) != ARRAY_SIZE(ctx.evfd))
+                       ;
+
+               /* 1ms should be enough to schedule away */
+               usleep(1000);
+
+               /* Quickly signal all handles at once */
+               for (n = 0; n < ARRAY_SIZE(ctx.evfd); n++) {
+                       ret = write(ctx.evfd[n], &v, sizeof(v));
+                       ASSERT_EQ(ret, sizeof(v));
+               }
+
+               /* Busy loop for 1s and wait for all waiters to wake up */
+               ms = msecs();
+               while (count_waiters(&ctx) && msecs() < ms + 1000)
+                       ;
+
+               ASSERT_EQ(count_waiters(&ctx), 0);
+       }
+       ctx.stopped = 1;
+       /* Stop waiters */
+       for (i = 0; i < ARRAY_SIZE(waiters); i++)
+               ret = pthread_kill(waiters[i], SIGUSR1);
+       for (i = 0; i < ARRAY_SIZE(waiters); i++)
+               pthread_join(waiters[i], NULL);
+
+       for (i = 0; i < ARRAY_SIZE(waiters); i++)
+               close(ctx.evfd[i]);
+       close(ctx.epfd);
+}
+
 TEST_HARNESS_MAIN
index c2c8de4faffff26a70e6a3bd131904aacabf5142..e59d985eeff0c8be95c79fd914ac706439952dc7 100644 (file)
@@ -11,5 +11,6 @@ CONFIG_PREEMPTIRQ_DELAY_TEST=m
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_SAMPLES=y
+CONFIG_SAMPLE_FTRACE_DIRECT=m
 CONFIG_SAMPLE_TRACE_PRINTK=m
 CONFIG_KALLSYMS_ALL=y
index 063ecb290a5a3442bb116639dbc7ac866c0f0639..a4605b5ee66d97dc12d92fb80bbbba2cf89ea106 100755 (executable)
@@ -17,6 +17,7 @@ echo "                -v|--verbose Increase verbosity of test messages"
 echo "         -vv        Alias of -v -v (Show all results in stdout)"
 echo "         -vvv       Alias of -v -v -v (Show all commands immediately)"
 echo "         --fail-unsupported Treat UNSUPPORTED as a failure"
+echo "         --fail-unresolved Treat UNRESOLVED as a failure"
 echo "         -d|--debug Debug mode (trace all shell commands)"
 echo "         -l|--logdir <dir> Save logs on the <dir>"
 echo "                     If <dir> is -, all logs output in console only"
@@ -29,8 +30,25 @@ err_ret=1
 # kselftest skip code is 4
 err_skip=4
 
+# cgroup RT scheduling prevents chrt commands from succeeding, which
+# induces failures in test wakeup tests.  Disable for the duration of
+# the tests.
+
+readonly sched_rt_runtime=/proc/sys/kernel/sched_rt_runtime_us
+
+sched_rt_runtime_orig=$(cat $sched_rt_runtime)
+
+setup() {
+  echo -1 > $sched_rt_runtime
+}
+
+cleanup() {
+  echo $sched_rt_runtime_orig > $sched_rt_runtime
+}
+
 errexit() { # message
   echo "Error: $1" 1>&2
+  cleanup
   exit $err_ret
 }
 
@@ -39,6 +57,8 @@ if [ `id -u` -ne 0 ]; then
   errexit "this must be run by root user"
 fi
 
+setup
+
 # Utilities
 absdir() { # file_path
   (cd `dirname $1`; pwd)
@@ -93,6 +113,10 @@ parse_opts() { # opts
       UNSUPPORTED_RESULT=1
       shift 1
     ;;
+    --fail-unresolved)
+      UNRESOLVED_RESULT=1
+      shift 1
+    ;;
     --logdir|-l)
       LOG_DIR=$2
       shift 2
@@ -157,6 +181,7 @@ KEEP_LOG=0
 DEBUG=0
 VERBOSE=0
 UNSUPPORTED_RESULT=0
+UNRESOLVED_RESULT=0
 STOP_FAILURE=0
 # Parse command-line options
 parse_opts $*
@@ -235,6 +260,7 @@ TOTAL_RESULT=0
 
 INSTANCE=
 CASENO=0
+
 testcase() { # testfile
   CASENO=$((CASENO+1))
   desc=`grep "^#[ \t]*description:" $1 | cut -f2 -d:`
@@ -260,7 +286,7 @@ eval_result() { # sigval
     $UNRESOLVED)
       prlog "  [${color_blue}UNRESOLVED${color_reset}]"
       UNRESOLVED_CASES="$UNRESOLVED_CASES $CASENO"
-      return 1 # this is a kind of bug.. something happened.
+      return $UNRESOLVED_RESULT # depends on use case
     ;;
     $UNTESTED)
       prlog "  [${color_blue}UNTESTED${color_reset}]"
@@ -273,7 +299,7 @@ eval_result() { # sigval
       return $UNSUPPORTED_RESULT # depends on use case
     ;;
     $XFAIL)
-      prlog "  [${color_red}XFAIL${color_reset}]"
+      prlog "  [${color_green}XFAIL${color_reset}]"
       XFAILED_CASES="$XFAILED_CASES $CASENO"
       return 0
     ;;
@@ -406,5 +432,7 @@ prlog "# of unsupported: " `echo $UNSUPPORTED_CASES | wc -w`
 prlog "# of xfailed: " `echo $XFAILED_CASES | wc -w`
 prlog "# of undefined(test bug): " `echo $UNDEFINED_CASES | wc -w`
 
+cleanup
+
 # if no error, return 0
 exit $TOTAL_RESULT
index aefab0c66d5482e1c56160cfd13d44d68ed820f2..f59853857ad227f87eadc6ce1ab7545d9472e9d4 100644 (file)
@@ -10,10 +10,7 @@ if ! grep -q function_graph available_tracers; then
     exit_unsupported
 fi
 
-if [ ! -f set_ftrace_filter ]; then
-    echo "set_ftrace_filter not found? Is dynamic ftrace not set?"
-    exit_unsupported
-fi
+check_filter_file set_ftrace_filter
 
 do_reset() {
     if [ -e /proc/sys/kernel/stack_tracer_enabled ]; then
index c8a5209f21191ef2cae389717044a70dc627908a..d610f47edd90b361018c7cff3c8fd1c333b80a22 100644 (file)
@@ -9,6 +9,8 @@ if ! grep -q function_graph available_tracers; then
     exit_unsupported
 fi
 
+check_filter_file set_ftrace_filter
+
 fail() { # msg
     echo $1
     exit_fail
index f4e92afab14b2485d66076fd2b002341eb6a0c7a..28936f434ee5e7e986ebba4890fe3d879f8ce16f 100644 (file)
@@ -9,6 +9,8 @@ if ! grep -q function available_tracers; then
     exit_unsupported
 fi
 
+check_filter_file set_ftrace_filter
+
 disable_tracing
 clear_trace
 
index 8aa46a2ea133819c7ad448db44ea98f17fc1a5f0..71db68a7975f2532c97a817df17c9147e019d428 100644 (file)
@@ -15,10 +15,7 @@ if [ ! -f set_ftrace_notrace_pid ]; then
     exit_unsupported
 fi
 
-if [ ! -f set_ftrace_filter ]; then
-    echo "set_ftrace_filter not found? Is function tracer not set?"
-    exit_unsupported
-fi
+check_filter_file set_ftrace_filter
 
 do_function_fork=1
 
index f2ee1e889e1350e2c77c0c33b713de96afabc86d..d58403c4b7cdad155aa99143e4972572645e6c3b 100644 (file)
@@ -16,10 +16,7 @@ if [ ! -f set_ftrace_pid ]; then
     exit_unsupported
 fi
 
-if [ ! -f set_ftrace_filter ]; then
-    echo "set_ftrace_filter not found? Is function tracer not set?"
-    exit_unsupported
-fi
+check_filter_file set_ftrace_filter
 
 do_function_fork=1
 
index 1a52f2883fe02cd5718903be31e7d6a03cc31639..b2aff786c1a204680caf8d8ff8f1fd98a1625092 100644 (file)
@@ -3,7 +3,7 @@
 # description: ftrace - stacktrace filter command
 # flags: instance
 
-[ ! -f set_ftrace_filter ] && exit_unsupported
+check_filter_file set_ftrace_filter
 
 echo _do_fork:stacktrace >> set_ftrace_filter
 
index ca2ffd7957f9e7e8feaa2d32f18a8f13376a7fd6..e9b1fd534e9661ca10bac0b288715168cd3ba895 100644 (file)
 #
 
 # The triggers are set within the set_ftrace_filter file
-if [ ! -f set_ftrace_filter ]; then
-    echo "set_ftrace_filter not found? Is dynamic ftrace not set?"
-    exit_unsupported
-fi
+check_filter_file set_ftrace_filter
 
 do_reset() {
     reset_ftrace_filter
index 9330c873f9fe93e22341ba62b19989d59c63d01b..1a4b4a442d33ebd52ff97f1405de91b0a4ab17e8 100644 (file)
@@ -2,7 +2,7 @@
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - function trace on module
 
-[ ! -f set_ftrace_filter ] && exit_unsupported
+check_filter_file set_ftrace_filter
 
 : "mod: allows to filter a non exist function"
 echo 'non_exist_func:mod:non_exist_module' > set_ftrace_filter
index dfbae637c60c7618efd87df6ae349d2d0093dd3b..a3dadb6b93b4c81bda80ec762e8f01c162e83f24 100644 (file)
@@ -18,10 +18,7 @@ if ! grep -q function_graph available_tracers; then
     exit_unsupported;
 fi
 
-if [ ! -f set_ftrace_filter ]; then
-    echo "set_ftrace_filter not found? Is dynamic ftrace not set?"
-    exit_unsupported
-fi
+check_filter_file set_ftrace_filter
 
 if [ ! -f function_profile_enabled ]; then
     echo "function_profile_enabled not found, function profiling enabled?"
index 51f6e6146bd93a8c422d9c79cc30d02fdc010cc1..70bad441fa7d3428658b0003f07d4b3a2ea9bfe1 100644 (file)
 #
 
 # The triggers are set within the set_ftrace_filter file
-if [ ! -f set_ftrace_filter ]; then
-    echo "set_ftrace_filter not found? Is dynamic ftrace not set?"
-    exit_unsupported
-fi
+check_filter_file set_ftrace_filter
 
 fail() { # mesg
     echo $1
index b414f0e3c64629ed3e0b118a18c5fa066c9fcdd0..51e9e80bc0e677487480b732b82f1fc342a2d59c 100644 (file)
@@ -8,6 +8,8 @@ if [ ! -f stack_trace ]; then
   exit_unsupported
 fi
 
+check_filter_file stack_trace_filter
+
 echo > stack_trace_filter
 echo 0 > stack_max_size
 echo 1 > /proc/sys/kernel/stack_tracer_enabled
index 1947387fe97607f27f225546dffb7152f458198a..3ed173f2944ac8e202086417342e2b02aa864653 100644 (file)
 #
 
 # The triggers are set within the set_ftrace_filter file
-if [ ! -f set_ftrace_filter ]; then
-    echo "set_ftrace_filter not found? Is dynamic ftrace not set?"
-    exit_unsupported
-fi
+check_filter_file set_ftrace_filter
 
 fail() { # mesg
     echo $1
index 5d4550591ff9f789d0f783c891b3cd766ceee27d..61a3c7e2634dfed97a6b95f85497a8dcd893acfe 100644 (file)
@@ -1,3 +1,9 @@
+check_filter_file() { # check filter file introduced by dynamic ftrace
+    if [ ! -f "$1" ]; then
+        echo "$1 not found? Is dynamic ftrace not set?"
+        exit_unsupported
+    fi
+}
 
 clear_trace() { # reset trace output
     echo > trace
index 1bcb67dcae26797ffea12e57ff65d12ec4b92e55..81490ecaaa9276de971f250e46f0400177d92b08 100644 (file)
@@ -38,7 +38,7 @@ for width in 64 32 16 8; do
   echo 0 > events/kprobes/testprobe/enable
 
   : "Confirm the arguments is recorded in given types correctly"
-  ARGS=`grep "testprobe" trace | sed -e 's/.* arg1=\(.*\) arg2=\(.*\) arg3=\(.*\) arg4=\(.*\)/\1 \2 \3 \4/'`
+  ARGS=`grep "testprobe" trace | head -n 1 | sed -e 's/.* arg1=\(.*\) arg2=\(.*\) arg3=\(.*\) arg4=\(.*\)/\1 \2 \3 \4/'`
   check_types $ARGS $width
 
   : "Clear event for next loop"
index 7650a82db3f571d1ae9355e7edd6deb2812688cc..df5072815b87e450fbf0b8a32b3d3578f97a8d78 100644 (file)
@@ -5,6 +5,8 @@
 [ -f kprobe_events ] || exit_unsupported # this is configurable
 grep "function" available_tracers || exit_unsupported # this is configurable
 
+check_filter_file set_ftrace_filter
+
 # prepare
 echo nop > current_tracer
 echo _do_fork > set_ftrace_filter
index 0bb80619db580af1dcb23ff8fde3235d20a2c825..32bdc978a711c1a309bdd2702f779f5e8e60ac82 100644 (file)
@@ -1,13 +1,13 @@
 # SPDX-License-Identifier: GPL-2.0
 
-MOUNT_CFLAGS := $(shell pkg-config --cflags mount 2>/dev/null)
-MOUNT_LDLIBS := $(shell pkg-config --libs mount 2>/dev/null)
-ifeq ($(MOUNT_LDLIBS),)
-MOUNT_LDLIBS := -lmount -I/usr/include/libmount
+VAR_CFLAGS := $(shell pkg-config --cflags mount 2>/dev/null)
+VAR_LDLIBS := $(shell pkg-config --libs mount 2>/dev/null)
+ifeq ($(VAR_LDLIBS),)
+VAR_LDLIBS := -lmount -I/usr/include/libmount
 endif
 
-CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(MOUNT_CFLAGS)
-LDLIBS += $(MOUNT_LDLIBS)
+CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(VAR_CFLAGS)
+LDLIBS += $(VAR_LDLIBS)
 
 TEST_PROGS := gpio-mockup.sh
 TEST_FILES := gpio-mockup-sysfs.sh
index 7340fd6a9a9f2cbd0d0f16ad7388d674b0ae0fb5..39f0fa2a8fd63ff51bfeb062831d6e95aaea4b0e 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 CFLAGS := $(CFLAGS) -Wall -D_GNU_SOURCE
-LDLIBS := $(LDLIBS) -lm
+LDLIBS += -lm
 
 uname_M := $(shell uname -m 2>/dev/null || echo not)
 ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
index 4c156aeab6b80c011ab6ad503c9521bc10341c7b..5ec4d9e18806cd81b547d5f64d2137af0a3249b5 100644 (file)
@@ -137,7 +137,7 @@ int dump_queue(struct msgque_data *msgque)
        for (kern_id = 0; kern_id < 256; kern_id++) {
                ret = msgctl(kern_id, MSG_STAT, &ds);
                if (ret < 0) {
-                       if (errno == -EINVAL)
+                       if (errno == EINVAL)
                                continue;
                        printf("Failed to get stats for IPC queue with id %d\n",
                                        kern_id);
index e84d901f85672fdc7df7fe9e947f3068f398d1bc..676b3a8b114d76c9db133df011d9174e51cd0c6c 100644 (file)
@@ -33,7 +33,7 @@ tap_timeout()
 {
        # Make sure tests will time out if utility is available.
        if [ -x /usr/bin/timeout ] ; then
-               /usr/bin/timeout "$kselftest_timeout" "$1"
+               /usr/bin/timeout --foreground "$kselftest_timeout" "$1"
        else
                "$1"
        fi
diff --git a/tools/testing/selftests/kselftest_deps.sh b/tools/testing/selftests/kselftest_deps.sh
new file mode 100755 (executable)
index 0000000..bbc0464
--- /dev/null
@@ -0,0 +1,272 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# kselftest_deps.sh
+#
+# Checks for kselftest build dependencies on the build system.
+# Copyright (c) 2020 Shuah Khan <skhan@linuxfoundation.org>
+#
+#
+
+usage()
+{
+
+echo -e "Usage: $0 -[p] <compiler> [test_name]\n"
+echo -e "\tkselftest_deps.sh [-p] gcc"
+echo -e "\tkselftest_deps.sh [-p] gcc vm"
+echo -e "\tkselftest_deps.sh [-p] aarch64-linux-gnu-gcc"
+echo -e "\tkselftest_deps.sh [-p] aarch64-linux-gnu-gcc vm\n"
+echo "- Should be run in selftests directory in the kernel repo."
+echo "- Checks if Kselftests can be built/cross-built on a system."
+echo "- Parses all test/sub-test Makefile to find library dependencies."
+echo "- Runs compile test on a trivial C file with LDLIBS specified"
+echo "  in the test Makefiles to identify missing library dependencies."
+echo "- Prints suggested target list for a system filtering out tests"
+echo "  failed the build dependency check from the TARGETS in Selftests"
+echo "  main Makefile when optional -p is specified."
+echo "- Prints pass/fail dependency check for each tests/sub-test."
+echo "- Prints pass/fail targets and libraries."
+echo "- Default: runs dependency checks on all tests."
+echo "- Optional test name can be specified to check dependencies for it."
+exit 1
+
+}
+
+# Start main()
+main()
+{
+
+base_dir=`pwd`
+# Make sure we're in the selftests top-level directory.
+if [ $(basename "$base_dir") !=  "selftests" ]; then
+       echo -e "\tPlease run $0 in"
+       echo -e "\ttools/testing/selftests directory ..."
+       exit 1
+fi
+
+print_targets=0
+
+while getopts "p" arg; do
+    case $arg in
+        p)
+               print_targets=1
+       shift;;
+    esac
+done
+
+if [ $# -eq 0 ]
+then
+       usage
+fi
+
+# Compiler
+CC=$1
+
+tmp_file=$(mktemp).c
+trap "rm -f $tmp_file.o $tmp_file $tmp_file.bin" EXIT
+#echo $tmp_file
+
+pass=$(mktemp).out
+trap "rm -f $pass" EXIT
+#echo $pass
+
+fail=$(mktemp).out
+trap "rm -f $fail" EXIT
+#echo $fail
+
+# Generate tmp source fire for compile test
+cat << "EOF" > $tmp_file
+int main()
+{
+}
+EOF
+
+# Save results
+total_cnt=0
+fail_trgts=()
+fail_libs=()
+fail_cnt=0
+pass_trgts=()
+pass_libs=()
+pass_cnt=0
+
+# Get all TARGETS from selftests Makefile
+targets=$(egrep "^TARGETS +|^TARGETS =" Makefile | cut -d "=" -f2)
+
+# Single test case
+if [ $# -eq 2 ]
+then
+       test=$2/Makefile
+
+       l1_test $test
+       l2_test $test
+       l3_test $test
+
+       print_results $1 $2
+       exit $?
+fi
+
+# Level 1: LDLIBS set static.
+#
+# Find all LDLIBS set statically for all executables built by a Makefile
+# and filter out VAR_LDLIBS to discard the following:
+#      gpio/Makefile:LDLIBS += $(VAR_LDLIBS)
+# Append space at the end of the list to append more tests.
+
+l1_tests=$(grep -r --include=Makefile "^LDLIBS" | \
+               grep -v "VAR_LDLIBS" | awk -F: '{print $1}')
+
+# Level 2: LDLIBS set dynamically.
+#
+# Level 2
+# Some tests have multiple valid LDLIBS lines for individual sub-tests
+# that need dependency checks. Find them and append them to the tests
+# e.g: vm/Makefile:$(OUTPUT)/userfaultfd: LDLIBS += -lpthread
+# Filter out VAR_LDLIBS to discard the following:
+#      memfd/Makefile:$(OUTPUT)/fuse_mnt: LDLIBS += $(VAR_LDLIBS)
+# Append space at the end of the list to append more tests.
+
+l2_tests=$(grep -r --include=Makefile ": LDLIBS" | \
+               grep -v "VAR_LDLIBS" | awk -F: '{print $1}')
+
+# Level 3
+# gpio,  memfd and others use pkg-config to find mount and fuse libs
+# respectively and save it in VAR_LDLIBS. If pkg-config doesn't find
+# any, VAR_LDLIBS set to default.
+# Use the default value and filter out pkg-config for dependency check.
+# e.g:
+# gpio/Makefile
+#      VAR_LDLIBS := $(shell pkg-config --libs mount) 2>/dev/null)
+# memfd/Makefile
+#      VAR_LDLIBS := $(shell pkg-config fuse --libs 2>/dev/null)
+
+l3_tests=$(grep -r --include=Makefile "^VAR_LDLIBS" | \
+               grep -v "pkg-config" | awk -F: '{print $1}')
+
+#echo $l1_tests
+#echo $l2_1_tests
+#echo $l3_tests
+
+all_tests
+print_results $1 $2
+
+exit $?
+}
+# end main()
+
+all_tests()
+{
+       for test in $l1_tests; do
+               l1_test $test
+       done
+
+       for test in $l2_tests; do
+               l2_test $test
+       done
+
+       for test in $l3_tests; do
+               l3_test $test
+       done
+}
+
+# Use same parsing used for l1_tests and pick libraries this time.
+l1_test()
+{
+       test_libs=$(grep --include=Makefile "^LDLIBS" $test | \
+                       grep -v "VAR_LDLIBS" | \
+                       sed -e 's/\:/ /' | \
+                       sed -e 's/+/ /' | cut -d "=" -f 2)
+
+       check_libs $test $test_libs
+}
+
+# Use same parsing used for l2__tests and pick libraries this time.
+l2_test()
+{
+       test_libs=$(grep --include=Makefile ": LDLIBS" $test | \
+                       grep -v "VAR_LDLIBS" | \
+                       sed -e 's/\:/ /' | sed -e 's/+/ /' | \
+                       cut -d "=" -f 2)
+
+       check_libs $test $test_libs
+}
+
+l3_test()
+{
+       test_libs=$(grep --include=Makefile "^VAR_LDLIBS" $test | \
+                       grep -v "pkg-config" | sed -e 's/\:/ /' |
+                       sed -e 's/+/ /' | cut -d "=" -f 2)
+
+       check_libs $test $test_libs
+}
+
+check_libs()
+{
+
+if [[ ! -z "${test_libs// }" ]]
+then
+
+       #echo $test_libs
+
+       for lib in $test_libs; do
+
+       let total_cnt+=1
+       $CC -o $tmp_file.bin $lib $tmp_file > /dev/null 2>&1
+       if [ $? -ne 0 ]; then
+               echo "FAIL: $test dependency check: $lib" >> $fail
+               let fail_cnt+=1
+               fail_libs+="$lib "
+               fail_target=$(echo "$test" | cut -d "/" -f1)
+               fail_trgts+="$fail_target "
+               targets=$(echo "$targets" | grep -v "$fail_target")
+       else
+               echo "PASS: $test dependency check passed $lib" >> $pass
+               let pass_cnt+=1
+               pass_libs+="$lib "
+               pass_trgts+="$(echo "$test" | cut -d "/" -f1) "
+       fi
+
+       done
+fi
+}
+
+print_results()
+{
+       echo -e "========================================================";
+       echo -e "Kselftest Dependency Check for [$0 $1 $2] results..."
+
+       if [ $print_targets -ne 0 ]
+       then
+       echo -e "Suggested Selftest Targets for your configuration:"
+       echo -e "$targets";
+       fi
+
+       echo -e "========================================================";
+       echo -e "Checked tests defining LDLIBS dependencies"
+       echo -e "--------------------------------------------------------";
+       echo -e "Total tests with Dependencies:"
+       echo -e "$total_cnt Pass: $pass_cnt Fail: $fail_cnt";
+
+       if [ $pass_cnt -ne 0 ]; then
+       echo -e "--------------------------------------------------------";
+       cat $pass
+       echo -e "--------------------------------------------------------";
+       echo -e "Targets passed build dependency check on system:"
+       echo -e "$(echo "$pass_trgts" | xargs -n1 | sort -u | xargs)"
+       fi
+
+       if [ $fail_cnt -ne 0 ]; then
+       echo -e "--------------------------------------------------------";
+       cat $fail
+       echo -e "--------------------------------------------------------";
+       echo -e "Targets failed build dependency check on system:"
+       echo -e "$(echo "$fail_trgts" | xargs -n1 | sort -u | xargs)"
+       echo -e "--------------------------------------------------------";
+       echo -e "Missing libraries system"
+       echo -e "$(echo "$fail_libs" | xargs -n1 | sort -u | xargs)"
+       fi
+
+       echo -e "--------------------------------------------------------";
+       echo -e "========================================================";
+}
+
+main "$@"
index 2902f6a78f8a313fa1da2511984bc47579a46916..2bb8c81fc0b44005d7533f739846d7d9c605805c 100644 (file)
@@ -705,7 +705,7 @@ static void __timeout_handler(int sig, siginfo_t *info, void *ucontext)
        /* Sanity check handler execution environment. */
        if (!t) {
                fprintf(TH_LOG_STREAM,
-                       "no active test in SIGARLM handler!?\n");
+                       "no active test in SIGALRM handler!?\n");
                abort();
        }
        if (sig != SIGALRM || sig != info->si_signo) {
@@ -731,7 +731,7 @@ void __wait_for_test(struct __test_metadata *t)
        if (sigaction(SIGALRM, &action, &saved_action)) {
                t->passed = 0;
                fprintf(TH_LOG_STREAM,
-                       "%s: unable to install SIGARLM handler\n",
+                       "%s: unable to install SIGALRM handler\n",
                        t->name);
                return;
        }
@@ -743,7 +743,7 @@ void __wait_for_test(struct __test_metadata *t)
        if (sigaction(SIGALRM, &saved_action, NULL)) {
                t->passed = 0;
                fprintf(TH_LOG_STREAM,
-                       "%s: unable to uninstall SIGARLM handler\n",
+                       "%s: unable to uninstall SIGALRM handler\n",
                        t->name);
                return;
        }
index 712a2ddd2a2711a8271706fd2d37501ae3a3386d..b728c0a0f9b212e01fee31177988b63c15661d69 100644 (file)
@@ -5,8 +5,34 @@ all:
 
 top_srcdir = ../../../..
 KSFT_KHDR_INSTALL := 1
+
+# For cross-builds to work, UNAME_M has to map to ARCH and arch specific
+# directories and targets in this Makefile. "uname -m" doesn't map to
+# arch specific sub-directory names.
+#
+# UNAME_M variable to used to run the compiles pointing to the right arch
+# directories and build the right targets for these supported architectures.
+#
+# TEST_GEN_PROGS and LIBKVM are set using UNAME_M variable.
+# LINUX_TOOL_ARCH_INCLUDE is set using ARCH variable.
+#
+# x86_64 targets are named to include x86_64 as a suffix and directories
+# for includes are in x86_64 sub-directory. s390x and aarch64 follow the
+# same convention. "uname -m" doesn't result in the correct mapping for
+# s390x and aarch64.
+#
+# No change necessary for x86_64
 UNAME_M := $(shell uname -m)
 
+# Set UNAME_M for arm64 compile/install to work
+ifeq ($(ARCH),arm64)
+       UNAME_M := aarch64
+endif
+# Set UNAME_M s390x compile/install to work
+ifeq ($(ARCH),s390)
+       UNAME_M := s390x
+endif
+
 LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/sparsebit.c lib/test_util.c
 LIBKVM_x86_64 = lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/svm.c lib/x86_64/ucall.c
 LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c
@@ -53,7 +79,7 @@ LIBKVM += $(LIBKVM_$(UNAME_M))
 INSTALL_HDR_PATH = $(top_srcdir)/usr
 LINUX_HDR_PATH = $(INSTALL_HDR_PATH)/include/
 LINUX_TOOL_INCLUDE = $(top_srcdir)/tools/include
-LINUX_TOOL_ARCH_INCLUDE = $(top_srcdir)/tools/arch/x86/include
+LINUX_TOOL_ARCH_INCLUDE = $(top_srcdir)/tools/arch/$(ARCH)/include
 CFLAGS += -Wall -Wstrict-prototypes -Wuninitialized -O2 -g -std=gnu99 \
        -fno-stack-protector -fno-PIE -I$(LINUX_TOOL_INCLUDE) \
        -I$(LINUX_TOOL_ARCH_INCLUDE) -I$(LINUX_HDR_PATH) -Iinclude \
@@ -84,6 +110,7 @@ $(LIBKVM_OBJ): $(OUTPUT)/%.o: %.c
 $(OUTPUT)/libkvm.a: $(LIBKVM_OBJ)
        $(AR) crs $@ $^
 
+x := $(shell mkdir -p $(sort $(dir $(TEST_GEN_PROGS))))
 all: $(STATIC_LIBS)
 $(TEST_GEN_PROGS): $(STATIC_LIBS)
 
index d8f4d6bfe05d731ca7c2fc2c0b45977f90a479da..a034438b62662b4c103d46b93f854bd9999a9490 100644 (file)
@@ -219,8 +219,8 @@ struct hv_enlightened_vmcs {
 #define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_MASK \
                (~((1ull << HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT) - 1))
 
-struct hv_enlightened_vmcs *current_evmcs;
-struct hv_vp_assist_page *current_vp_assist;
+extern struct hv_enlightened_vmcs *current_evmcs;
+extern struct hv_vp_assist_page *current_vp_assist;
 
 int vcpu_enable_evmcs(struct kvm_vm *vm, int vcpu_id);
 
index 6f17f69394be53eb40466cab71b975f59296bfe3..4ae104f6ce69f3c9285b81042ff82f9f024d4b16 100644 (file)
@@ -17,6 +17,9 @@
 
 bool enable_evmcs;
 
+struct hv_enlightened_vmcs *current_evmcs;
+struct hv_vp_assist_page *current_vp_assist;
+
 struct eptPageTableEntry {
        uint64_t readable:1;
        uint64_t writable:1;
index 0a15f9e23431228eb8bd19798305afd1914683a1..4da8b565fa326e54720eb6b8041b997ef98f3b91 100644 (file)
@@ -4,14 +4,25 @@ CFLAGS += -I../../../../include/uapi/
 CFLAGS += -I../../../../include/
 CFLAGS += -I../../../../usr/include/
 
-TEST_GEN_PROGS := memfd_test fuse_test fuse_mnt
+TEST_GEN_PROGS := memfd_test
 TEST_PROGS := run_fuse_test.sh run_hugetlbfs_test.sh
+TEST_GEN_FILES := fuse_test fuse_mnt
 
-fuse_mnt.o: CFLAGS += $(shell pkg-config fuse --cflags)
+VAR_CFLAGS := $(shell pkg-config fuse --cflags 2>/dev/null)
+ifeq ($(VAR_CFLAGS),)
+VAR_CFLAGS := -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse
+endif
+
+VAR_LDLIBS := $(shell pkg-config fuse --libs 2>/dev/null)
+ifeq ($(VAR_LDLIBS),)
+VAR_LDLIBS := -lfuse -pthread
+endif
+
+fuse_mnt.o: CFLAGS += $(VAR_CFLAGS)
 
 include ../lib.mk
 
-$(OUTPUT)/fuse_mnt: LDLIBS += $(shell pkg-config fuse --libs)
+$(OUTPUT)/fuse_mnt: LDLIBS += $(VAR_LDLIBS)
 
 $(OUTPUT)/memfd_test: memfd_test.c common.c
 $(OUTPUT)/fuse_test: fuse_test.c common.c
index 796670ebc65b37c66ee3c865bb6a90f5881267c2..6560ed796ac48e96fe3a5fb28c76ade7ac186b3a 100755 (executable)
@@ -749,6 +749,29 @@ ipv4_fcnal_runtime()
        run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
        log_test $? 0 "Ping - multipath"
 
+       run_cmd "$IP ro delete 172.16.101.1/32 nhid 122"
+
+       #
+       # multiple default routes
+       # - tests fib_select_default
+       run_cmd "$IP nexthop add id 501 via 172.16.1.2 dev veth1"
+       run_cmd "$IP ro add default nhid 501"
+       run_cmd "$IP ro add default via 172.16.1.3 dev veth1 metric 20"
+       run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
+       log_test $? 0 "Ping - multiple default routes, nh first"
+
+       # flip the order
+       run_cmd "$IP ro del default nhid 501"
+       run_cmd "$IP ro del default via 172.16.1.3 dev veth1 metric 20"
+       run_cmd "$IP ro add default via 172.16.1.2 dev veth1 metric 20"
+       run_cmd "$IP nexthop replace id 501 via 172.16.1.3 dev veth1"
+       run_cmd "$IP ro add default nhid 501 metric 20"
+       run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
+       log_test $? 0 "Ping - multiple default routes, nh second"
+
+       run_cmd "$IP nexthop delete nhid 501"
+       run_cmd "$IP ro del default"
+
        #
        # IPv4 with blackhole nexthops
        #
index b7616704b55e982f20d55c768def568f54e0efc1..84205c3a55ebed11ddbbf307d771338e0f4d1ac5 100755 (executable)
@@ -618,16 +618,22 @@ fib_nexthop_test()
 
 fib_suppress_test()
 {
+       echo
+       echo "FIB rule with suppress_prefixlength"
+       setup
+
        $IP link add dummy1 type dummy
        $IP link set dummy1 up
        $IP -6 route add default dev dummy1
        $IP -6 rule add table main suppress_prefixlength 0
-       ping -f -c 1000 -W 1 1234::1 || true
+       ping -f -c 1000 -W 1 1234::1 >/dev/null 2>&1
        $IP -6 rule del table main suppress_prefixlength 0
        $IP link del dummy1
 
        # If we got here without crashing, we're good.
-       return 0
+       log_test 0 0 "FIB rule suppress test"
+
+       cleanup
 }
 
 ################################################################################
index 35505b31e5cc092453ea7b72d9dba45bed2d6549..4555f88252bafd31d6c225590316f03b08d3b132 100644 (file)
@@ -165,9 +165,10 @@ void *child_thread(void *arg)
                        socklen_t zc_len = sizeof(zc);
                        int res;
 
+                       memset(&zc, 0, sizeof(zc));
                        zc.address = (__u64)((unsigned long)addr);
                        zc.length = chunk_size;
-                       zc.recv_skip_hint = 0;
+
                        res = getsockopt(fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE,
                                         &zc, &zc_len);
                        if (res == -1)
@@ -281,12 +282,14 @@ static void setup_sockaddr(int domain, const char *str_addr,
 static void do_accept(int fdlisten)
 {
        pthread_attr_t attr;
+       int rcvlowat;
 
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
+       rcvlowat = chunk_size;
        if (setsockopt(fdlisten, SOL_SOCKET, SO_RCVLOWAT,
-                      &chunk_size, sizeof(chunk_size)) == -1) {
+                      &rcvlowat, sizeof(rcvlowat)) == -1) {
                perror("setsockopt SO_RCVLOWAT");
        }
 
index 89fb3e0b552ec16e24b44f90f82e5047e22384d7..c0aa46ce14f6ce088b4c8b288b94aeeaf4e3fcac 100644 (file)
@@ -2803,12 +2803,13 @@ TEST(syscall_restart)
                         offsetof(struct seccomp_data, nr)),
 
 #ifdef __NR_sigreturn
-               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_sigreturn, 6, 0),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_sigreturn, 7, 0),
 #endif
-               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 5, 0),
-               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_exit, 4, 0),
-               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_rt_sigreturn, 3, 0),
-               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_nanosleep, 4, 0),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 6, 0),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_exit, 5, 0),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_rt_sigreturn, 4, 0),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_nanosleep, 5, 0),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_clock_nanosleep, 4, 0),
                BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_restart_syscall, 4, 0),
 
                /* Allow __NR_write for easy logging. */
@@ -2895,7 +2896,8 @@ TEST(syscall_restart)
        ASSERT_EQ(PTRACE_EVENT_SECCOMP, (status >> 16));
        ASSERT_EQ(0, ptrace(PTRACE_GETEVENTMSG, child_pid, NULL, &msg));
        ASSERT_EQ(0x100, msg);
-       EXPECT_EQ(__NR_nanosleep, get_syscall(_metadata, child_pid));
+       ret = get_syscall(_metadata, child_pid);
+       EXPECT_TRUE(ret == __NR_nanosleep || ret == __NR_clock_nanosleep);
 
        /* Might as well check siginfo for sanity while we're here. */
        ASSERT_EQ(0, ptrace(PTRACE_GETSIGINFO, child_pid, NULL, &info));
index e566c70e64a1971e653a2922012e5e420a85b193..a3e43189d94003db8170a91f7d9b71ab4f1a407d 100755 (executable)
@@ -713,9 +713,8 @@ def set_operation_mode(pm, parser, args, remaining):
         exit(0)
 
     if args.list:
-        if args.list:
-            list_test_cases(alltests)
-            exit(0)
+        list_test_cases(alltests)
+        exit(0)
 
     if len(alltests):
         req_plugins = pm.get_required_plugins(alltests)
index b630c7b5950a960b95a9bb0aeda79e41924ca989..8155c2ea7ccbb6ed1b9685f3c602105eb2c26173 100755 (executable)
@@ -1,17 +1,8 @@
 #!/bin/bash
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
-self.flags = flags
 
-# Kselftest framework requirement - SKIP code is 4.
-ksft_skip=4
-
-
-if [ -f /dev/tpm0 ] ; then
-       python -m unittest -v tpm2_tests.SmokeTest
-       python -m unittest -v tpm2_tests.AsyncTest
-else
-       exit $ksft_skip
-fi
+python -m unittest -v tpm2_tests.SmokeTest
+python -m unittest -v tpm2_tests.AsyncTest
 
 CLEAR_CMD=$(which tpm2_clear)
 if [ -n $CLEAR_CMD ]; then
index 180b469c53b47d4e0e2e3d7c6bb2ecc7331065e2..a6f5e346635e560db7c7767b22f32f760922600a 100755 (executable)
@@ -1,11 +1,4 @@
 #!/bin/bash
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
 
-# Kselftest framework requirement - SKIP code is 4.
-ksft_skip=4
-
-if [ -f /dev/tpmrm0 ] ; then
-       python -m unittest -v tpm2_tests.SpaceTest
-else
-       exit $ksft_skip
-fi
+python -m unittest -v tpm2_tests.SpaceTest
index d31db052dff6a5f62b70e5f01a03909d0a2e5cfb..6998877f707e84df504a605ea6251ff307f130c1 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for vm selftests
 uname_M := $(shell uname -m 2>/dev/null || echo not)
-ARCH ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/')
+MACHINE ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/')
 
 CFLAGS = -Wall -I ../../../../usr/include $(EXTRA_CFLAGS)
 LDLIBS = -lrt
@@ -20,7 +20,7 @@ TEST_GEN_FILES += thuge-gen
 TEST_GEN_FILES += transhuge-stress
 TEST_GEN_FILES += userfaultfd
 
-ifneq (,$(filter $(ARCH),arm64 ia64 mips64 parisc64 ppc64 riscv64 s390x sh64 sparc64 x86_64))
+ifneq (,$(filter $(MACHINE),arm64 ia64 mips64 parisc64 ppc64 ppc64le riscv64 s390x sh64 sparc64 x86_64))
 TEST_GEN_FILES += va_128TBswitch
 TEST_GEN_FILES += virtual_address_range
 TEST_GEN_FILES += write_to_hugetlbfs
index 665009ebfba4a9feabd1b96e61008bb50c780d29..76ca5e7a3951acb9d65bf446b7432f8bc02918b5 100755 (executable)
@@ -59,7 +59,7 @@ else
 fi
 
 #filter 64bit architectures
-ARCH64STR="arm64 ia64 mips64 parisc64 ppc64 riscv64 s390x sh64 sparc64 x86_64"
+ARCH64STR="arm64 ia64 mips64 parisc64 ppc64 ppc64le riscv64 s390x sh64 sparc64 x86_64"
 if [ -z $ARCH ]; then
   ARCH=`uname -m 2>/dev/null | sed -e 's/aarch64.*/arm64/'`
 fi
index 936e1ca9410ec16d6935e0b4dd15cfae0d373bb7..17a1f53ceba01aa7536fd6f57029bbb6b2918ea6 100755 (executable)
@@ -48,8 +48,11 @@ cleanup() {
        exec 2>/dev/null
        printf "$orig_message_cost" > /proc/sys/net/core/message_cost
        ip0 link del dev wg0
+       ip0 link del dev wg1
        ip1 link del dev wg0
+       ip1 link del dev wg1
        ip2 link del dev wg0
+       ip2 link del dev wg1
        local to_kill="$(ip netns pids $netns0) $(ip netns pids $netns1) $(ip netns pids $netns2)"
        [[ -n $to_kill ]] && kill $to_kill
        pp ip netns del $netns1
@@ -77,18 +80,20 @@ ip0 link set wg0 netns $netns2
 key1="$(pp wg genkey)"
 key2="$(pp wg genkey)"
 key3="$(pp wg genkey)"
+key4="$(pp wg genkey)"
 pub1="$(pp wg pubkey <<<"$key1")"
 pub2="$(pp wg pubkey <<<"$key2")"
 pub3="$(pp wg pubkey <<<"$key3")"
+pub4="$(pp wg pubkey <<<"$key4")"
 psk="$(pp wg genpsk)"
 [[ -n $key1 && -n $key2 && -n $psk ]]
 
 configure_peers() {
        ip1 addr add 192.168.241.1/24 dev wg0
-       ip1 addr add fd00::1/24 dev wg0
+       ip1 addr add fd00::1/112 dev wg0
 
        ip2 addr add 192.168.241.2/24 dev wg0
-       ip2 addr add fd00::2/24 dev wg0
+       ip2 addr add fd00::2/112 dev wg0
 
        n1 wg set wg0 \
                private-key <(echo "$key1") \
@@ -230,9 +235,38 @@ n1 ping -W 1 -c 1 192.168.241.2
 n1 wg set wg0 private-key <(echo "$key3")
 n2 wg set wg0 peer "$pub3" preshared-key <(echo "$psk") allowed-ips 192.168.241.1/32 peer "$pub1" remove
 n1 ping -W 1 -c 1 192.168.241.2
+n2 wg set wg0 peer "$pub3" remove
+
+# Test that we can route wg through wg
+ip1 addr flush dev wg0
+ip2 addr flush dev wg0
+ip1 addr add fd00::5:1/112 dev wg0
+ip2 addr add fd00::5:2/112 dev wg0
+n1 wg set wg0 private-key <(echo "$key1") peer "$pub2" preshared-key <(echo "$psk") allowed-ips fd00::5:2/128 endpoint 127.0.0.1:2
+n2 wg set wg0 private-key <(echo "$key2") listen-port 2 peer "$pub1" preshared-key <(echo "$psk") allowed-ips fd00::5:1/128 endpoint 127.212.121.99:9998
+ip1 link add wg1 type wireguard
+ip2 link add wg1 type wireguard
+ip1 addr add 192.168.241.1/24 dev wg1
+ip1 addr add fd00::1/112 dev wg1
+ip2 addr add 192.168.241.2/24 dev wg1
+ip2 addr add fd00::2/112 dev wg1
+ip1 link set mtu 1340 up dev wg1
+ip2 link set mtu 1340 up dev wg1
+n1 wg set wg1 listen-port 5 private-key <(echo "$key3") peer "$pub4" allowed-ips 192.168.241.2/32,fd00::2/128 endpoint [fd00::5:2]:5
+n2 wg set wg1 listen-port 5 private-key <(echo "$key4") peer "$pub3" allowed-ips 192.168.241.1/32,fd00::1/128 endpoint [fd00::5:1]:5
+tests
+# Try to set up a routing loop between the two namespaces
+ip1 link set netns $netns0 dev wg1
+ip0 addr add 192.168.241.1/24 dev wg1
+ip0 link set up dev wg1
+n0 ping -W 1 -c 1 192.168.241.2
+n1 wg set wg0 peer "$pub2" endpoint 192.168.241.2:7
+ip2 link del wg0
+ip2 link del wg1
+! n0 ping -W 1 -c 10 -f 192.168.241.2 || false # Should not crash kernel
 
+ip0 link del wg1
 ip1 link del wg0
-ip2 link del wg0
 
 # Test using NAT. We now change the topology to this:
 # ┌────────────────────────────────────────┐    ┌────────────────────────────────────────────────┐     ┌────────────────────────────────────────┐
@@ -282,6 +316,20 @@ pp sleep 3
 n2 ping -W 1 -c 1 192.168.241.1
 n1 wg set wg0 peer "$pub2" persistent-keepalive 0
 
+# Test that onion routing works, even when it loops
+n1 wg set wg0 peer "$pub3" allowed-ips 192.168.242.2/32 endpoint 192.168.241.2:5
+ip1 addr add 192.168.242.1/24 dev wg0
+ip2 link add wg1 type wireguard
+ip2 addr add 192.168.242.2/24 dev wg1
+n2 wg set wg1 private-key <(echo "$key3") listen-port 5 peer "$pub1" allowed-ips 192.168.242.1/32
+ip2 link set wg1 up
+n1 ping -W 1 -c 1 192.168.242.2
+ip2 link del wg1
+n1 wg set wg0 peer "$pub3" endpoint 192.168.242.2:5
+! n1 ping -W 1 -c 1 192.168.242.2 || false # Should not crash kernel
+n1 wg set wg0 peer "$pub3" remove
+ip1 addr del 192.168.242.1/24 dev wg0
+
 # Do a wg-quick(8)-style policy routing for the default route, making sure vethc has a v6 address to tease out bugs.
 ip1 -6 addr add fc00::9/96 dev vethc
 ip1 -6 route add default via fc00::1
index 990c510a9cfa5f4e5ac279dd78cc79725c1a8d9e..f52f1e2bc7f64dba3c4d24d276fde663fed03909 100644 (file)
@@ -10,3 +10,4 @@ CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=hvc0 wg.success=hvc1"
 CONFIG_SECTION_MISMATCH_WARN_ONLY=y
 CONFIG_FRAME_WARN=1280
+CONFIG_THREAD_SHIFT=14
index 5909e7ef2a5c5c1a30b40e4c7d58ff585335e756..9803dbb54181ce8cac6111d83b8c36c58331d959 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_KASAN=y
 CONFIG_KASAN_INLINE=y
 CONFIG_UBSAN=y
 CONFIG_UBSAN_SANITIZE_ALL=y
-CONFIG_UBSAN_NO_ALIGNMENT=y
 CONFIG_UBSAN_NULL=y
 CONFIG_DEBUG_KMEMLEAK=y
 CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=8192
index f33f32f1d20802e678e5e85f6bd23d298b3705fe..b587b9a7a124bb2fcda464c6efcc284dd4c37742 100644 (file)
@@ -4,7 +4,7 @@ test: virtio_test vringh_test
 virtio_test: virtio_ring.o virtio_test.o
 vringh_test: vringh_test.o vringh.o virtio_ring.o
 
-CFLAGS += -g -O2 -Werror -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE
+CFLAGS += -g -O2 -Werror -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -include ../../include/linux/kconfig.h
 vpath %.c ../../drivers/virtio ../../drivers/vhost
 mod:
        ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test V=${V}
@@ -22,7 +22,8 @@ OOT_CONFIGS=\
        CONFIG_VHOST=m \
        CONFIG_VHOST_NET=n \
        CONFIG_VHOST_SCSI=n \
-       CONFIG_VHOST_VSOCK=n
+       CONFIG_VHOST_VSOCK=n \
+       CONFIG_VHOST_RING=n
 OOT_BUILD=KCFLAGS="-I "${OOT_VHOST} ${MAKE} -C ${OOT_KSRC} V=${V}
 oot-build:
        echo "UNSUPPORTED! Don't use the resulting modules in production!"
index d0351f83aebed9f1ce87c390e586ce45c7068337..04d563fc9b95ca0e80d323e271473492400f7273 100644 (file)
@@ -1,4 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0 */
+#include <stdlib.h>
 #if defined(__i386__) || defined(__x86_64__)
 #define barrier() asm volatile("" ::: "memory")
 #define virt_mb() __sync_synchronize()
diff --git a/tools/virtio/generated/autoconf.h b/tools/virtio/generated/autoconf.h
new file mode 100644 (file)
index 0000000..e69de29
index 903dc9c4bd115f196538138da3b32f30bcbd807e..2c51bccb97bb27ee816e64644c41b4c00f967796 100644 (file)
@@ -7,4 +7,5 @@
 
 #define READ_ONCE(var) (*((volatile typeof(var) *)(&(var))))
 
+#define __aligned(x) __attribute((__aligned__(x)))
 #endif
index 20f6cf04377f0c257aeb4bacb3133b6a35e9e9b6..9860622cbb151126571ef0962cdab5735c59c5dd 100644 (file)
@@ -1,6 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for vm tools
 #
+include ../scripts/Makefile.include
+
 TARGETS=page-types slabinfo page_owner_sort
 
 LIB_DIR = ../lib/api
index d31f267961e75a956174964e445338a74abc757b..25c0e47d57cbe314ff9b993c4456c0d8fd65a0d1 100644 (file)
@@ -125,12 +125,16 @@ static void __hyp_text kvm_adjust_itstate(struct kvm_vcpu *vcpu)
  */
 void __hyp_text kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr)
 {
+       u32 pc = *vcpu_pc(vcpu);
        bool is_thumb;
 
        is_thumb = !!(*vcpu_cpsr(vcpu) & PSR_AA32_T_BIT);
        if (is_thumb && !is_wide_instr)
-               *vcpu_pc(vcpu) += 2;
+               pc += 2;
        else
-               *vcpu_pc(vcpu) += 4;
+               pc += 4;
+
+       *vcpu_pc(vcpu) = pc;
+
        kvm_adjust_itstate(vcpu);
 }
index 14a162e295a947f70cf5b6bd8e573af7b2d628c8..ae364716ee40c1140ea4e6e9d12e964728a94859 100644 (file)
@@ -186,6 +186,33 @@ static void kvm_psci_system_reset(struct kvm_vcpu *vcpu)
        kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET);
 }
 
+static void kvm_psci_narrow_to_32bit(struct kvm_vcpu *vcpu)
+{
+       int i;
+
+       /*
+        * Zero the input registers' upper 32 bits. They will be fully
+        * zeroed on exit, so we're fine changing them in place.
+        */
+       for (i = 1; i < 4; i++)
+               vcpu_set_reg(vcpu, i, lower_32_bits(vcpu_get_reg(vcpu, i)));
+}
+
+static unsigned long kvm_psci_check_allowed_function(struct kvm_vcpu *vcpu, u32 fn)
+{
+       switch(fn) {
+       case PSCI_0_2_FN64_CPU_SUSPEND:
+       case PSCI_0_2_FN64_CPU_ON:
+       case PSCI_0_2_FN64_AFFINITY_INFO:
+               /* Disallow these functions for 32bit guests */
+               if (vcpu_mode_is_32bit(vcpu))
+                       return PSCI_RET_NOT_SUPPORTED;
+               break;
+       }
+
+       return 0;
+}
+
 static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 {
        struct kvm *kvm = vcpu->kvm;
@@ -193,6 +220,10 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
        unsigned long val;
        int ret = 1;
 
+       val = kvm_psci_check_allowed_function(vcpu, psci_fn);
+       if (val)
+               goto out;
+
        switch (psci_fn) {
        case PSCI_0_2_FN_PSCI_VERSION:
                /*
@@ -210,12 +241,16 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
                val = PSCI_RET_SUCCESS;
                break;
        case PSCI_0_2_FN_CPU_ON:
+               kvm_psci_narrow_to_32bit(vcpu);
+               fallthrough;
        case PSCI_0_2_FN64_CPU_ON:
                mutex_lock(&kvm->lock);
                val = kvm_psci_vcpu_on(vcpu);
                mutex_unlock(&kvm->lock);
                break;
        case PSCI_0_2_FN_AFFINITY_INFO:
+               kvm_psci_narrow_to_32bit(vcpu);
+               fallthrough;
        case PSCI_0_2_FN64_AFFINITY_INFO:
                val = kvm_psci_vcpu_affinity_info(vcpu);
                break;
@@ -256,6 +291,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
                break;
        }
 
+out:
        smccc_set_retval(vcpu, val, 0, 0, 0);
        return ret;
 }
@@ -273,6 +309,10 @@ static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu)
                break;
        case PSCI_1_0_FN_PSCI_FEATURES:
                feature = smccc_get_arg1(vcpu);
+               val = kvm_psci_check_allowed_function(vcpu, feature);
+               if (val)
+                       break;
+
                switch(feature) {
                case PSCI_0_2_FN_PSCI_VERSION:
                case PSCI_0_2_FN_CPU_SUSPEND:
index a963b9d766b73a75d93a500cdaf0c2cc49ba8fdc..32e32d67a127f0e7a3b59a4e5b36d1c9c124d7b9 100644 (file)
@@ -294,8 +294,15 @@ int vgic_init(struct kvm *kvm)
                }
        }
 
-       if (vgic_has_its(kvm)) {
+       if (vgic_has_its(kvm))
                vgic_lpi_translation_cache_init(kvm);
+
+       /*
+        * If we have GICv4.1 enabled, unconditionnaly request enable the
+        * v4 support so that we get HW-accelerated vSGIs. Otherwise, only
+        * enable it if we present a virtual ITS to the guest.
+        */
+       if (vgic_supports_direct_msis(kvm)) {
                ret = vgic_v4_init(kvm);
                if (ret)
                        goto out;
@@ -348,6 +355,12 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
 
+       /*
+        * Retire all pending LPIs on this vcpu anyway as we're
+        * going to destroy it.
+        */
+       vgic_flush_pending_lpis(vcpu);
+
        INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
 }
 
@@ -359,10 +372,10 @@ static void __kvm_vgic_destroy(struct kvm *kvm)
 
        vgic_debug_destroy(kvm);
 
-       kvm_vgic_dist_destroy(kvm);
-
        kvm_for_each_vcpu(i, vcpu, kvm)
                kvm_vgic_vcpu_destroy(vcpu);
+
+       kvm_vgic_dist_destroy(kvm);
 }
 
 void kvm_vgic_destroy(struct kvm *kvm)
index d53d34a33e35d7496519c4fc234eed6cec7bcb2a..c012a52b19f5757cef32fa84af25b78c6ca744c9 100644 (file)
@@ -96,14 +96,21 @@ out_unlock:
         * We "cache" the configuration table entries in our struct vgic_irq's.
         * However we only have those structs for mapped IRQs, so we read in
         * the respective config data from memory here upon mapping the LPI.
+        *
+        * Should any of these fail, behave as if we couldn't create the LPI
+        * by dropping the refcount and returning the error.
         */
        ret = update_lpi_config(kvm, irq, NULL, false);
-       if (ret)
+       if (ret) {
+               vgic_put_irq(kvm, irq);
                return ERR_PTR(ret);
+       }
 
        ret = vgic_v3_lpi_sync_pending_status(kvm, irq);
-       if (ret)
+       if (ret) {
+               vgic_put_irq(kvm, irq);
                return ERR_PTR(ret);
+       }
 
        return irq;
 }
index 5945f062d74973d5fced21356f79fb24dc3255a0..a016f07adc2811295f33c85da86cee52f90f8c8c 100644 (file)
@@ -409,24 +409,28 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
                NULL, vgic_mmio_uaccess_write_v2_group, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
-               vgic_mmio_read_enable, vgic_mmio_write_senable, NULL, NULL, 1,
+               vgic_mmio_read_enable, vgic_mmio_write_senable,
+               NULL, vgic_uaccess_write_senable, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
-               vgic_mmio_read_enable, vgic_mmio_write_cenable, NULL, NULL, 1,
+               vgic_mmio_read_enable, vgic_mmio_write_cenable,
+               NULL, vgic_uaccess_write_cenable, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
-               vgic_mmio_read_pending, vgic_mmio_write_spending, NULL, NULL, 1,
+               vgic_mmio_read_pending, vgic_mmio_write_spending,
+               NULL, vgic_uaccess_write_spending, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
-               vgic_mmio_read_pending, vgic_mmio_write_cpending, NULL, NULL, 1,
+               vgic_mmio_read_pending, vgic_mmio_write_cpending,
+               NULL, vgic_uaccess_write_cpending, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
                vgic_mmio_read_active, vgic_mmio_write_sactive,
-               NULL, vgic_mmio_uaccess_write_sactive, 1,
+               vgic_uaccess_read_active, vgic_mmio_uaccess_write_sactive, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
                vgic_mmio_read_active, vgic_mmio_write_cactive,
-               NULL, vgic_mmio_uaccess_write_cactive, 1,
+               vgic_uaccess_read_active, vgic_mmio_uaccess_write_cactive, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
                vgic_mmio_read_priority, vgic_mmio_write_priority, NULL, NULL,
index e72dcc4542475a74fa1f890532d26cd6945fdad5..89a14ec8b33bb2009786d921759868943a152e24 100644 (file)
@@ -50,7 +50,8 @@ bool vgic_has_its(struct kvm *kvm)
 
 bool vgic_supports_direct_msis(struct kvm *kvm)
 {
-       return kvm_vgic_global_state.has_gicv4 && vgic_has_its(kvm);
+       return (kvm_vgic_global_state.has_gicv4_1 ||
+               (kvm_vgic_global_state.has_gicv4 && vgic_has_its(kvm)));
 }
 
 /*
@@ -538,10 +539,12 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
                vgic_mmio_read_group, vgic_mmio_write_group, NULL, NULL, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
-               vgic_mmio_read_enable, vgic_mmio_write_senable, NULL, NULL, 1,
+               vgic_mmio_read_enable, vgic_mmio_write_senable,
+               NULL, vgic_uaccess_write_senable, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
-               vgic_mmio_read_enable, vgic_mmio_write_cenable, NULL, NULL, 1,
+               vgic_mmio_read_enable, vgic_mmio_write_cenable,
+              NULL, vgic_uaccess_write_cenable, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
                vgic_mmio_read_pending, vgic_mmio_write_spending,
@@ -553,11 +556,11 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
                vgic_mmio_read_active, vgic_mmio_write_sactive,
-               NULL, vgic_mmio_uaccess_write_sactive, 1,
+               vgic_uaccess_read_active, vgic_mmio_uaccess_write_sactive, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
                vgic_mmio_read_active, vgic_mmio_write_cactive,
-               NULL, vgic_mmio_uaccess_write_cactive,
+               vgic_uaccess_read_active, vgic_mmio_uaccess_write_cactive,
                1, VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
                vgic_mmio_read_priority, vgic_mmio_write_priority, NULL, NULL,
@@ -609,11 +612,13 @@ static const struct vgic_register_region vgic_v3_rd_registers[] = {
        REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_IGROUPR0,
                vgic_mmio_read_group, vgic_mmio_write_group, 4,
                VGIC_ACCESS_32bit),
-       REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_ISENABLER0,
-               vgic_mmio_read_enable, vgic_mmio_write_senable, 4,
+       REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ISENABLER0,
+               vgic_mmio_read_enable, vgic_mmio_write_senable,
+               NULL, vgic_uaccess_write_senable, 4,
                VGIC_ACCESS_32bit),
-       REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_ICENABLER0,
-               vgic_mmio_read_enable, vgic_mmio_write_cenable, 4,
+       REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ICENABLER0,
+               vgic_mmio_read_enable, vgic_mmio_write_cenable,
+               NULL, vgic_uaccess_write_cenable, 4,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ISPENDR0,
                vgic_mmio_read_pending, vgic_mmio_write_spending,
@@ -625,12 +630,12 @@ static const struct vgic_register_region vgic_v3_rd_registers[] = {
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ISACTIVER0,
                vgic_mmio_read_active, vgic_mmio_write_sactive,
-               NULL, vgic_mmio_uaccess_write_sactive,
-               4, VGIC_ACCESS_32bit),
+               vgic_uaccess_read_active, vgic_mmio_uaccess_write_sactive, 4,
+               VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ICACTIVER0,
                vgic_mmio_read_active, vgic_mmio_write_cactive,
-               NULL, vgic_mmio_uaccess_write_cactive,
-               4, VGIC_ACCESS_32bit),
+               vgic_uaccess_read_active, vgic_mmio_uaccess_write_cactive, 4,
+               VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_IPRIORITYR0,
                vgic_mmio_read_priority, vgic_mmio_write_priority, 32,
                VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
index 2199302597fafa32edced522d4df282bb87008dc..b2d73fc0d1ef48091ee428f915cad6054b3c3c21 100644 (file)
@@ -184,6 +184,48 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
        }
 }
 
+int vgic_uaccess_write_senable(struct kvm_vcpu *vcpu,
+                              gpa_t addr, unsigned int len,
+                              unsigned long val)
+{
+       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+       int i;
+       unsigned long flags;
+
+       for_each_set_bit(i, &val, len * 8) {
+               struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
+               irq->enabled = true;
+               vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
+
+               vgic_put_irq(vcpu->kvm, irq);
+       }
+
+       return 0;
+}
+
+int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu,
+                              gpa_t addr, unsigned int len,
+                              unsigned long val)
+{
+       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+       int i;
+       unsigned long flags;
+
+       for_each_set_bit(i, &val, len * 8) {
+               struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
+               irq->enabled = false;
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+
+               vgic_put_irq(vcpu->kvm, irq);
+       }
+
+       return 0;
+}
+
 unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
                                     gpa_t addr, unsigned int len)
 {
@@ -219,17 +261,6 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
        return value;
 }
 
-/* Must be called with irq->irq_lock held */
-static void vgic_hw_irq_spending(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
-                                bool is_uaccess)
-{
-       if (is_uaccess)
-               return;
-
-       irq->pending_latch = true;
-       vgic_irq_set_phys_active(irq, true);
-}
-
 static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq)
 {
        return (vgic_irq_is_sgi(irq->intid) &&
@@ -240,7 +271,6 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
                              gpa_t addr, unsigned int len,
                              unsigned long val)
 {
-       bool is_uaccess = !kvm_get_running_vcpu();
        u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
        int i;
        unsigned long flags;
@@ -270,22 +300,48 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
                        continue;
                }
 
+               irq->pending_latch = true;
                if (irq->hw)
-                       vgic_hw_irq_spending(vcpu, irq, is_uaccess);
-               else
-                       irq->pending_latch = true;
+                       vgic_irq_set_phys_active(irq, true);
+
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
 
-/* Must be called with irq->irq_lock held */
-static void vgic_hw_irq_cpending(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
-                                bool is_uaccess)
+int vgic_uaccess_write_spending(struct kvm_vcpu *vcpu,
+                               gpa_t addr, unsigned int len,
+                               unsigned long val)
 {
-       if (is_uaccess)
-               return;
+       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+       int i;
+       unsigned long flags;
+
+       for_each_set_bit(i, &val, len * 8) {
+               struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
+               irq->pending_latch = true;
 
+               /*
+                * GICv2 SGIs are terribly broken. We can't restore
+                * the source of the interrupt, so just pick the vcpu
+                * itself as the source...
+                */
+               if (is_vgic_v2_sgi(vcpu, irq))
+                       irq->source |= BIT(vcpu->vcpu_id);
+
+               vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
+
+               vgic_put_irq(vcpu->kvm, irq);
+       }
+
+       return 0;
+}
+
+/* Must be called with irq->irq_lock held */
+static void vgic_hw_irq_cpending(struct kvm_vcpu *vcpu, struct vgic_irq *irq)
+{
        irq->pending_latch = false;
 
        /*
@@ -308,7 +364,6 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
                              gpa_t addr, unsigned int len,
                              unsigned long val)
 {
-       bool is_uaccess = !kvm_get_running_vcpu();
        u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
        int i;
        unsigned long flags;
@@ -339,7 +394,7 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
                }
 
                if (irq->hw)
-                       vgic_hw_irq_cpending(vcpu, irq, is_uaccess);
+                       vgic_hw_irq_cpending(vcpu, irq);
                else
                        irq->pending_latch = false;
 
@@ -348,8 +403,68 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
        }
 }
 
-unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
-                                   gpa_t addr, unsigned int len)
+int vgic_uaccess_write_cpending(struct kvm_vcpu *vcpu,
+                               gpa_t addr, unsigned int len,
+                               unsigned long val)
+{
+       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+       int i;
+       unsigned long flags;
+
+       for_each_set_bit(i, &val, len * 8) {
+               struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
+               /*
+                * More fun with GICv2 SGIs! If we're clearing one of them
+                * from userspace, which source vcpu to clear? Let's not
+                * even think of it, and blow the whole set.
+                */
+               if (is_vgic_v2_sgi(vcpu, irq))
+                       irq->source = 0;
+
+               irq->pending_latch = false;
+
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+
+               vgic_put_irq(vcpu->kvm, irq);
+       }
+
+       return 0;
+}
+
+/*
+ * If we are fiddling with an IRQ's active state, we have to make sure the IRQ
+ * is not queued on some running VCPU's LRs, because then the change to the
+ * active state can be overwritten when the VCPU's state is synced coming back
+ * from the guest.
+ *
+ * For shared interrupts as well as GICv3 private interrupts, we have to
+ * stop all the VCPUs because interrupts can be migrated while we don't hold
+ * the IRQ locks and we don't want to be chasing moving targets.
+ *
+ * For GICv2 private interrupts we don't have to do anything because
+ * userspace accesses to the VGIC state already require all VCPUs to be
+ * stopped, and only the VCPU itself can modify its private interrupts
+ * active state, which guarantees that the VCPU is not running.
+ */
+static void vgic_access_active_prepare(struct kvm_vcpu *vcpu, u32 intid)
+{
+       if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3 ||
+           intid >= VGIC_NR_PRIVATE_IRQS)
+               kvm_arm_halt_guest(vcpu->kvm);
+}
+
+/* See vgic_access_active_prepare */
+static void vgic_access_active_finish(struct kvm_vcpu *vcpu, u32 intid)
+{
+       if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3 ||
+           intid >= VGIC_NR_PRIVATE_IRQS)
+               kvm_arm_resume_guest(vcpu->kvm);
+}
+
+static unsigned long __vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+                                            gpa_t addr, unsigned int len)
 {
        u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
        u32 value = 0;
@@ -359,6 +474,10 @@ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
        for (i = 0; i < len * 8; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
+               /*
+                * Even for HW interrupts, don't evaluate the HW state as
+                * all the guest is interested in is the virtual state.
+                */
                if (irq->active)
                        value |= (1U << i);
 
@@ -368,6 +487,29 @@ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
        return value;
 }
 
+unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+                                   gpa_t addr, unsigned int len)
+{
+       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+       u32 val;
+
+       mutex_lock(&vcpu->kvm->lock);
+       vgic_access_active_prepare(vcpu, intid);
+
+       val = __vgic_mmio_read_active(vcpu, addr, len);
+
+       vgic_access_active_finish(vcpu, intid);
+       mutex_unlock(&vcpu->kvm->lock);
+
+       return val;
+}
+
+unsigned long vgic_uaccess_read_active(struct kvm_vcpu *vcpu,
+                                   gpa_t addr, unsigned int len)
+{
+       return __vgic_mmio_read_active(vcpu, addr, len);
+}
+
 /* Must be called with irq->irq_lock held */
 static void vgic_hw_irq_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
                                      bool active, bool is_uaccess)
@@ -426,36 +568,6 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
                raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 }
 
-/*
- * If we are fiddling with an IRQ's active state, we have to make sure the IRQ
- * is not queued on some running VCPU's LRs, because then the change to the
- * active state can be overwritten when the VCPU's state is synced coming back
- * from the guest.
- *
- * For shared interrupts, we have to stop all the VCPUs because interrupts can
- * be migrated while we don't hold the IRQ locks and we don't want to be
- * chasing moving targets.
- *
- * For private interrupts we don't have to do anything because userspace
- * accesses to the VGIC state already require all VCPUs to be stopped, and
- * only the VCPU itself can modify its private interrupts active state, which
- * guarantees that the VCPU is not running.
- */
-static void vgic_change_active_prepare(struct kvm_vcpu *vcpu, u32 intid)
-{
-       if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3 ||
-           intid > VGIC_NR_PRIVATE_IRQS)
-               kvm_arm_halt_guest(vcpu->kvm);
-}
-
-/* See vgic_change_active_prepare */
-static void vgic_change_active_finish(struct kvm_vcpu *vcpu, u32 intid)
-{
-       if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3 ||
-           intid > VGIC_NR_PRIVATE_IRQS)
-               kvm_arm_resume_guest(vcpu->kvm);
-}
-
 static void __vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
                                      gpa_t addr, unsigned int len,
                                      unsigned long val)
@@ -477,11 +589,11 @@ void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
        u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
 
        mutex_lock(&vcpu->kvm->lock);
-       vgic_change_active_prepare(vcpu, intid);
+       vgic_access_active_prepare(vcpu, intid);
 
        __vgic_mmio_write_cactive(vcpu, addr, len, val);
 
-       vgic_change_active_finish(vcpu, intid);
+       vgic_access_active_finish(vcpu, intid);
        mutex_unlock(&vcpu->kvm->lock);
 }
 
@@ -514,11 +626,11 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
        u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
 
        mutex_lock(&vcpu->kvm->lock);
-       vgic_change_active_prepare(vcpu, intid);
+       vgic_access_active_prepare(vcpu, intid);
 
        __vgic_mmio_write_sactive(vcpu, addr, len, val);
 
-       vgic_change_active_finish(vcpu, intid);
+       vgic_access_active_finish(vcpu, intid);
        mutex_unlock(&vcpu->kvm->lock);
 }
 
index 5af2aefad4359a26b1c9db8e0dc4d9edcfe99825..fefcca2b14dc7297db682d523b0326de249622ad 100644 (file)
@@ -138,6 +138,14 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
                             gpa_t addr, unsigned int len,
                             unsigned long val);
 
+int vgic_uaccess_write_senable(struct kvm_vcpu *vcpu,
+                              gpa_t addr, unsigned int len,
+                              unsigned long val);
+
+int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu,
+                              gpa_t addr, unsigned int len,
+                              unsigned long val);
+
 unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
                                     gpa_t addr, unsigned int len);
 
@@ -149,9 +157,20 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
                              gpa_t addr, unsigned int len,
                              unsigned long val);
 
+int vgic_uaccess_write_spending(struct kvm_vcpu *vcpu,
+                               gpa_t addr, unsigned int len,
+                               unsigned long val);
+
+int vgic_uaccess_write_cpending(struct kvm_vcpu *vcpu,
+                               gpa_t addr, unsigned int len,
+                               unsigned long val);
+
 unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
                                    gpa_t addr, unsigned int len);
 
+unsigned long vgic_uaccess_read_active(struct kvm_vcpu *vcpu,
+                                   gpa_t addr, unsigned int len);
+
 void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
                             gpa_t addr, unsigned int len,
                             unsigned long val);