Merge tag 'icc-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/djakov/icc...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Jun 2023 19:12:43 +0000 (21:12 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Jun 2023 19:12:43 +0000 (21:12 +0200)
Georgi writes:

interconnect changes for 6.5

This pull request contains the interconnect changes for the 6.5-rc1 merge
window which is a mix of core and driver changes with the following highlights:

- Support for configuring QoS on the Qualcomm's RPM-based platforms, that
  required special handling of some interface (non-scaling) clocks.
- Support for clock-based interconnect providers for cases when clock
  corresponds to bus bandwidth. This is used to enable CPU cluster bandwidth
  scaling on MSM8996 platforms. One patch is touching a file in the clock
  subsystem that has been acked by the maintainer.

Core changes:
interconnect: add clk-based icc provider support
interconnect: icc-clk: fix modular build
interconnect: drop unused icc_get() interface

Driver changes:
interconnect: qcom: rpm: Rename icc desc clocks to bus_blocks
interconnect: qcom: rpm: Rename icc provider num_clocks to num_bus_clocks
interconnect: qcom: rpm: Drop unused parameters
interconnect: qcom: rpm: Set QoS registers only once
interconnect: qcom: rpm: Handle interface clocks
interconnect: qcom: icc-rpm: Enforce 2 or 0 bus clocks
interconnect: qcom: rpm: Don't use clk_get_optional for bus clocks anymore
interconnect: qcom: msm8996: Promote to core_initcall
interconnect: qcom: rpm: allocate enough data in probe()
dt-bindings: interconnect/msm8996-cbf: add defines to be used by CBF
clk: qcom: cbf-msm8996: scale CBF clock according to the CPUfreq
dt-bindings: interconnect: fsl,imx8m-noc: drop unneeded quotes

Signed-off-by: Georgi Djakov <djakov@kernel.org>
* tag 'icc-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/djakov/icc:
  dt-bindings: interconnect: fsl,imx8m-noc: drop unneeded quotes
  interconnect: icc-clk: fix modular build
  clk: qcom: cbf-msm8996: scale CBF clock according to the CPUfreq
  interconnect: drop unused icc_get() interface
  interconnect: qcom: rpm: allocate enough data in probe()
  interconnect: qcom: msm8996: Promote to core_initcall
  interconnect: qcom: rpm: Don't use clk_get_optional for bus clocks anymore
  interconnect: qcom: icc-rpm: Enforce 2 or 0 bus clocks
  interconnect: qcom: rpm: Handle interface clocks
  interconnect: add clk-based icc provider support
  dt-bindings: interconnect/msm8996-cbf: add defines to be used by CBF
  interconnect: qcom: rpm: Set QoS registers only once
  interconnect: qcom: rpm: Drop unused parameters
  interconnect: qcom: rpm: Rename icc provider num_clocks to num_bus_clocks
  interconnect: qcom: rpm: Rename icc desc clocks to bus_blocks

1672 files changed:
.mailmap
CREDITS
Documentation/ABI/testing/sysfs-bus-counter
Documentation/admin-guide/cifs/changes.rst
Documentation/admin-guide/cifs/usage.rst
Documentation/admin-guide/quickly-build-trimmed-linux.rst
Documentation/block/index.rst
Documentation/block/request.rst [deleted file]
Documentation/cdrom/index.rst
Documentation/devicetree/bindings/ata/ceva,ahci-1v84.yaml
Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
Documentation/devicetree/bindings/extcon/qcom,pm8941-misc.yaml
Documentation/devicetree/bindings/extcon/wlf,arizona.yaml
Documentation/devicetree/bindings/fpga/lattice,sysconfig.yaml
Documentation/devicetree/bindings/fpga/microchip,mpf-spi-fpga-mgr.yaml
Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml
Documentation/devicetree/bindings/iio/adc/mediatek,mt2701-auxadc.yaml
Documentation/devicetree/bindings/iio/adc/nxp,imx8qxp-adc.yaml
Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml
Documentation/devicetree/bindings/iio/adc/renesas,rcar-gyroadc.yaml
Documentation/devicetree/bindings/iio/adc/rockchip-saradc.yaml
Documentation/devicetree/bindings/iio/afe/voltage-divider.yaml
Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
Documentation/devicetree/bindings/iio/imu/st,lsm6dsx.yaml
Documentation/devicetree/bindings/iio/light/rohm,bu27008.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/iio/light/ti,opt4001.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/iio/potentiometer/renesas,x9250.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/iio/st,st-sensors.yaml
Documentation/devicetree/bindings/iio/temperature/melexis,mlx90614.yaml
Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
Documentation/devicetree/bindings/media/i2c/ovti,ov2685.yaml
Documentation/devicetree/bindings/net/can/st,stm32-bxcan.yaml
Documentation/devicetree/bindings/nvmem/brcm,nvram.yaml
Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml
Documentation/devicetree/bindings/nvmem/layouts/fixed-cell.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/nvmem/layouts/fixed-layout.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/nvmem/layouts/nvmem-layout.yaml
Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml
Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml
Documentation/devicetree/bindings/nvmem/nvmem.yaml
Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml
Documentation/devicetree/bindings/nvmem/rmem.yaml
Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/nvmem/rockchip-otp.txt [deleted file]
Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml
Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml
Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-common.yaml
Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-ep.yaml
Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
Documentation/devicetree/bindings/serial/8250_omap.yaml
Documentation/devicetree/bindings/sound/tas2562.yaml
Documentation/devicetree/bindings/sound/tas2770.yaml
Documentation/devicetree/bindings/sound/tas27xx.yaml
Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
Documentation/devicetree/bindings/sram/sram.yaml
Documentation/devicetree/bindings/usb/cdns,usb3.yaml
Documentation/devicetree/bindings/usb/snps,dwc3.yaml
Documentation/fault-injection/provoke-crashes.rst
Documentation/filesystems/index.rst
Documentation/filesystems/ramfs-rootfs-initramfs.rst
Documentation/filesystems/sharedsubtree.rst
Documentation/filesystems/smb/cifsroot.rst [moved from Documentation/filesystems/cifs/cifsroot.rst with 97% similarity]
Documentation/filesystems/smb/index.rst [moved from Documentation/filesystems/cifs/index.rst with 100% similarity]
Documentation/filesystems/smb/ksmbd.rst [moved from Documentation/filesystems/cifs/ksmbd.rst with 100% similarity]
Documentation/fpga/index.rst
Documentation/locking/index.rst
Documentation/misc-devices/index.rst
Documentation/misc-devices/tps6594-pfsm.rst [new file with mode: 0644]
Documentation/mm/page_table_check.rst
Documentation/netlink/specs/ethtool.yaml
Documentation/netlink/specs/handshake.yaml
Documentation/networking/bonding.rst
Documentation/networking/device_drivers/ethernet/mellanox/mlx5/devlink.rst
Documentation/networking/index.rst
Documentation/networking/tls-handshake.rst
Documentation/networking/x25-iface.rst
Documentation/pcmcia/index.rst
Documentation/process/maintainer-netdev.rst
Documentation/s390/vfio-ap.rst
Documentation/staging/crc32.rst
Documentation/timers/index.rst
Documentation/trace/histogram.rst
Documentation/userspace-api/ioctl/ioctl-number.rst
MAINTAINERS
Makefile
arch/arm/boot/dts/imx6qdl-mba6.dtsi
arch/arm/boot/dts/imx6ull-dhcor-som.dtsi
arch/arm/boot/dts/stm32f429.dtsi
arch/arm/boot/dts/stm32f7-pinctrl.dtsi
arch/arm/boot/dts/vexpress-v2p-ca5s.dts
arch/arm/include/asm/arm_pmuv3.h
arch/arm/kernel/unwind.c
arch/arm/mach-sa1100/jornada720_ssp.c
arch/arm/vfp/entry.S
arch/arm/vfp/vfphw.S
arch/arm64/boot/dts/arm/foundation-v8.dtsi
arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts
arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts
arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi
arch/arm64/boot/dts/freescale/imx8mn.dtsi
arch/arm64/boot/dts/freescale/imx8mp.dtsi
arch/arm64/boot/dts/freescale/imx8x-colibri-eval-v3.dtsi
arch/arm64/boot/dts/freescale/imx8x-colibri-iris.dtsi
arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi
arch/arm64/include/asm/arm_pmuv3.h
arch/arm64/include/asm/cputype.h
arch/arm64/include/asm/kvm_pgtable.h
arch/arm64/include/asm/sysreg.h
arch/arm64/kernel/mte.c
arch/arm64/kernel/vdso.c
arch/arm64/kvm/fpsimd.c
arch/arm64/kvm/hyp/include/hyp/switch.h
arch/arm64/kvm/hyp/nvhe/mem_protect.c
arch/arm64/kvm/hyp/nvhe/switch.c
arch/arm64/kvm/hyp/pgtable.c
arch/arm64/kvm/hyp/vhe/switch.c
arch/arm64/kvm/inject_fault.c
arch/arm64/kvm/pmu-emul.c
arch/arm64/kvm/sys_regs.c
arch/arm64/kvm/vgic/vgic-init.c
arch/arm64/kvm/vgic/vgic-its.c
arch/arm64/kvm/vgic/vgic-kvm-device.c
arch/arm64/kvm/vgic/vgic-mmio-v3.c
arch/arm64/kvm/vgic/vgic-mmio.c
arch/arm64/kvm/vgic/vgic-v2.c
arch/arm64/kvm/vgic/vgic-v3.c
arch/arm64/kvm/vgic/vgic-v4.c
arch/arm64/kvm/vmid.c
arch/arm64/mm/copypage.c
arch/arm64/mm/fault.c
arch/m68k/kernel/signal.c
arch/mips/Kconfig
arch/mips/alchemy/common/dbdma.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/setup.c
arch/parisc/Kconfig
arch/parisc/Kconfig.debug
arch/parisc/include/asm/cacheflush.h
arch/parisc/include/asm/pgtable.h
arch/parisc/include/asm/spinlock.h
arch/parisc/include/asm/spinlock_types.h
arch/parisc/kernel/alternative.c
arch/parisc/kernel/cache.c
arch/parisc/kernel/kexec.c
arch/parisc/kernel/pci-dma.c
arch/parisc/kernel/process.c
arch/parisc/kernel/traps.c
arch/powerpc/Kconfig
arch/powerpc/boot/Makefile
arch/powerpc/crypto/Kconfig
arch/powerpc/crypto/Makefile
arch/powerpc/crypto/aes-gcm-p10-glue.c
arch/powerpc/crypto/aesp10-ppc.pl [moved from arch/powerpc/crypto/aesp8-ppc.pl with 99% similarity]
arch/powerpc/crypto/ghashp10-ppc.pl [moved from arch/powerpc/crypto/ghashp8-ppc.pl with 97% similarity]
arch/powerpc/include/asm/iommu.h
arch/powerpc/kernel/dma-iommu.c
arch/powerpc/kernel/iommu.c
arch/powerpc/kernel/isa-bridge.c
arch/powerpc/mm/book3s64/radix_pgtable.c
arch/powerpc/net/bpf_jit_comp.c
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/xmon/xmon.c
arch/riscv/Kconfig
arch/riscv/errata/Makefile
arch/riscv/include/asm/hugetlb.h
arch/riscv/include/asm/perf_event.h
arch/riscv/kernel/Makefile
arch/riscv/kernel/pi/Makefile
arch/riscv/kernel/probes/Makefile
arch/riscv/kernel/vmlinux.lds.S
arch/riscv/mm/hugetlbpage.c
arch/riscv/mm/init.c
arch/s390/Kconfig
arch/s390/configs/debug_defconfig
arch/s390/configs/defconfig
arch/s390/configs/zfcpdump_defconfig
arch/s390/crypto/chacha-glue.c
arch/s390/include/asm/compat.h
arch/s390/include/uapi/asm/statfs.h
arch/s390/kernel/Makefile
arch/s390/kernel/ipl.c
arch/s390/kernel/topology.c
arch/um/drivers/Makefile
arch/um/drivers/harddog.h [new file with mode: 0644]
arch/um/drivers/harddog_kern.c
arch/um/drivers/harddog_user.c
arch/um/drivers/harddog_user_exp.c [new file with mode: 0644]
arch/x86/crypto/aria-aesni-avx-asm_64.S
arch/x86/events/core.c
arch/x86/events/intel/core.c
arch/x86/events/intel/ds.c
arch/x86/events/intel/uncore_snbep.c
arch/x86/include/asm/fpu/sched.h
arch/x86/include/asm/perf_event.h
arch/x86/include/asm/vmx.h
arch/x86/kernel/Makefile
arch/x86/kernel/amd_nb.c
arch/x86/kernel/cpu/topology.c
arch/x86/kernel/dumpstack.c
arch/x86/kernel/fpu/context.h
arch/x86/kernel/fpu/core.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/svm/svm.c
arch/x86/kvm/vmx/sgx.c
arch/x86/kvm/x86.c
arch/x86/lib/copy_user_64.S
arch/x86/lib/retpoline.S
arch/x86/mm/init.c
arch/x86/pci/xen.c
arch/xtensa/kernel/signal.c
arch/xtensa/kernel/xtensa_ksyms.c
arch/xtensa/lib/Makefile
arch/xtensa/lib/bswapdi2.S [new file with mode: 0644]
arch/xtensa/lib/bswapsi2.S [new file with mode: 0644]
block/blk-core.c
block/blk-map.c
block/blk-mq-tag.c
block/blk-settings.c
block/blk-wbt.c
block/fops.c
drivers/accel/qaic/qaic_control.c
drivers/accel/qaic/qaic_data.c
drivers/accel/qaic/qaic_drv.c
drivers/accessibility/speakup/Kconfig
drivers/accessibility/speakup/main.c
drivers/acpi/apei/apei-internal.h
drivers/acpi/apei/bert.c
drivers/acpi/resource.c
drivers/android/binder.c
drivers/android/binder_alloc.c
drivers/android/binder_alloc.h
drivers/android/binder_alloc_selftest.c
drivers/android/binder_internal.h
drivers/ata/libata-scsi.c
drivers/base/cacheinfo.c
drivers/base/class.c
drivers/base/firmware_loader/main.c
drivers/base/regmap/Kconfig
drivers/base/regmap/regcache-maple.c
drivers/base/regmap/regmap-sdw.c
drivers/base/regmap/regmap.c
drivers/block/nbd.c
drivers/block/rnbd/rnbd-proto.h
drivers/block/ublk_drv.c
drivers/block/xen-blkfront.c
drivers/bluetooth/btnxpuart.c
drivers/bus/fsl-mc/dprc-driver.c
drivers/cdx/cdx.c
drivers/cdx/controller/Kconfig
drivers/cdx/controller/mcdi.c
drivers/cdx/controller/mcdi.h
drivers/char/Kconfig
drivers/char/agp/parisc-agp.c
drivers/char/tpm/tpm-chip.c
drivers/char/tpm/tpm-interface.c
drivers/char/tpm/tpm_tis.c
drivers/char/tpm/tpm_tis_core.c
drivers/char/tpm/tpm_tis_core.h
drivers/char/xilinx_hwicap/xilinx_hwicap.c
drivers/comedi/Kconfig
drivers/counter/104-quad-8.c
drivers/counter/Kconfig
drivers/counter/Makefile
drivers/counter/counter-sysfs.c
drivers/counter/i8254.c [new file with mode: 0644]
drivers/counter/stm32-timer-cnt.c
drivers/cpufreq/acpi-cpufreq.c
drivers/cpufreq/amd-pstate.c
drivers/cpufreq/pcc-cpufreq.c
drivers/cxl/core/mbox.c
drivers/cxl/core/pci.c
drivers/cxl/core/port.c
drivers/cxl/cxl.h
drivers/cxl/cxlmem.h
drivers/cxl/cxlpci.h
drivers/cxl/mem.c
drivers/cxl/pci.c
drivers/cxl/port.c
drivers/dma/at_hdmac.c
drivers/dma/at_xdmac.c
drivers/dma/idxd/cdev.c
drivers/dma/pl330.c
drivers/dma/ti/k3-udma.c
drivers/extcon/Kconfig
drivers/extcon/extcon-axp288.c
drivers/extcon/extcon-fsa9480.c
drivers/extcon/extcon-palmas.c
drivers/extcon/extcon-ptn5150.c
drivers/extcon/extcon-qcom-spmi-misc.c
drivers/extcon/extcon-rt8973a.c
drivers/extcon/extcon-sm5502.c
drivers/extcon/extcon-usbc-tusb320.c
drivers/extcon/extcon.c
drivers/extcon/extcon.h
drivers/firewire/net.c
drivers/firmware/arm_ffa/bus.c
drivers/firmware/arm_ffa/driver.c
drivers/firmware/arm_scmi/raw_mode.c
drivers/firmware/dmi-sysfs.c
drivers/firmware/efi/libstub/Makefile.zboot
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/stratix10-svc.c
drivers/firmware/sysfb_simplefb.c
drivers/firmware/xilinx/zynqmp-debug.c
drivers/firmware/xilinx/zynqmp-debug.h
drivers/firmware/xilinx/zynqmp.c
drivers/fpga/dfl-fme-main.c
drivers/fpga/zynq-fpga.c
drivers/gpio/Kconfig
drivers/gpio/gpio-f7188x.c
drivers/gpio/gpio-mockup.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
drivers/gpu/drm/amd/amdgpu/nv.c
drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
drivers/gpu/drm/amd/amdgpu/soc21.c
drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h
drivers/gpu/drm/amd/display/dc/link/link_validation.c
drivers/gpu/drm/amd/pm/amdgpu_dpm.c
drivers/gpu/drm/amd/pm/amdgpu_pm.c
drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_managed.c
drivers/gpu/drm/drm_mipi_dsi.c
drivers/gpu/drm/drm_panel_orientation_quirks.c
drivers/gpu/drm/exynos/exynos_drm_g2d.h
drivers/gpu/drm/i915/Kconfig
drivers/gpu/drm/i915/display/intel_atomic_plane.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_hdcp.c
drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hwio.h
drivers/gpu/drm/msm/dp/dp_audio.c
drivers/gpu/drm/msm/dp/dp_audio.h
drivers/gpu/drm/msm/dp/dp_display.c
drivers/gpu/drm/msm/msm_atomic.c
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gem_submit.c
drivers/gpu/drm/msm/msm_iommu.c
drivers/gpu/drm/nouveau/include/nvif/if0012.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
drivers/gpu/drm/pl111/pl111_display.c
drivers/gpu/drm/pl111/pl111_drm.h
drivers/gpu/drm/pl111/pl111_drv.c
drivers/gpu/drm/pl111/pl111_versatile.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/scheduler/sched_main.c
drivers/hid/hid-google-hammer.c
drivers/hid/hid-ids.h
drivers/hid/hid-logitech-hidpp.c
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c
drivers/hwmon/k10temp.c
drivers/hwtracing/coresight/coresight-etm-perf.c
drivers/hwtracing/coresight/coresight-tmc-etr.c
drivers/iio/accel/adxl313_i2c.c
drivers/iio/accel/adxl345_i2c.c
drivers/iio/accel/adxl355_i2c.c
drivers/iio/accel/adxl367_i2c.c
drivers/iio/accel/adxl372_i2c.c
drivers/iio/accel/bma180.c
drivers/iio/accel/bma400_core.c
drivers/iio/accel/bma400_i2c.c
drivers/iio/accel/bmc150-accel-i2c.c
drivers/iio/accel/da280.c
drivers/iio/accel/da311.c
drivers/iio/accel/dmard06.c
drivers/iio/accel/dmard09.c
drivers/iio/accel/dmard10.c
drivers/iio/accel/fxls8962af-core.c
drivers/iio/accel/fxls8962af-i2c.c
drivers/iio/accel/kionix-kx022a-i2c.c
drivers/iio/accel/kionix-kx022a-spi.c
drivers/iio/accel/kionix-kx022a.c
drivers/iio/accel/kxcjk-1013.c
drivers/iio/accel/kxsd9-i2c.c
drivers/iio/accel/mc3230.c
drivers/iio/accel/mma7455_i2c.c
drivers/iio/accel/mma7660.c
drivers/iio/accel/mma8452.c
drivers/iio/accel/mma9551.c
drivers/iio/accel/mma9553.c
drivers/iio/accel/msa311.c
drivers/iio/accel/mxc4005.c
drivers/iio/accel/mxc6255.c
drivers/iio/accel/st_accel_core.c
drivers/iio/accel/st_accel_i2c.c
drivers/iio/accel/stk8312.c
drivers/iio/accel/stk8ba50.c
drivers/iio/adc/Kconfig
drivers/iio/adc/ad4130.c
drivers/iio/adc/ad7091r5.c
drivers/iio/adc/ad7192.c
drivers/iio/adc/ad7291.c
drivers/iio/adc/ad799x.c
drivers/iio/adc/ad_sigma_delta.c
drivers/iio/adc/imx93_adc.c
drivers/iio/adc/ina2xx-adc.c
drivers/iio/adc/ltc2471.c
drivers/iio/adc/ltc2485.c
drivers/iio/adc/ltc2497.c
drivers/iio/adc/max1363.c
drivers/iio/adc/max9611.c
drivers/iio/adc/mcp3422.c
drivers/iio/adc/meson_saradc.c
drivers/iio/adc/mt6370-adc.c
drivers/iio/adc/mxs-lradc-adc.c
drivers/iio/adc/nau7802.c
drivers/iio/adc/palmas_gpadc.c
drivers/iio/adc/qcom-spmi-adc5.c
drivers/iio/adc/qcom-spmi-vadc.c
drivers/iio/adc/rockchip_saradc.c
drivers/iio/adc/rtq6056.c
drivers/iio/adc/stm32-adc.c
drivers/iio/adc/ti-adc081c.c
drivers/iio/adc/ti-ads1015.c
drivers/iio/adc/ti-ads1100.c
drivers/iio/adc/ti-ads7924.c
drivers/iio/addac/ad74413r.c
drivers/iio/amplifiers/ad8366.c
drivers/iio/cdc/ad7150.c
drivers/iio/cdc/ad7746.c
drivers/iio/chemical/ams-iaq-core.c
drivers/iio/chemical/atlas-ezo-sensor.c
drivers/iio/chemical/atlas-sensor.c
drivers/iio/chemical/bme680_i2c.c
drivers/iio/chemical/ccs811.c
drivers/iio/chemical/scd30_i2c.c
drivers/iio/chemical/scd4x.c
drivers/iio/chemical/sgp30.c
drivers/iio/chemical/sgp40.c
drivers/iio/chemical/sps30_i2c.c
drivers/iio/chemical/sunrise_co2.c
drivers/iio/chemical/vz89x.c
drivers/iio/dac/Makefile
drivers/iio/dac/ad5064.c
drivers/iio/dac/ad5380.c
drivers/iio/dac/ad5446.c
drivers/iio/dac/ad5593r.c
drivers/iio/dac/ad5696-i2c.c
drivers/iio/dac/ds4424.c
drivers/iio/dac/m62332.c
drivers/iio/dac/max517.c
drivers/iio/dac/max5821.c
drivers/iio/dac/mcp4725.c
drivers/iio/dac/ti-dac5571.c
drivers/iio/gyro/bmg160_i2c.c
drivers/iio/gyro/fxas21002c_i2c.c
drivers/iio/gyro/itg3200_core.c
drivers/iio/gyro/mpu3050-i2c.c
drivers/iio/gyro/st_gyro_i2c.c
drivers/iio/health/afe4404.c
drivers/iio/health/max30100.c
drivers/iio/health/max30102.c
drivers/iio/humidity/am2315.c
drivers/iio/humidity/hdc100x.c
drivers/iio/humidity/hdc2010.c
drivers/iio/humidity/hts221_i2c.c
drivers/iio/humidity/htu21.c
drivers/iio/humidity/si7005.c
drivers/iio/humidity/si7020.c
drivers/iio/imu/bmi160/bmi160_i2c.c
drivers/iio/imu/bno055/bno055_i2c.c
drivers/iio/imu/fxos8700_i2c.c
drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c
drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c
drivers/iio/imu/inv_mpu6050/Kconfig
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
drivers/iio/imu/kmx61.c
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
drivers/iio/imu/st_lsm9ds0/Kconfig
drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c
drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c
drivers/iio/industrialio-buffer.c
drivers/iio/industrialio-gts-helper.c
drivers/iio/industrialio-trigger.c
drivers/iio/light/Kconfig
drivers/iio/light/Makefile
drivers/iio/light/adjd_s311.c
drivers/iio/light/adux1020.c
drivers/iio/light/al3010.c
drivers/iio/light/al3320a.c
drivers/iio/light/apds9300.c
drivers/iio/light/apds9960.c
drivers/iio/light/as73211.c
drivers/iio/light/bh1750.c
drivers/iio/light/bh1780.c
drivers/iio/light/cm32181.c
drivers/iio/light/cm3232.c
drivers/iio/light/cm3323.c
drivers/iio/light/cm36651.c
drivers/iio/light/gp2ap002.c
drivers/iio/light/gp2ap020a00f.c
drivers/iio/light/isl29018.c
drivers/iio/light/isl29028.c
drivers/iio/light/isl29125.c
drivers/iio/light/jsa1212.c
drivers/iio/light/ltr501.c
drivers/iio/light/ltrf216a.c
drivers/iio/light/lv0104cs.c
drivers/iio/light/max44000.c
drivers/iio/light/max44009.c
drivers/iio/light/noa1305.c
drivers/iio/light/opt3001.c
drivers/iio/light/opt4001.c [new file with mode: 0644]
drivers/iio/light/pa12203001.c
drivers/iio/light/rohm-bu27008.c [new file with mode: 0644]
drivers/iio/light/rohm-bu27034.c
drivers/iio/light/rpr0521.c
drivers/iio/light/si1133.c
drivers/iio/light/si1145.c
drivers/iio/light/st_uvis25_i2c.c
drivers/iio/light/stk3310.c
drivers/iio/light/tcs3414.c
drivers/iio/light/tcs3472.c
drivers/iio/light/tsl2563.c
drivers/iio/light/tsl2583.c
drivers/iio/light/tsl2591.c
drivers/iio/light/tsl2772.c
drivers/iio/light/tsl4531.c
drivers/iio/light/us5182d.c
drivers/iio/light/vcnl4000.c
drivers/iio/light/vcnl4035.c
drivers/iio/light/veml6030.c
drivers/iio/light/veml6070.c
drivers/iio/light/vl6180.c
drivers/iio/light/zopt2201.c
drivers/iio/magnetometer/ak8974.c
drivers/iio/magnetometer/ak8975.c
drivers/iio/magnetometer/bmc150_magn_i2c.c
drivers/iio/magnetometer/hmc5843_i2c.c
drivers/iio/magnetometer/mag3110.c
drivers/iio/magnetometer/mmc35240.c
drivers/iio/magnetometer/rm3100-i2c.c
drivers/iio/magnetometer/st_magn_core.c
drivers/iio/magnetometer/st_magn_i2c.c
drivers/iio/magnetometer/tmag5273.c
drivers/iio/magnetometer/yamaha-yas530.c
drivers/iio/potentiometer/Kconfig
drivers/iio/potentiometer/Makefile
drivers/iio/potentiometer/ad5110.c
drivers/iio/potentiometer/ad5272.c
drivers/iio/potentiometer/ds1803.c
drivers/iio/potentiometer/max5432.c
drivers/iio/potentiometer/mcp4018.c
drivers/iio/potentiometer/mcp4531.c
drivers/iio/potentiometer/tpl0102.c
drivers/iio/potentiometer/x9250.c [new file with mode: 0644]
drivers/iio/potentiostat/lmp91000.c
drivers/iio/pressure/Kconfig
drivers/iio/pressure/Makefile
drivers/iio/pressure/abp060mg.c
drivers/iio/pressure/bmp280-i2c.c
drivers/iio/pressure/dlhl60d.c
drivers/iio/pressure/dps310.c
drivers/iio/pressure/hp03.c
drivers/iio/pressure/hp206c.c
drivers/iio/pressure/icp10100.c
drivers/iio/pressure/mpl115_i2c.c
drivers/iio/pressure/mpl3115.c
drivers/iio/pressure/mprls0025pa.c [new file with mode: 0644]
drivers/iio/pressure/ms5611_i2c.c
drivers/iio/pressure/ms5637.c
drivers/iio/pressure/st_pressure_i2c.c
drivers/iio/pressure/t5403.c
drivers/iio/pressure/zpa2326_i2c.c
drivers/iio/proximity/isl29501.c
drivers/iio/proximity/mb1232.c
drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
drivers/iio/proximity/rfd77402.c
drivers/iio/proximity/srf08.c
drivers/iio/proximity/sx9310.c
drivers/iio/proximity/sx9324.c
drivers/iio/proximity/sx9360.c
drivers/iio/proximity/sx9500.c
drivers/iio/proximity/vcnl3020.c
drivers/iio/proximity/vl53l0x-i2c.c
drivers/iio/temperature/max30208.c
drivers/iio/temperature/mlx90614.c
drivers/iio/temperature/mlx90632.c
drivers/iio/temperature/tmp006.c
drivers/iio/temperature/tmp007.c
drivers/iio/temperature/tmp117.c
drivers/iio/temperature/tsys01.c
drivers/iio/temperature/tsys02d.c
drivers/infiniband/hw/bnxt_re/ib_verbs.c
drivers/infiniband/hw/bnxt_re/main.c
drivers/infiniband/hw/bnxt_re/qplib_fp.c
drivers/infiniband/hw/bnxt_re/qplib_res.c
drivers/infiniband/hw/bnxt_re/qplib_sp.c
drivers/infiniband/hw/efa/efa_verbs.c
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
drivers/infiniband/hw/hns/hns_roce_hw_v2.h
drivers/infiniband/hw/hns/hns_roce_mr.c
drivers/infiniband/hw/irdma/verbs.c
drivers/infiniband/sw/rxe/rxe_comp.c
drivers/infiniband/sw/rxe/rxe_net.c
drivers/infiniband/sw/rxe/rxe_qp.c
drivers/infiniband/sw/rxe/rxe_recv.c
drivers/infiniband/sw/rxe/rxe_req.c
drivers/infiniband/sw/rxe/rxe_resp.c
drivers/infiniband/sw/rxe/rxe_verbs.c
drivers/iommu/Kconfig
drivers/iommu/amd/amd_iommu.h
drivers/iommu/amd/init.c
drivers/iommu/amd/iommu.c
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
drivers/iommu/mtk_iommu.c
drivers/iommu/rockchip-iommu.c
drivers/irqchip/irq-gic-common.c
drivers/irqchip/irq-gic-common.h
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-mbigen.c
drivers/irqchip/irq-meson-gpio.c
drivers/irqchip/irq-mips-gic.c
drivers/isdn/Kconfig
drivers/isdn/hardware/mISDN/Kconfig
drivers/leds/rgb/leds-qcom-lpg.c
drivers/mailbox/mailbox-test.c
drivers/md/raid5.c
drivers/media/cec/core/cec-adap.c
drivers/media/cec/core/cec-core.c
drivers/media/cec/core/cec-priv.h
drivers/media/dvb-core/dvb_ca_en50221.c
drivers/media/dvb-core/dvb_demux.c
drivers/media/dvb-core/dvb_frontend.c
drivers/media/dvb-core/dvb_net.c
drivers/media/dvb-core/dvbdev.c
drivers/media/dvb-frontends/mn88443x.c
drivers/media/pci/netup_unidvb/netup_unidvb_core.c
drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c
drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateful.c
drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c
drivers/media/platform/qcom/camss/camss-video.c
drivers/media/platform/renesas/rcar-vin/rcar-dma.c
drivers/media/platform/verisilicon/hantro_v4l2.c
drivers/media/usb/dvb-usb-v2/ce6230.c
drivers/media/usb/dvb-usb-v2/ec168.c
drivers/media/usb/dvb-usb-v2/rtl28xxu.c
drivers/media/usb/dvb-usb/az6027.c
drivers/media/usb/dvb-usb/digitv.c
drivers/media/usb/dvb-usb/dw2102.c
drivers/media/usb/pvrusb2/Kconfig
drivers/media/usb/ttusb-dec/ttusb_dec.c
drivers/media/usb/uvc/uvc_driver.c
drivers/media/v4l2-core/v4l2-mc.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/tps6594-core.c [new file with mode: 0644]
drivers/mfd/tps6594-i2c.c [new file with mode: 0644]
drivers/mfd/tps6594-spi.c [new file with mode: 0644]
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/ad525x_dpot-i2c.c
drivers/misc/altera-stapl/Makefile
drivers/misc/altera-stapl/altera.c
drivers/misc/apds9802als.c
drivers/misc/apds990x.c
drivers/misc/bh1770glc.c
drivers/misc/ds1682.c
drivers/misc/eeprom/at24.c
drivers/misc/eeprom/ee1004.c
drivers/misc/eeprom/eeprom.c
drivers/misc/eeprom/idt_89hpesx.c
drivers/misc/eeprom/max6875.c
drivers/misc/fastrpc.c
drivers/misc/hmc6352.c
drivers/misc/ics932s401.c
drivers/misc/isl29003.c
drivers/misc/isl29020.c
drivers/misc/lis3lv02d/lis3lv02d_i2c.c
drivers/misc/lkdtm/core.c
drivers/misc/mei/bus-fixup.c
drivers/misc/mei/bus.c
drivers/misc/smpro-errmon.c
drivers/misc/sram.c
drivers/misc/tps6594-esm.c [new file with mode: 0644]
drivers/misc/tps6594-pfsm.c [new file with mode: 0644]
drivers/misc/tsl2550.c
drivers/misc/uacce/uacce.c
drivers/misc/xilinx_sdfec.c
drivers/mmc/core/block.c
drivers/mmc/core/pwrseq_sd8787.c
drivers/mmc/host/sdhci-cadence.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/vub300.c
drivers/mtd/mtdchar.c
drivers/mtd/nand/raw/ingenic/ingenic_ecc.h
drivers/mtd/nand/raw/marvell_nand.c
drivers/mtd/spi-nor/core.c
drivers/mtd/spi-nor/spansion.c
drivers/mux/Kconfig
drivers/mux/adg792a.c
drivers/mux/mmio.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_netlink.c
drivers/net/bonding/bond_options.c
drivers/net/can/Kconfig
drivers/net/can/bxcan.c
drivers/net/can/dev/skb.c
drivers/net/can/kvaser_pciefd.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/port.h
drivers/net/dsa/rzn1_a5psw.c
drivers/net/dsa/rzn1_a5psw.h
drivers/net/ethernet/3com/3c515.c
drivers/net/ethernet/3com/3c589_cs.c
drivers/net/ethernet/8390/ne.c
drivers/net/ethernet/8390/smc-ultra.c
drivers/net/ethernet/8390/wd.c
drivers/net/ethernet/amd/lance.c
drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/cirrus/cs89x0.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/google/gve/gve_main.c
drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c
drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
drivers/net/ethernet/intel/ice/ice_dcb_lib.c
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_sriov.c
drivers/net/ethernet/intel/ice/ice_txrx.c
drivers/net/ethernet/intel/ice/ice_txrx.h
drivers/net/ethernet/intel/ice/ice_vf_lib.c
drivers/net/ethernet/intel/ice/ice_vf_lib.h
drivers/net/ethernet/intel/ice/ice_virtchnl.c
drivers/net/ethernet/intel/igb/e1000_mac.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mediatek/mtk_wed.c
drivers/net/ethernet/mellanox/mlx5/core/cmd.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/port_buffer.c
drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h
drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.h
drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
drivers/net/ethernet/mellanox/mlx5/core/en_common.c
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.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_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
drivers/net/ethernet/mellanox/mlx5/core/eq.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h
drivers/net/ethernet/mellanox/mlx5/core/mr.c
drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c
drivers/net/ethernet/microchip/lan966x/lan966x_main.c
drivers/net/ethernet/microsoft/mana/mana_en.c
drivers/net/ethernet/microsoft/mana/mana_ethtool.c
drivers/net/ethernet/mscc/vsc7514_regs.c
drivers/net/ethernet/netronome/nfp/nic/main.h
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/renesas/rswitch.c
drivers/net/ethernet/sfc/ef100_netdev.c
drivers/net/ethernet/sfc/efx_devlink.c
drivers/net/ethernet/sfc/tc.c
drivers/net/ethernet/stmicro/stmmac/dwmac4.h
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c
drivers/net/ethernet/sun/cassini.c
drivers/net/ipa/ipa_endpoint.c
drivers/net/ipvlan/ipvlan_core.c
drivers/net/mdio/mdio-i2c.c
drivers/net/mdio/mdio-mvusb.c
drivers/net/pcs/pcs-xpcs.c
drivers/net/phy/bcm-phy-lib.h
drivers/net/phy/bcm7xxx.c
drivers/net/phy/dp83867.c
drivers/net/phy/mscc/mscc.h
drivers/net/phy/mscc/mscc_main.c
drivers/net/phy/mxl-gpy.c
drivers/net/phy/phylink.c
drivers/net/tap.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/qmi_wwan.c
drivers/net/virtio_net.c
drivers/net/wireless/broadcom/b43/b43.h
drivers/net/wireless/broadcom/b43legacy/b43legacy.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
drivers/net/wireless/intel/iwlwifi/fw/acpi.c
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/mvm/link.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
drivers/net/wireless/intel/iwlwifi/mvm/rfi.c
drivers/net/wireless/intel/iwlwifi/mvm/rs.c
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/mvm/tx.c
drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h
drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
drivers/net/wireless/mediatek/mt76/mt7996/mac.c
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
drivers/net/wireless/realtek/rtw88/mac80211.c
drivers/net/wireless/realtek/rtw88/main.c
drivers/net/wireless/realtek/rtw88/main.h
drivers/net/wireless/realtek/rtw88/sdio.c
drivers/net/wireless/realtek/rtw88/usb.h
drivers/net/wireless/realtek/rtw89/mac.c
drivers/net/wireless/realtek/rtw89/mac.h
drivers/net/wireless/realtek/rtw89/rtw8852b.c
drivers/net/wireless/virtual/mac80211_hwsim.c
drivers/net/wwan/iosm/iosm_ipc_imem.c
drivers/net/wwan/iosm/iosm_ipc_imem_ops.c
drivers/net/wwan/iosm/iosm_ipc_imem_ops.h
drivers/net/wwan/t7xx/t7xx_pci.c
drivers/net/wwan/t7xx/t7xx_pci.h
drivers/nfc/nfcsim.c
drivers/nvme/host/constants.c
drivers/nvme/host/core.c
drivers/nvme/host/hwmon.c
drivers/nvme/host/ioctl.c
drivers/nvme/host/multipath.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/target/passthru.c
drivers/nvmem/Kconfig
drivers/nvmem/Makefile
drivers/nvmem/brcm_nvram.c
drivers/nvmem/core.c
drivers/nvmem/imx-ocotp-ele.c [new file with mode: 0644]
drivers/nvmem/imx-ocotp.c
drivers/nvmem/rmem.c
drivers/nvmem/rockchip-otp.c
drivers/nvmem/sunplus-ocotp.c
drivers/nvmem/zynqmp_nvmem.c
drivers/parport/Kconfig
drivers/pci/quirks.c
drivers/pcmcia/Kconfig
drivers/pcmcia/rsrc_nonstatic.c
drivers/phy/amlogic/phy-meson-g12a-mipi-dphy-analog.c
drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c
drivers/phy/qualcomm/phy-qcom-qmp-combo.c
drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c
drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
drivers/platform/mellanox/mlxbf-pmc.c
drivers/platform/mellanox/mlxbf-tmfifo.c
drivers/platform/x86/amd/pmf/core.c
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/hp/hp-wmi.c
drivers/platform/x86/intel/ifs/load.c
drivers/platform/x86/intel/speed_select_if/isst_if_common.c
drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
drivers/platform/x86/intel_scu_pcidrv.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/touchscreen_dmi.c
drivers/power/supply/ab8500_btemp.c
drivers/power/supply/ab8500_fg.c
drivers/power/supply/axp288_fuel_gauge.c
drivers/power/supply/bq24190_charger.c
drivers/power/supply/bq25890_charger.c
drivers/power/supply/bq27xxx_battery.c
drivers/power/supply/bq27xxx_battery_i2c.c
drivers/power/supply/mt6360_charger.c
drivers/power/supply/power_supply_core.c
drivers/power/supply/power_supply_leds.c
drivers/power/supply/power_supply_sysfs.c
drivers/power/supply/rt9467-charger.c
drivers/power/supply/sbs-charger.c
drivers/power/supply/sc27xx_fuel_gauge.c
drivers/regulator/core.c
drivers/regulator/mt6359-regulator.c
drivers/regulator/pca9450-regulator.c
drivers/s390/block/dasd_eckd.c
drivers/s390/cio/device.c
drivers/s390/cio/qdio.h
drivers/s390/crypto/pkey_api.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_inline.h
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/scsi_lib.c
drivers/scsi/stex.c
drivers/scsi/storvsc_drv.c
drivers/soc/fsl/qe/Kconfig
drivers/spi/spi-cadence.c
drivers/spi/spi-dw-mmio.c
drivers/spi/spi-geni-qcom.c
drivers/staging/iio/addac/adt7316-i2c.c
drivers/staging/iio/impedance-analyzer/ad5933.c
drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
drivers/staging/media/imx/imx8mq-mipi-csi2.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_nego.c
drivers/target/iscsi/iscsi_target_util.c
drivers/target/iscsi/iscsi_target_util.h
drivers/tee/optee/smc_abi.c
drivers/thermal/intel/int340x_thermal/int3400_thermal.c
drivers/thunderbolt/nhi.c
drivers/thunderbolt/nhi_regs.h
drivers/tty/serial/8250/8250_bcm7271.c
drivers/tty/serial/8250/8250_exar.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/8250/8250_port.c
drivers/tty/serial/8250/8250_tegra.c
drivers/tty/serial/Kconfig
drivers/tty/serial/arc_uart.c
drivers/tty/serial/cpm_uart/cpm_uart.h
drivers/tty/serial/fsl_lpuart.c
drivers/tty/serial/qcom_geni_serial.c
drivers/tty/vt/vc_screen.c
drivers/ufs/core/ufs-mcq.c
drivers/ufs/core/ufshcd.c
drivers/uio/uio_dfl.c
drivers/usb/cdns3/cdns3-gadget.c
drivers/usb/class/usbtmc.c
drivers/usb/core/buffer.c
drivers/usb/core/devio.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/debugfs.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/u_ether.c
drivers/usb/gadget/udc/amd5536udc_pci.c
drivers/usb/gadget/udc/core.c
drivers/usb/host/uhci-pci.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.h
drivers/usb/storage/scsiglue.c
drivers/usb/typec/altmodes/displayport.c
drivers/usb/typec/tipd/core.c
drivers/vfio/vfio_iommu_type1.c
drivers/vhost/vhost.c
drivers/video/fbdev/68328fb.c
drivers/video/fbdev/Kconfig
drivers/video/fbdev/arcfb.c
drivers/video/fbdev/atmel_lcdfb.c
drivers/video/fbdev/aty/atyfb_base.c
drivers/video/fbdev/au1100fb.c
drivers/video/fbdev/au1200fb.c
drivers/video/fbdev/broadsheetfb.c
drivers/video/fbdev/bw2.c
drivers/video/fbdev/cg14.c
drivers/video/fbdev/controlfb.c
drivers/video/fbdev/core/bitblit.c
drivers/video/fbdev/core/fbmem.c
drivers/video/fbdev/core/modedb.c
drivers/video/fbdev/g364fb.c
drivers/video/fbdev/hgafb.c
drivers/video/fbdev/hpfb.c
drivers/video/fbdev/i810/i810_dvt.c
drivers/video/fbdev/imsttfb.c
drivers/video/fbdev/macfb.c
drivers/video/fbdev/matrox/matroxfb_maven.c
drivers/video/fbdev/maxinefb.c
drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c
drivers/video/fbdev/p9100.c
drivers/video/fbdev/platinumfb.c
drivers/video/fbdev/sa1100fb.c
drivers/video/fbdev/ssd1307fb.c
drivers/video/fbdev/stifb.c
drivers/video/fbdev/udlfb.c
drivers/video/fbdev/valkyriefb.c
drivers/video/fbdev/vfb.c
drivers/w1/masters/sgi_w1.c
drivers/w1/slaves/Kconfig
drivers/w1/slaves/w1_ds2438.c
drivers/w1/slaves/w1_therm.c
drivers/w1/w1.c
drivers/xen/pvcalls-back.c
fs/Kconfig
fs/Makefile
fs/btrfs/backref.c
fs/btrfs/backref.h
fs/btrfs/bio.c
fs/btrfs/block-group.c
fs/btrfs/block-rsv.c
fs/btrfs/ctree.c
fs/btrfs/disk-io.c
fs/btrfs/file-item.c
fs/btrfs/free-space-cache.c
fs/btrfs/free-space-tree.c
fs/btrfs/free-space-tree.h
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/print-tree.c
fs/btrfs/relocation.c
fs/btrfs/scrub.c
fs/btrfs/super.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/btrfs/zoned.c
fs/ceph/mds_client.c
fs/ceph/snap.c
fs/coredump.c
fs/erofs/Kconfig
fs/erofs/Makefile
fs/erofs/internal.h
fs/erofs/xattr.c
fs/erofs/zdata.c
fs/ext4/balloc.c
fs/ext4/ext4.h
fs/ext4/extents_status.c
fs/ext4/fsync.c
fs/ext4/hash.c
fs/ext4/ialloc.c
fs/ext4/inline.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/migrate.c
fs/ext4/mmp.c
fs/ext4/namei.c
fs/ext4/super.c
fs/ext4/xattr.c
fs/gfs2/super.c
fs/lockd/svc.c
fs/nfs/dir.c
fs/nfs/nfs4proc.c
fs/nfsd/nfsctl.c
fs/nfsd/trace.h
fs/nfsd/vfs.c
fs/nilfs2/inode.c
fs/notify/inotify/inotify_fsnotify.c
fs/pipe.c
fs/smb/Kconfig [new file with mode: 0644]
fs/smb/Makefile [new file with mode: 0644]
fs/smb/client/Kconfig [moved from fs/cifs/Kconfig with 100% similarity]
fs/smb/client/Makefile [moved from fs/cifs/Makefile with 100% similarity]
fs/smb/client/asn1.c [moved from fs/cifs/asn1.c with 100% similarity]
fs/smb/client/cached_dir.c [moved from fs/cifs/cached_dir.c with 100% similarity]
fs/smb/client/cached_dir.h [moved from fs/cifs/cached_dir.h with 100% similarity]
fs/smb/client/cifs_debug.c [moved from fs/cifs/cifs_debug.c with 99% similarity]
fs/smb/client/cifs_debug.h [moved from fs/cifs/cifs_debug.h with 100% similarity]
fs/smb/client/cifs_dfs_ref.c [moved from fs/cifs/cifs_dfs_ref.c with 100% similarity]
fs/smb/client/cifs_fs_sb.h [moved from fs/cifs/cifs_fs_sb.h with 100% similarity]
fs/smb/client/cifs_ioctl.h [moved from fs/cifs/cifs_ioctl.h with 100% similarity]
fs/smb/client/cifs_spnego.c [moved from fs/cifs/cifs_spnego.c with 100% similarity]
fs/smb/client/cifs_spnego.h [moved from fs/cifs/cifs_spnego.h with 100% similarity]
fs/smb/client/cifs_spnego_negtokeninit.asn1 [moved from fs/cifs/cifs_spnego_negtokeninit.asn1 with 100% similarity]
fs/smb/client/cifs_swn.c [moved from fs/cifs/cifs_swn.c with 100% similarity]
fs/smb/client/cifs_swn.h [moved from fs/cifs/cifs_swn.h with 100% similarity]
fs/smb/client/cifs_unicode.c [moved from fs/cifs/cifs_unicode.c with 100% similarity]
fs/smb/client/cifs_unicode.h [moved from fs/cifs/cifs_unicode.h with 100% similarity]
fs/smb/client/cifs_uniupr.h [moved from fs/cifs/cifs_uniupr.h with 100% similarity]
fs/smb/client/cifsacl.c [moved from fs/cifs/cifsacl.c with 100% similarity]
fs/smb/client/cifsacl.h [moved from fs/cifs/cifsacl.h with 100% similarity]
fs/smb/client/cifsencrypt.c [moved from fs/cifs/cifsencrypt.c with 99% similarity]
fs/smb/client/cifsfs.c [moved from fs/cifs/cifsfs.c with 99% similarity]
fs/smb/client/cifsfs.h [moved from fs/cifs/cifsfs.h with 100% similarity]
fs/smb/client/cifsglob.h [moved from fs/cifs/cifsglob.h with 99% similarity]
fs/smb/client/cifspdu.h [moved from fs/cifs/cifspdu.h with 99% similarity]
fs/smb/client/cifsproto.h [moved from fs/cifs/cifsproto.h with 100% similarity]
fs/smb/client/cifsroot.c [moved from fs/cifs/cifsroot.c with 100% similarity]
fs/smb/client/cifssmb.c [moved from fs/cifs/cifssmb.c with 100% similarity]
fs/smb/client/connect.c [moved from fs/cifs/connect.c with 99% similarity]
fs/smb/client/dfs.c [moved from fs/cifs/dfs.c with 99% similarity]
fs/smb/client/dfs.h [moved from fs/cifs/dfs.h with 100% similarity]
fs/smb/client/dfs_cache.c [moved from fs/cifs/dfs_cache.c with 100% similarity]
fs/smb/client/dfs_cache.h [moved from fs/cifs/dfs_cache.h with 100% similarity]
fs/smb/client/dir.c [moved from fs/cifs/dir.c with 100% similarity]
fs/smb/client/dns_resolve.c [moved from fs/cifs/dns_resolve.c with 100% similarity]
fs/smb/client/dns_resolve.h [moved from fs/cifs/dns_resolve.h with 100% similarity]
fs/smb/client/export.c [moved from fs/cifs/export.c with 100% similarity]
fs/smb/client/file.c [moved from fs/cifs/file.c with 99% similarity]
fs/smb/client/fs_context.c [moved from fs/cifs/fs_context.c with 99% similarity]
fs/smb/client/fs_context.h [moved from fs/cifs/fs_context.h with 100% similarity]
fs/smb/client/fscache.c [moved from fs/cifs/fscache.c with 100% similarity]
fs/smb/client/fscache.h [moved from fs/cifs/fscache.h with 100% similarity]
fs/smb/client/inode.c [moved from fs/cifs/inode.c with 100% similarity]
fs/smb/client/ioctl.c [moved from fs/cifs/ioctl.c with 98% similarity]
fs/smb/client/link.c [moved from fs/cifs/link.c with 100% similarity]
fs/smb/client/misc.c [moved from fs/cifs/misc.c with 100% similarity]
fs/smb/client/netlink.c [moved from fs/cifs/netlink.c with 100% similarity]
fs/smb/client/netlink.h [moved from fs/cifs/netlink.h with 100% similarity]
fs/smb/client/netmisc.c [moved from fs/cifs/netmisc.c with 100% similarity]
fs/smb/client/nterr.c [moved from fs/cifs/nterr.c with 100% similarity]
fs/smb/client/nterr.h [moved from fs/cifs/nterr.h with 100% similarity]
fs/smb/client/ntlmssp.h [moved from fs/cifs/ntlmssp.h with 100% similarity]
fs/smb/client/readdir.c [moved from fs/cifs/readdir.c with 100% similarity]
fs/smb/client/rfc1002pdu.h [moved from fs/cifs/rfc1002pdu.h with 100% similarity]
fs/smb/client/sess.c [moved from fs/cifs/sess.c with 100% similarity]
fs/smb/client/smb1ops.c [moved from fs/cifs/smb1ops.c with 99% similarity]
fs/smb/client/smb2file.c [moved from fs/cifs/smb2file.c with 100% similarity]
fs/smb/client/smb2glob.h [moved from fs/cifs/smb2glob.h with 100% similarity]
fs/smb/client/smb2inode.c [moved from fs/cifs/smb2inode.c with 100% similarity]
fs/smb/client/smb2maperror.c [moved from fs/cifs/smb2maperror.c with 100% similarity]
fs/smb/client/smb2misc.c [moved from fs/cifs/smb2misc.c with 100% similarity]
fs/smb/client/smb2ops.c [moved from fs/cifs/smb2ops.c with 99% similarity]
fs/smb/client/smb2pdu.c [moved from fs/cifs/smb2pdu.c with 99% similarity]
fs/smb/client/smb2pdu.h [moved from fs/cifs/smb2pdu.h with 100% similarity]
fs/smb/client/smb2proto.h [moved from fs/cifs/smb2proto.h with 100% similarity]
fs/smb/client/smb2status.h [moved from fs/cifs/smb2status.h with 100% similarity]
fs/smb/client/smb2transport.c [moved from fs/cifs/smb2transport.c with 100% similarity]
fs/smb/client/smbdirect.c [moved from fs/cifs/smbdirect.c with 100% similarity]
fs/smb/client/smbdirect.h [moved from fs/cifs/smbdirect.h with 100% similarity]
fs/smb/client/smbencrypt.c [moved from fs/cifs/smbencrypt.c with 98% similarity]
fs/smb/client/smberr.h [moved from fs/cifs/smberr.h with 100% similarity]
fs/smb/client/trace.c [moved from fs/cifs/trace.c with 100% similarity]
fs/smb/client/trace.h [moved from fs/cifs/trace.h with 100% similarity]
fs/smb/client/transport.c [moved from fs/cifs/transport.c with 100% similarity]
fs/smb/client/unc.c [moved from fs/cifs/unc.c with 100% similarity]
fs/smb/client/winucase.c [moved from fs/cifs/winucase.c with 100% similarity]
fs/smb/client/xattr.c [moved from fs/cifs/xattr.c with 100% similarity]
fs/smb/common/Makefile [moved from fs/smbfs_common/Makefile with 59% similarity]
fs/smb/common/arc4.h [moved from fs/smbfs_common/arc4.h with 100% similarity]
fs/smb/common/cifs_arc4.c [moved from fs/smbfs_common/cifs_arc4.c with 100% similarity]
fs/smb/common/cifs_md4.c [moved from fs/smbfs_common/cifs_md4.c with 100% similarity]
fs/smb/common/md4.h [moved from fs/smbfs_common/md4.h with 100% similarity]
fs/smb/common/smb2pdu.h [moved from fs/smbfs_common/smb2pdu.h with 100% similarity]
fs/smb/common/smbfsctl.h [moved from fs/smbfs_common/smbfsctl.h with 100% similarity]
fs/smb/server/Kconfig [moved from fs/ksmbd/Kconfig with 100% similarity]
fs/smb/server/Makefile [moved from fs/ksmbd/Makefile with 100% similarity]
fs/smb/server/asn1.c [moved from fs/ksmbd/asn1.c with 100% similarity]
fs/smb/server/asn1.h [moved from fs/ksmbd/asn1.h with 100% similarity]
fs/smb/server/auth.c [moved from fs/ksmbd/auth.c with 99% similarity]
fs/smb/server/auth.h [moved from fs/ksmbd/auth.h with 100% similarity]
fs/smb/server/connection.c [moved from fs/ksmbd/connection.c with 99% similarity]
fs/smb/server/connection.h [moved from fs/ksmbd/connection.h with 100% similarity]
fs/smb/server/crypto_ctx.c [moved from fs/ksmbd/crypto_ctx.c with 100% similarity]
fs/smb/server/crypto_ctx.h [moved from fs/ksmbd/crypto_ctx.h with 100% similarity]
fs/smb/server/glob.h [moved from fs/ksmbd/glob.h with 100% similarity]
fs/smb/server/ksmbd_netlink.h [moved from fs/ksmbd/ksmbd_netlink.h with 100% similarity]
fs/smb/server/ksmbd_spnego_negtokeninit.asn1 [moved from fs/ksmbd/ksmbd_spnego_negtokeninit.asn1 with 100% similarity]
fs/smb/server/ksmbd_spnego_negtokentarg.asn1 [moved from fs/ksmbd/ksmbd_spnego_negtokentarg.asn1 with 100% similarity]
fs/smb/server/ksmbd_work.c [moved from fs/ksmbd/ksmbd_work.c with 100% similarity]
fs/smb/server/ksmbd_work.h [moved from fs/ksmbd/ksmbd_work.h with 100% similarity]
fs/smb/server/mgmt/ksmbd_ida.c [moved from fs/ksmbd/mgmt/ksmbd_ida.c with 100% similarity]
fs/smb/server/mgmt/ksmbd_ida.h [moved from fs/ksmbd/mgmt/ksmbd_ida.h with 100% similarity]
fs/smb/server/mgmt/share_config.c [moved from fs/ksmbd/mgmt/share_config.c with 100% similarity]
fs/smb/server/mgmt/share_config.h [moved from fs/ksmbd/mgmt/share_config.h with 100% similarity]
fs/smb/server/mgmt/tree_connect.c [moved from fs/ksmbd/mgmt/tree_connect.c with 100% similarity]
fs/smb/server/mgmt/tree_connect.h [moved from fs/ksmbd/mgmt/tree_connect.h with 100% similarity]
fs/smb/server/mgmt/user_config.c [moved from fs/ksmbd/mgmt/user_config.c with 100% similarity]
fs/smb/server/mgmt/user_config.h [moved from fs/ksmbd/mgmt/user_config.h with 100% similarity]
fs/smb/server/mgmt/user_session.c [moved from fs/ksmbd/mgmt/user_session.c with 100% similarity]
fs/smb/server/mgmt/user_session.h [moved from fs/ksmbd/mgmt/user_session.h with 100% similarity]
fs/smb/server/misc.c [moved from fs/ksmbd/misc.c with 100% similarity]
fs/smb/server/misc.h [moved from fs/ksmbd/misc.h with 100% similarity]
fs/smb/server/ndr.c [moved from fs/ksmbd/ndr.c with 100% similarity]
fs/smb/server/ndr.h [moved from fs/ksmbd/ndr.h with 100% similarity]
fs/smb/server/nterr.h [moved from fs/ksmbd/nterr.h with 100% similarity]
fs/smb/server/ntlmssp.h [moved from fs/ksmbd/ntlmssp.h with 100% similarity]
fs/smb/server/oplock.c [moved from fs/ksmbd/oplock.c with 97% similarity]
fs/smb/server/oplock.h [moved from fs/ksmbd/oplock.h with 99% similarity]
fs/smb/server/server.c [moved from fs/ksmbd/server.c with 100% similarity]
fs/smb/server/server.h [moved from fs/ksmbd/server.h with 100% similarity]
fs/smb/server/smb2misc.c [moved from fs/ksmbd/smb2misc.c with 98% similarity]
fs/smb/server/smb2ops.c [moved from fs/ksmbd/smb2ops.c with 100% similarity]
fs/smb/server/smb2pdu.c [moved from fs/ksmbd/smb2pdu.c with 99% similarity]
fs/smb/server/smb2pdu.h [moved from fs/ksmbd/smb2pdu.h with 100% similarity]
fs/smb/server/smb_common.c [moved from fs/ksmbd/smb_common.c with 100% similarity]
fs/smb/server/smb_common.h [moved from fs/ksmbd/smb_common.h with 99% similarity]
fs/smb/server/smbacl.c [moved from fs/ksmbd/smbacl.c with 100% similarity]
fs/smb/server/smbacl.h [moved from fs/ksmbd/smbacl.h with 100% similarity]
fs/smb/server/smbfsctl.h [moved from fs/ksmbd/smbfsctl.h with 98% similarity]
fs/smb/server/smbstatus.h [moved from fs/ksmbd/smbstatus.h with 99% similarity]
fs/smb/server/transport_ipc.c [moved from fs/ksmbd/transport_ipc.c with 100% similarity]
fs/smb/server/transport_ipc.h [moved from fs/ksmbd/transport_ipc.h with 100% similarity]
fs/smb/server/transport_rdma.c [moved from fs/ksmbd/transport_rdma.c with 100% similarity]
fs/smb/server/transport_rdma.h [moved from fs/ksmbd/transport_rdma.h with 100% similarity]
fs/smb/server/transport_tcp.c [moved from fs/ksmbd/transport_tcp.c with 100% similarity]
fs/smb/server/transport_tcp.h [moved from fs/ksmbd/transport_tcp.h with 100% similarity]
fs/smb/server/unicode.c [moved from fs/ksmbd/unicode.c with 100% similarity]
fs/smb/server/unicode.h [moved from fs/ksmbd/unicode.h with 100% similarity]
fs/smb/server/uniupr.h [moved from fs/ksmbd/uniupr.h with 100% similarity]
fs/smb/server/vfs.c [moved from fs/ksmbd/vfs.c with 99% similarity]
fs/smb/server/vfs.h [moved from fs/ksmbd/vfs.h with 100% similarity]
fs/smb/server/vfs_cache.c [moved from fs/ksmbd/vfs_cache.c with 100% similarity]
fs/smb/server/vfs_cache.h [moved from fs/ksmbd/vfs_cache.h with 100% similarity]
fs/smb/server/xattr.h [moved from fs/ksmbd/xattr.h with 100% similarity]
fs/statfs.c
fs/xattr.c
fs/xfs/libxfs/xfs_ag.c
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/scrub/bmap.c
fs/xfs/scrub/common.c
fs/xfs/scrub/common.h
fs/xfs/scrub/fscounters.c
fs/xfs/scrub/scrub.c
fs/xfs/scrub/scrub.h
fs/xfs/scrub/trace.h
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_icache.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_super.c
include/asm-generic/vmlinux.lds.h
include/drm/display/drm_dp.h
include/drm/display/drm_dp_helper.h
include/drm/drm_managed.h
include/dt-bindings/mux/ti-serdes.h
include/linux/amba/bus.h
include/linux/arm_ffa.h
include/linux/blkdev.h
include/linux/compiler.h
include/linux/cper.h
include/linux/device/class.h
include/linux/dim.h
include/linux/efi.h
include/linux/firewire.h
include/linux/firmware/xlnx-zynqmp.h
include/linux/fs.h
include/linux/i8254.h [new file with mode: 0644]
include/linux/if_team.h
include/linux/if_vlan.h
include/linux/iio/common/st_sensors.h
include/linux/iio/iio-gts-helper.h
include/linux/iio/iio.h
include/linux/iio/trigger.h
include/linux/io_uring.h
include/linux/lockdep.h
include/linux/lockdep_types.h
include/linux/mfd/tps6594.h [new file with mode: 0644]
include/linux/mlx5/driver.h
include/linux/mlx5/mlx5_ifc.h
include/linux/msi.h
include/linux/page-flags.h
include/linux/parport.h
include/linux/pci_ids.h
include/linux/pe.h
include/linux/phy.h
include/linux/platform_data/st_sensors_pdata.h
include/linux/power/bq27xxx_battery.h
include/linux/sched/task.h
include/linux/sched/vhost_task.h
include/linux/shrinker.h
include/linux/skbuff.h
include/linux/skmsg.h
include/linux/sunrpc/svc_rdma.h
include/linux/sunrpc/svc_xprt.h
include/linux/sunrpc/svcsock.h
include/linux/tpm.h
include/linux/trace_events.h
include/linux/uacce.h
include/linux/usb/composite.h
include/linux/usb/hcd.h
include/linux/user_events.h
include/media/dvb_frontend.h
include/media/dvb_net.h
include/media/dvbdev.h
include/media/v4l2-subdev.h
include/net/bluetooth/hci_core.h
include/net/bonding.h
include/net/handshake.h
include/net/ip.h
include/net/mana/mana.h
include/net/nexthop.h
include/net/page_pool.h
include/net/sock.h
include/net/tcp.h
include/net/tls.h
include/sound/hda-mlink.h
include/sound/soc-acpi.h
include/sound/soc-dpcm.h
include/target/iscsi/iscsi_target_core.h
include/uapi/linux/counter.h
include/uapi/linux/handshake.h
include/uapi/linux/in.h
include/uapi/linux/tps6594_pfsm.h [new file with mode: 0644]
include/uapi/sound/skl-tplg-interface.h
include/uapi/sound/sof/tokens.h
include/ufs/ufshcd.h
io_uring/epoll.c
io_uring/sqpoll.c
kernel/bpf/hashtab.c
kernel/bpf/offload.c
kernel/bpf/verifier.c
kernel/events/core.c
kernel/exit.c
kernel/fork.c
kernel/irq/msi.c
kernel/locking/lockdep.c
kernel/locking/rwsem.c
kernel/module/decompress.c
kernel/module/main.c
kernel/module/stats.c
kernel/sched/core.c
kernel/signal.c
kernel/time/tick-broadcast.c
kernel/trace/fprobe.c
kernel/trace/rethook.c
kernel/trace/trace.c
kernel/trace/trace_events.c
kernel/trace/trace_events_hist.c
kernel/trace/trace_events_user.c
kernel/trace/trace_osnoise.c
kernel/trace/trace_probe.h
kernel/trace/trace_selftest.c
kernel/vhost_task.c
lib/debugobjects.c
lib/dim/dim.c
lib/dim/net_dim.c
lib/dim/rdma_dim.c
lib/maple_tree.c
lib/test_firmware.c
mm/Kconfig.debug
mm/kfence/kfence.h
mm/page_table_check.c
mm/shrinker_debug.c
mm/vmscan.c
mm/zsmalloc.c
mm/zswap.c
net/8021q/vlan_dev.c
net/atm/resources.c
net/bluetooth/hci_conn.c
net/bridge/br_forward.c
net/bridge/br_private_tunnel.h
net/can/isotp.c
net/can/j1939/socket.c
net/core/datagram.c
net/core/dev.c
net/core/page_pool.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/skmsg.c
net/core/sock.c
net/core/sock_map.c
net/core/stream.c
net/devlink/core.c
net/devlink/devl_internal.h
net/devlink/leftover.c
net/handshake/handshake-test.c
net/handshake/handshake.h
net/handshake/netlink.c
net/handshake/request.c
net/handshake/tlshd.c
net/ipv4/af_inet.c
net/ipv4/inet_connection_sock.c
net/ipv4/ip_sockglue.c
net/ipv4/raw.c
net/ipv4/tcp.c
net/ipv4/tcp_bpf.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_timer.c
net/ipv4/udp.c
net/ipv4/udplite.c
net/ipv6/exthdrs_core.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_gre.c
net/ipv6/raw.c
net/ipv6/udplite.c
net/key/af_key.c
net/llc/af_llc.c
net/mac80211/cfg.c
net/mac80211/chan.c
net/mac80211/ieee80211_i.h
net/mac80211/trace.h
net/mac80211/tx.c
net/mac80211/util.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/netfilter/core.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_chain_filter.c
net/netfilter/nft_set_rbtree.c
net/netlink/af_netlink.c
net/netrom/nr_subr.c
net/nsh/nsh.c
net/packet/af_packet.c
net/packet/diag.c
net/rxrpc/af_rxrpc.c
net/rxrpc/ar-internal.h
net/rxrpc/local_event.c
net/sched/cls_flower.c
net/sched/sch_api.c
net/sched/sch_ingress.c
net/sctp/transport.c
net/smc/af_smc.c
net/smc/smc_close.c
net/smc/smc_core.c
net/smc/smc_llc.c
net/smc/smc_rx.c
net/smc/smc_tx.c
net/socket.c
net/sunrpc/auth_gss/gss_krb5_crypto.c
net/sunrpc/sched.c
net/sunrpc/svc.c
net/sunrpc/svc_xprt.c
net/sunrpc/svcsock.c
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
net/sunrpc/xprtrdma/svc_rdma_transport.c
net/tipc/bearer.c
net/tipc/bearer.h
net/tipc/link.c
net/tipc/socket.c
net/tipc/udp_media.c
net/tls/tls.h
net/tls/tls_device.c
net/tls/tls_main.c
net/tls/tls_strp.c
net/tls/tls_sw.c
net/unix/af_unix.c
net/vmw_vsock/af_vsock.c
net/vmw_vsock/virtio_transport_common.c
net/wireless/scan.c
net/xfrm/xfrm_device.c
net/xfrm/xfrm_interface_core.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_user.c
samples/Kconfig
samples/Makefile
samples/bpf/hbm.c
samples/pfsm/.gitignore [new file with mode: 0644]
samples/pfsm/Makefile [new file with mode: 0644]
samples/pfsm/pfsm-wakeup.c [new file with mode: 0644]
scripts/tags.sh
security/selinux/Makefile
sound/core/oss/pcm_plugin.h
sound/firewire/digi00x/digi00x-stream.c
sound/hda/hdac_device.c
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/hda/hda_generic.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/amd/yc/acp6x-mach.c
sound/soc/codecs/cs35l41-lib.c
sound/soc/codecs/cs35l56.c
sound/soc/codecs/lpass-tx-macro.c
sound/soc/codecs/rt5682-i2c.c
sound/soc/codecs/rt5682.c
sound/soc/codecs/rt5682.h
sound/soc/codecs/ssm2602.c
sound/soc/dwc/dwc-i2s.c
sound/soc/fsl/fsl_micfil.c
sound/soc/intel/avs/apl.c
sound/soc/intel/avs/avs.h
sound/soc/intel/avs/board_selection.c
sound/soc/intel/avs/control.c
sound/soc/intel/avs/dsp.c
sound/soc/intel/avs/messages.h
sound/soc/intel/avs/path.h
sound/soc/intel/avs/pcm.c
sound/soc/intel/avs/probes.c
sound/soc/jz4740/jz4740-i2s.c
sound/soc/mediatek/mt8186/mt8186-afe-clk.c
sound/soc/mediatek/mt8186/mt8186-afe-clk.h
sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
sound/soc/mediatek/mt8186/mt8186-audsys-clk.c
sound/soc/mediatek/mt8186/mt8186-audsys-clk.h
sound/soc/soc-pcm.c
sound/soc/sof/amd/acp-ipc.c
sound/soc/sof/debug.c
sound/soc/sof/intel/hda-mlink.c
sound/soc/sof/ipc3-topology.c
sound/soc/sof/ipc4-topology.c
sound/soc/sof/pcm.c
sound/soc/sof/pm.c
sound/soc/sof/sof-client-probes.c
sound/soc/sof/topology.c
sound/usb/format.c
tools/arch/arm64/include/uapi/asm/kvm.h
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/asm/disabled-features.h
tools/arch/x86/include/asm/msr-index.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/arch/x86/include/uapi/asm/prctl.h
tools/arch/x86/include/uapi/asm/unistd_32.h
tools/arch/x86/lib/memcpy_64.S
tools/arch/x86/lib/memset_64.S
tools/counter/.gitignore [new file with mode: 0644]
tools/counter/Makefile
tools/gpio/lsgpio.c
tools/include/asm/alternative.h
tools/include/linux/coresight-pmu.h
tools/include/uapi/drm/drm.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/const.h
tools/include/uapi/linux/in.h
tools/include/uapi/linux/kvm.h
tools/include/uapi/linux/prctl.h
tools/include/uapi/sound/asound.h
tools/net/ynl/lib/ynl.py
tools/perf/Makefile.config
tools/perf/Makefile.perf
tools/perf/arch/arm/util/cs-etm.c
tools/perf/arch/arm/util/pmu.c
tools/perf/arch/arm64/util/header.c
tools/perf/arch/arm64/util/pmu.c
tools/perf/arch/s390/entry/syscalls/syscall.tbl
tools/perf/bench/mem-memcpy-x86-64-asm-def.h
tools/perf/bench/mem-memcpy-x86-64-asm.S
tools/perf/bench/mem-memset-x86-64-asm-def.h
tools/perf/bench/mem-memset-x86-64-asm.S
tools/perf/builtin-ftrace.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/pmu-events/arch/x86/alderlake/adl-metrics.json
tools/perf/pmu-events/arch/x86/alderlaken/adln-metrics.json
tools/perf/pmu-events/arch/x86/broadwell/bdw-metrics.json
tools/perf/pmu-events/arch/x86/broadwellde/bdwde-metrics.json
tools/perf/pmu-events/arch/x86/broadwellx/bdx-metrics.json
tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json
tools/perf/pmu-events/arch/x86/haswell/hsw-metrics.json
tools/perf/pmu-events/arch/x86/haswellx/hsx-metrics.json
tools/perf/pmu-events/arch/x86/icelake/icl-metrics.json
tools/perf/pmu-events/arch/x86/icelakex/icx-metrics.json
tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json
tools/perf/pmu-events/arch/x86/ivytown/ivt-metrics.json
tools/perf/pmu-events/arch/x86/jaketown/jkt-metrics.json
tools/perf/pmu-events/arch/x86/sandybridge/snb-metrics.json
tools/perf/pmu-events/arch/x86/sapphirerapids/spr-metrics.json
tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json
tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json
tools/perf/pmu-events/arch/x86/tigerlake/tgl-metrics.json
tools/perf/pmu-events/jevents.py
tools/perf/pmu-events/pmu-events.h
tools/perf/tests/attr.py
tools/perf/tests/attr/base-stat
tools/perf/tests/attr/test-stat-default
tools/perf/tests/attr/test-stat-detailed-1
tools/perf/tests/attr/test-stat-detailed-2
tools/perf/tests/attr/test-stat-detailed-3
tools/perf/tests/expr.c
tools/perf/tests/parse-metric.c
tools/perf/tests/shell/stat.sh
tools/perf/tests/shell/test_intel_pt.sh
tools/perf/tests/shell/test_java_symbol.sh
tools/perf/trace/beauty/arch_prctl.c
tools/perf/trace/beauty/x86_arch_prctl.sh
tools/perf/util/Build
tools/perf/util/bpf_skel/lock_contention.bpf.c
tools/perf/util/bpf_skel/sample_filter.bpf.c
tools/perf/util/bpf_skel/vmlinux.h
tools/perf/util/cs-etm.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/expr.y
tools/perf/util/metricgroup.c
tools/perf/util/parse-events.c
tools/perf/util/stat-display.c
tools/perf/util/stat-shadow.c
tools/perf/util/symbol-elf.c
tools/power/cpupower/lib/powercap.c
tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
tools/testing/cxl/Kbuild
tools/testing/cxl/test/mem.c
tools/testing/cxl/test/mock.c
tools/testing/selftests/bpf/Makefile
tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h [new file with mode: 0644]
tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
tools/testing/selftests/bpf/progs/test_sockmap_drop_prog.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/test_sockmap_kern.h
tools/testing/selftests/bpf/progs/test_sockmap_pass_prog.c [new file with mode: 0644]
tools/testing/selftests/drivers/net/bonding/bond_options.sh
tools/testing/selftests/drivers/net/bonding/bond_topo_3d1c.sh
tools/testing/selftests/ftrace/Makefile
tools/testing/selftests/ftrace/ftracetest
tools/testing/selftests/ftrace/ftracetest-ktap [new file with mode: 0755]
tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-stack-legacy.tc [new file with mode: 0644]
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-stack.tc
tools/testing/selftests/gpio/gpio-sim.sh
tools/testing/selftests/kvm/Makefile
tools/testing/selftests/kvm/x86_64/recalc_apic_map_test.c [new file with mode: 0644]
tools/testing/selftests/net/fib_nexthops.sh
tools/testing/selftests/net/fib_tests.sh
tools/testing/selftests/net/forwarding/lib.sh
tools/testing/selftests/net/mptcp/Makefile
tools/testing/selftests/net/mptcp/diag.sh
tools/testing/selftests/net/mptcp/mptcp_connect.sh
tools/testing/selftests/net/mptcp/mptcp_join.sh
tools/testing/selftests/net/mptcp/mptcp_lib.sh [new file with mode: 0644]
tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
tools/testing/selftests/net/mptcp/pm_netlink.sh
tools/testing/selftests/net/mptcp/simult_flows.sh
tools/testing/selftests/net/mptcp/userspace_pm.sh
tools/testing/selftests/net/srv6_end_dt4_l3vpn_test.sh
tools/testing/selftests/netfilter/nft_flowtable.sh
tools/testing/selftests/sgx/Makefile
virt/kvm/kvm_main.c

index 71127b2608d20913bd29b3c87835d115391fb3d7..bf076bbc36b1e2207d0b12fa525fdc3fe30d715d 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -364,6 +364,11 @@ Nicolas Pitre <nico@fluxnic.net> <nico@linaro.org>
 Nicolas Saenz Julienne <nsaenz@kernel.org> <nsaenzjulienne@suse.de>
 Nicolas Saenz Julienne <nsaenz@kernel.org> <nsaenzjulienne@suse.com>
 Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+Nikolay Aleksandrov <razor@blackwall.org> <naleksan@redhat.com>
+Nikolay Aleksandrov <razor@blackwall.org> <nikolay@redhat.com>
+Nikolay Aleksandrov <razor@blackwall.org> <nikolay@cumulusnetworks.com>
+Nikolay Aleksandrov <razor@blackwall.org> <nikolay@nvidia.com>
+Nikolay Aleksandrov <razor@blackwall.org> <nikolay@isovalent.com>
 Oleksandr Natalenko <oleksandr@natalenko.name> <oleksandr@redhat.com>
 Oleksij Rempel <linux@rempel-privat.de> <bug-track@fisher-privat.net>
 Oleksij Rempel <linux@rempel-privat.de> <external.Oleksij.Rempel@de.bosch.com>
diff --git a/CREDITS b/CREDITS
index 2d9da9a7defa666cbfcd2aab7fcca821f2027066..de7e4dbbc5991194ce9bcaeb94a368e79d79832a 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1706,6 +1706,10 @@ S: Panoramastrasse 18
 S: D-69126 Heidelberg
 S: Germany
 
+N: Neil Horman
+M: nhorman@tuxdriver.com
+D: SCTP protocol maintainer.
+
 N: Simon Horman
 M: horms@verge.net.au
 D: Renesas ARM/ARM64 SoC maintainer
index 1417c4272c6ca4e9a2a0c560e0211a89571fd3ef..dc3b3a5c876b2591aae58f6df61f96a9e121bc3c 100644 (file)
@@ -90,6 +90,60 @@ Description:
                        counter does not freeze at the boundary points, but
                        counts continuously throughout.
 
+               interrupt on terminal count:
+                       The output signal is initially low, and will remain low
+                       until the counter reaches zero. The output signal then
+                       goes high and remains high until a new preset value is
+                       set.
+
+               hardware retriggerable one-shot:
+                       The output signal is initially high. The output signal
+                       will go low by a trigger input signal, and will remain
+                       low until the counter reaches zero. The output will then
+                       go high and remain high until the next trigger. A
+                       trigger results in loading the counter to the preset
+                       value and setting the output signal low, thus starting
+                       the one-shot pulse.
+
+               rate generator:
+                       The output signal is initially high. When the counter
+                       has decremented to 1, the output signal goes low for one
+                       clock pulse. The output signal then goes high again, the
+                       counter is reloaded to the preset value, and the process
+                       repeats in a periodic manner as such.
+
+               square wave mode:
+                       The output signal is initially high.
+
+                       If the initial count is even, the counter is decremented
+                       by two on succeeding clock pulses. When the count
+                       expires, the output signal changes value and the
+                       counter is reloaded to the preset value. The process
+                       repeats in periodic manner as such.
+
+                       If the initial count is odd, the initial count minus one
+                       (an even number) is loaded and then is decremented by
+                       two on succeeding clock pulses. One clock pulse after
+                       the count expires, the output signal goes low and the
+                       counter is reloaded to the preset value minus one.
+                       Succeeding clock pulses decrement the count by two. When
+                       the count expires, the output goes high again and the
+                       counter is reloaded to the preset value minus one. The
+                       process repeats in a periodic manner as such.
+
+               software triggered strobe:
+                       The output signal is initially high. When the count
+                       expires, the output will go low for one clock pulse and
+                       then go high again. The counting sequence is "triggered"
+                       by setting the preset value.
+
+               hardware triggered strobe:
+                       The output signal is initially high. Counting is started
+                       by a trigger input signal. When the count expires, the
+                       output signal will go low for one clock pulse and then
+                       go high again. A trigger results in loading the counter
+                       to the preset value.
+
 What:          /sys/bus/counter/devices/counterX/countY/count_mode_available
 What:          /sys/bus/counter/devices/counterX/countY/error_noise_available
 What:          /sys/bus/counter/devices/counterX/countY/function_available
index 3147bbae9c43f21a41c5e110404821b5c2027e62..8c42c4de510b1046eeca71db2dd2e15bbde11897 100644 (file)
@@ -5,5 +5,5 @@ Changes
 See https://wiki.samba.org/index.php/LinuxCIFSKernel for summary
 information about fixes/improvements to CIFS/SMB2/SMB3 support (changes
 to cifs.ko module) by kernel version (and cifs internal module version).
-This may be easier to read than parsing the output of "git log fs/cifs"
-by release.
+This may be easier to read than parsing the output of
+"git log fs/smb/client" by release.
index 2e151cd8c2e4de65c13d5c1f51b346911bc45d98..5f936b4b601881d3e031b71a1cc258c5ddb9585e 100644 (file)
@@ -45,7 +45,7 @@ Installation instructions
 
 If you have built the CIFS vfs as module (successfully) simply
 type ``make modules_install`` (or if you prefer, manually copy the file to
-the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.ko).
+the modules directory e.g. /lib/modules/6.3.0-060300-generic/kernel/fs/smb/client/cifs.ko).
 
 If you have built the CIFS vfs into the kernel itself, follow the instructions
 for your distribution on how to install a new kernel (usually you
@@ -66,15 +66,15 @@ If cifs is built as a module, then the size and number of network buffers
 and maximum number of simultaneous requests to one server can be configured.
 Changing these from their defaults is not recommended. By executing modinfo::
 
-       modinfo kernel/fs/cifs/cifs.ko
+       modinfo <path to cifs.ko>
 
-on kernel/fs/cifs/cifs.ko the list of configuration changes that can be made
+on kernel/fs/smb/client/cifs.ko the list of configuration changes that can be made
 at module initialization time (by running insmod cifs.ko) can be seen.
 
 Recommendations
 ===============
 
-To improve security the SMB2.1 dialect or later (usually will get SMB3) is now
+To improve security the SMB2.1 dialect or later (usually will get SMB3.1.1) is now
 the new default. To use old dialects (e.g. to mount Windows XP) use "vers=1.0"
 on mount (or vers=2.0 for Windows Vista).  Note that the CIFS (vers=1.0) is
 much older and less secure than the default dialect SMB3 which includes
index ff4f4cc8522bdbfa018269c1704a95827bd81c26..f08149bc53f84dd427e514d7eb898169030da8a7 100644 (file)
@@ -215,12 +215,14 @@ again.
    reduce the compile time enormously, especially if you are running an
    universal kernel from a commodity Linux distribution.
 
-   There is a catch: the make target 'localmodconfig' will disable kernel
-   features you have not directly or indirectly through some program utilized
-   since you booted the system. You can reduce or nearly eliminate that risk by
-   using tricks outlined in the reference section; for quick testing purposes
-   that risk is often negligible, but it is an aspect you want to keep in mind
-   in case your kernel behaves oddly.
+   There is a catch: 'localmodconfig' is likely to disable kernel features you
+   did not use since you booted your Linux -- like drivers for currently
+   disconnected peripherals or a virtualization software not haven't used yet.
+   You can reduce or nearly eliminate that risk with tricks the reference
+   section outlines; but when building a kernel just for quick testing purposes
+   it is often negligible if such features are missing. But you should keep that
+   aspect in mind when using a kernel built with this make target, as it might
+   be the reason why something you only use occasionally stopped working.
 
    [:ref:`details<configuration>`]
 
@@ -271,6 +273,9 @@ again.
    does nothing at all; in that case you have to manually install your kernel,
    as outlined in the reference section.
 
+   If you are running a immutable Linux distribution, check its documentation
+   and the web to find out how to install your own kernel there.
+
    [:ref:`details<install>`]
 
 .. _another_sbs:
@@ -291,29 +296,29 @@ again.
    version you care about, as git otherwise might retrieve the entire commit
    history::
 
-     git fetch --shallow-exclude=v6.1 origin
-
-   If you modified the sources (for example by applying a patch), you now need
-   to discard those modifications; that's because git otherwise will not be able
-   to switch to the sources of another version due to potential conflicting
-   changes::
-
-     git reset --hard
+     git fetch --shallow-exclude=v6.0 origin
 
-   Now checkout the version you are interested in, as explained above::
+   Now switch to the version you are interested in -- but be aware the command
+   used here will discard any modifications you performed, as they would
+   conflict with the sources you want to checkout::
 
-     git checkout --detach origin/master
+     git checkout --force --detach origin/master
 
    At this point you might want to patch the sources again or set/modify a build
-   tag, as explained earlier; afterwards adjust the build configuration to the
-   new codebase and build your next kernel::
+   tag, as explained earlier. Afterwards adjust the build configuration to the
+   new codebase using olddefconfig, which will now adjust the configuration file
+   you prepared earlier using localmodconfig  (~/linux/.config) for your next
+   kernel::
 
      # reminder: if you want to apply patches, do it at this point
      # reminder: you might want to update your build tag at this point
      make olddefconfig
+
+   Now build your kernel::
+
      make -j $(nproc --all)
 
-   Install the kernel as outlined above::
+   Afterwards install the kernel as outlined above::
 
      command -v installkernel && sudo make modules_install install
 
@@ -584,11 +589,11 @@ versions and individual commits at hand at any time::
     curl -L \
       https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/clone.bundle \
       -o linux-stable.git.bundle
-    git clone clone.bundle ~/linux/
+    git clone linux-stable.git.bundle ~/linux/
     rm linux-stable.git.bundle
     cd ~/linux/
-    git remote set-url origin
-    https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
+    git remote set-url origin \
+      https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
     git fetch origin
     git checkout --detach origin/master
 
index 102953166429bfea82614f452a8b17e38adcde49..9fea696f9daa0121a2e3e57368e2ebd44cbe0848 100644 (file)
@@ -18,7 +18,6 @@ Block
    kyber-iosched
    null_blk
    pr
-   request
    stat
    switching-sched
    writeback_cache_control
diff --git a/Documentation/block/request.rst b/Documentation/block/request.rst
deleted file mode 100644 (file)
index 747021e..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-============================
-struct request documentation
-============================
-
-Jens Axboe <jens.axboe@oracle.com> 27/05/02
-
-
-.. FIXME:
-   No idea about what does mean - seems just some noise, so comment it
-
-   1.0
-   Index
-
-   2.0 Struct request members classification
-
-       2.1 struct request members explanation
-
-   3.0
-
-
-   2.0
-
-
-
-Short explanation of request members
-====================================
-
-Classification flags:
-
-       =       ====================
-       D       driver member
-       B       block layer member
-       I       I/O scheduler member
-       =       ====================
-
-Unless an entry contains a D classification, a device driver must not access
-this member. Some members may contain D classifications, but should only be
-access through certain macros or functions (eg ->flags).
-
-<linux/blkdev.h>
-
-=============================== ======= =======================================
-Member                         Flag    Comment
-=============================== ======= =======================================
-struct list_head queuelist     BI      Organization on various internal
-                                       queues
-
-``void *elevator_private``     I       I/O scheduler private data
-
-unsigned char cmd[16]          D       Driver can use this for setting up
-                                       a cdb before execution, see
-                                       blk_queue_prep_rq
-
-unsigned long flags            DBI     Contains info about data direction,
-                                       request type, etc.
-
-int rq_status                  D       Request status bits
-
-kdev_t rq_dev                  DBI     Target device
-
-int errors                     DB      Error counts
-
-sector_t sector                        DBI     Target location
-
-unsigned long hard_nr_sectors  B       Used to keep sector sane
-
-unsigned long nr_sectors       DBI     Total number of sectors in request
-
-unsigned long hard_nr_sectors  B       Used to keep nr_sectors sane
-
-unsigned short nr_phys_segments        DB      Number of physical scatter gather
-                                       segments in a request
-
-unsigned short nr_hw_segments  DB      Number of hardware scatter gather
-                                       segments in a request
-
-unsigned int current_nr_sectors        DB      Number of sectors in first segment
-                                       of request
-
-unsigned int hard_cur_sectors  B       Used to keep current_nr_sectors sane
-
-int tag                                DB      TCQ tag, if assigned
-
-``void *special``              D       Free to be used by driver
-
-``char *buffer``               D       Map of first segment, also see
-                                       section on bouncing SECTION
-
-``struct completion *waiting`` D       Can be used by driver to get signalled
-                                       on request completion
-
-``struct bio *bio``            DBI     First bio in request
-
-``struct bio *biotail``                DBI     Last bio in request
-
-``struct request_queue *q``    DB      Request queue this request belongs to
-
-``struct request_list *rl``    B       Request list this request came from
-=============================== ======= =======================================
index e87a8785bc1a7172e7ed0ae897da3ba994b87587..e9b022d7093957d0e698cbc2ba0a303e3f6e4b4c 100644 (file)
@@ -1,8 +1,8 @@
 .. SPDX-License-Identifier: GPL-2.0
 
-=====
-cdrom
-=====
+======
+CD-ROM
+======
 
 .. toctree::
     :maxdepth: 1
index 9b31f864e071ee7c53f63eb87db631eb20c1e075..71364c6081ff50d9573102aa48c9bbaa4ea75f1e 100644 (file)
@@ -32,7 +32,7 @@ properties:
     maxItems: 1
 
   iommus:
-    maxItems: 1
+    maxItems: 4
 
   power-domains:
     maxItems: 1
index e6c1ebfe8a324773cab5a53a4a98fd294cdd9c99..130e16d025bcf8242249e9e0ee83941001c4247c 100644 (file)
@@ -82,6 +82,18 @@ properties:
       Indicates if the DSI controller is driving a panel which needs
       2 DSI links.
 
+  qcom,master-dsi:
+    type: boolean
+    description: |
+      Indicates if the DSI controller is the master DSI controller when
+      qcom,dual-dsi-mode enabled.
+
+  qcom,sync-dual-dsi:
+    type: boolean
+    description: |
+      Indicates if the DSI controller needs to sync the other DSI controller
+      with MIPI DCS commands when qcom,dual-dsi-mode enabled.
+
   assigned-clocks:
     minItems: 2
     maxItems: 4
index 6a9c96f0352ac3b781a56eefa6c2d282a0483a4a..2c8cf6aab19a20cc8c80bee989b634567330b0b9 100644 (file)
@@ -27,10 +27,14 @@ properties:
 
   interrupt-names:
     minItems: 1
-    items:
-      - const: usb_id
-      - const: usb_vbus
-
+    anyOf:
+      - items:
+          - const: usb_id
+          - const: usb_vbus
+      - items:
+          - const: usb_id
+      - items:
+          - const: usb_vbus
 required:
   - compatible
   - reg
@@ -49,7 +53,7 @@ examples:
             interrupt-controller;
             #interrupt-cells = <4>;
 
-            usb_id: misc@900 {
+            usb_id: usb-detect@900 {
                     compatible = "qcom,pm8941-misc";
                     reg = <0x900>;
                     interrupts = <0x0 0x9 0 IRQ_TYPE_EDGE_BOTH>;
index efdf59abb2e18b454f194c4e2bb4401ee725d187..351b202d0e10f0f23a60b57564c797baac4c6ba7 100644 (file)
@@ -23,7 +23,7 @@ properties:
       headphone detect mode to HPDETL, ARIZONA_ACCDET_MODE_HPR/2 sets it
       to HPDETR.  If this node is not included or if the value is unknown,
       then headphone detection mode is set to HPDETL.
-    $ref: "/schemas/types.yaml#/definitions/uint32"
+    $ref: /schemas/types.yaml#/definitions/uint32
     minimum: 1
     maximum: 2
 
@@ -51,7 +51,7 @@ properties:
     description:
       Additional software microphone detection debounce specified in
       milliseconds.
-    $ref: "/schemas/types.yaml#/definitions/uint32"
+    $ref: /schemas/types.yaml#/definitions/uint32
 
   wlf,micd-pol-gpio:
     description:
@@ -63,7 +63,7 @@ properties:
     description:
       Time allowed for MICBIAS to startup prior to performing microphone
       detection, specified as per the ARIZONA_MICD_TIME_XXX defines.
-    $ref: "/schemas/types.yaml#/definitions/uint32"
+    $ref: /schemas/types.yaml#/definitions/uint32
     minimum: 0
     maximum: 12
 
@@ -71,7 +71,7 @@ properties:
     description:
       Delay between successive microphone detection measurements, specified
       as per the ARIZONA_MICD_TIME_XXX defines.
-    $ref: "/schemas/types.yaml#/definitions/uint32"
+    $ref: /schemas/types.yaml#/definitions/uint32
     minimum: 0
     maximum: 12
 
@@ -79,7 +79,7 @@ properties:
     description:
       Microphone detection hardware debounces specified as the number of
       measurements to take.
-    $ref: "/schemas/types.yaml#/definitions/uint32"
+    $ref: /schemas/types.yaml#/definitions/uint32
     enum: [2, 4]
 
   wlf,micd-timeout-ms:
@@ -97,7 +97,7 @@ properties:
       CTIA / OMTP headsets), the field can be of variable length but
       should always be a multiple of 3 cells long, each three cell group
       represents one polarity configuration.
-    $ref: "/schemas/types.yaml#/definitions/uint32-matrix"
+    $ref: /schemas/types.yaml#/definitions/uint32-matrix
     items:
       items:
         - description:
@@ -119,7 +119,7 @@ properties:
     description:
       Settings for the general purpose switch, set as one of the
       ARIZONA_GPSW_XXX defines.
-    $ref: "/schemas/types.yaml#/definitions/uint32"
+    $ref: /schemas/types.yaml#/definitions/uint32
     minimum: 0
     maximum: 3
 
index 4fb05eb84e2af4488d06fc46345e24fb3f958af0..164331eb627502dae2545ab636f1e7ede6e45a66 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Lattice Slave SPI sysCONFIG FPGA manager
 
 maintainers:
-  - Ivan Bornyakov <i.bornyakov@metrotek.ru>
+  - Vladimir Georgiev <v.georgiev@metrotek.ru>
 
 description: |
   Lattice sysCONFIG port, which is used for FPGA configuration, among others,
index 527532f039cecad9b39248b74fa9839804da6345..a157eecfb5fc333ced32389a02f79281b3d4161d 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Microchip Polarfire FPGA manager.
 
 maintainers:
-  - Ivan Bornyakov <i.bornyakov@metrotek.ru>
+  - Vladimir Georgiev <v.georgiev@metrotek.ru>
 
 description:
   Device Tree Bindings for Microchip Polarfire FPGA Manager using slave SPI to
index d521d516088be733a797ad151128bb4f2052f03f..16def2985ab4fe507e86d1fbc18cb603c479f9d3 100644 (file)
@@ -47,6 +47,9 @@ properties:
   avdd-supply:
     description: AVdd voltage supply
 
+  vref-supply:
+    description: VRef voltage supply
+
   adi,rejection-60-Hz-enable:
     description: |
       This bit enables a notch at 60 Hz when the first notch of the sinc
@@ -89,6 +92,7 @@ required:
   - interrupts
   - dvdd-supply
   - avdd-supply
+  - vref-supply
   - spi-cpol
   - spi-cpha
 
@@ -115,6 +119,7 @@ examples:
             interrupt-parent = <&gpio>;
             dvdd-supply = <&dvdd>;
             avdd-supply = <&avdd>;
+            vref-supply = <&vref>;
 
             adi,refin2-pins-enable;
             adi,rejection-60-Hz-enable;
index 7f79a06e76f59614a6cc2a8414bc48761dac5d9d..6168b44ea72cf6eedde042dc9c61c15f1cf54b19 100644 (file)
@@ -26,6 +26,7 @@ properties:
           - mediatek,mt2712-auxadc
           - mediatek,mt6765-auxadc
           - mediatek,mt7622-auxadc
+          - mediatek,mt7986-auxadc
           - mediatek,mt8173-auxadc
       - items:
           - enum:
index 63369ba388e4738cd4934884a37fbc444749458b..0a192ca192c5b3221843afacfe1b60c06425423e 100644 (file)
@@ -39,6 +39,12 @@ properties:
   power-domains:
     maxItems: 1
 
+  vref-supply:
+    description: |
+      External ADC reference voltage supply on VREFH pad. If VERID[MVI] is
+      set, there are additional, internal reference voltages selectable.
+      VREFH1 is always from VREFH pad.
+
   "#io-channel-cells":
     const: 1
 
@@ -72,6 +78,7 @@ examples:
             assigned-clocks = <&clk IMX_SC_R_ADC_0>;
             assigned-clock-rates = <24000000>;
             power-domains = <&pd IMX_SC_R_ADC_0>;
+            vref-supply = <&reg_1v8>;
             #io-channel-cells = <1>;
         };
     };
index bd6e0d6f6e0ce8a3114a4d75d363c691c1484a42..ad7d6fc49de58ea1ed6ed9f55ba11d97ae6c721b 100644 (file)
@@ -54,7 +54,7 @@ required:
   - '#io-channel-cells'
 
 patternProperties:
-  "^.*@[0-9a-f]+$":
+  "^channel@[0-9a-f]+$":
     type: object
     additionalProperties: false
     description: |
@@ -101,7 +101,7 @@ patternProperties:
         oneOf:
           - items:
               - const: 1
-              - enum: [ 1, 3, 4, 6, 20, 8, 10 ]
+              - enum: [ 1, 3, 4, 6, 20, 8, 10, 16 ]
           - items:
               - const: 10
               - const: 81
@@ -148,7 +148,7 @@ allOf:
 
     then:
       patternProperties:
-        "^.*@[0-9a-f]+$":
+        "^channel@[0-9a-f]+$":
           properties:
             qcom,decimation:
               enum: [ 512, 1024, 2048, 4096 ]
@@ -171,7 +171,7 @@ allOf:
 
     then:
       patternProperties:
-        "^.*@[0-9a-f]+$":
+        "^channel@[0-9a-f]+$":
           properties:
             qcom,decimation:
               enum: [ 256, 512, 1024 ]
@@ -194,7 +194,7 @@ allOf:
 
     then:
       patternProperties:
-        "^.*@[0-9a-f]+$":
+        "^channel@[0-9a-f]+$":
           properties:
             qcom,decimation:
               enum: [ 250, 420, 840 ]
@@ -217,7 +217,7 @@ allOf:
 
     then:
       patternProperties:
-        "^.*@[0-9a-f]+$":
+        "^channel@[0-9a-f]+$":
           properties:
             qcom,decimation:
               enum: [ 85, 340, 1360 ]
@@ -249,7 +249,7 @@ examples:
             #io-channel-cells = <1>;
 
             /* Channel node */
-            adc-chan@39 {
+            channel@39 {
                 reg = <0x39>;
                 qcom,decimation = <512>;
                 qcom,ratiometric;
@@ -258,19 +258,19 @@ examples:
                 qcom,pre-scaling = <1 3>;
             };
 
-            adc-chan@9 {
+            channel@9 {
                 reg = <0x9>;
             };
 
-            adc-chan@a {
+            channel@a {
                 reg = <0xa>;
             };
 
-            adc-chan@e {
+            channel@e {
                 reg = <0xe>;
             };
 
-            adc-chan@f {
+            channel@f {
                 reg = <0xf>;
             };
         };
@@ -292,16 +292,18 @@ examples:
             #io-channel-cells = <1>;
 
             /* Other properties are omitted */
-            xo-therm@44 {
+            channel@44 {
                 reg = <PMK8350_ADC7_AMUX_THM1_100K_PU>;
                 qcom,ratiometric;
                 qcom,hw-settle-time = <200>;
+                label = "xo_therm";
             };
 
-            conn-therm@47 {
+            channel@47 {
                 reg = <PM8350_ADC7_AMUX_THM4_100K_PU(1)>;
                 qcom,ratiometric;
                 qcom,hw-settle-time = <200>;
+                label = "conn_therm";
             };
         };
     };
index 1c7aee5ed3e0bfb208f5438503f7cccc5065d2a7..36dff3250ea76fe51b6ca32ed850617b1c58b2f0 100644 (file)
@@ -90,7 +90,7 @@ patternProperties:
             of the MAX chips to the GyroADC, while MISO line of each Maxim
             ADC connects to a shared input pin of the GyroADC.
         enum:
-          - adi,7476
+          - adi,ad7476
           - fujitsu,mb88101a
           - maxim,max1162
           - maxim,max11100
index da50b529c1576bfcf7f83cbc21048fa9498731da..aa24b841393c0223c818723def339ba2f10d2aab 100644 (file)
@@ -15,6 +15,7 @@ properties:
       - const: rockchip,saradc
       - const: rockchip,rk3066-tsadc
       - const: rockchip,rk3399-saradc
+      - const: rockchip,rk3588-saradc
       - items:
           - enum:
               - rockchip,px30-saradc
index df2589f214e18b50d585e520be88a7a83f82863c..dddf97b50549f0012697c60c484c0a2917f49c83 100644 (file)
@@ -13,7 +13,7 @@ description: |
   When an io-channel measures the midpoint of a voltage divider, the
   interesting voltage is often the voltage over the full resistance
   of the divider. This binding describes the voltage divider in such
-  a curcuit.
+  a circuit.
 
     Vin ----.
             |
index ec64d7877fe5b39ba6586a75fe9dcb890dd30d79..1db6952ddca5e118ffcced78e4b9cf0ba9e0179c 100644 (file)
@@ -30,6 +30,9 @@ properties:
           - invensense,mpu9150
           - invensense,mpu9250
           - invensense,mpu9255
+      - items:
+          - const: invensense,icm20600
+          - const: invensense,icm20602
       - items:
           - const: invensense,icm20608d
           - const: invensense,icm20608
index b39f5217d8ff3ced8375d8eebd0cc92871f122f8..ee8724ad33ab382cdafc6415cc0af6f239e1831d 100644 (file)
@@ -98,6 +98,7 @@ required:
   - reg
 
 allOf:
+  - $ref: /schemas/iio/iio.yaml#
   - $ref: /schemas/spi/spi-peripheral-props.yaml#
 
 unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/iio/light/rohm,bu27008.yaml b/Documentation/devicetree/bindings/iio/light/rohm,bu27008.yaml
new file mode 100644 (file)
index 0000000..4f66fd4
--- /dev/null
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/light/rohm,bu27008.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ROHM BU27008 color sensor
+
+maintainers:
+  - Matti Vaittinen <mazziesaccount@gmail.com>
+
+description:
+  The ROHM BU27008 is a sensor with 5 photodiodes (red, green, blue, clear
+  and IR) with four configurable channels. Red and green being always
+  available and two out of the rest three (blue, clear, IR) can be
+  selected to be simultaneously measured. Typical application is adjusting
+  LCD backlight of TVs, mobile phones and tablet PCs.
+
+properties:
+  compatible:
+    const: rohm,bu27008
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  vdd-supply: true
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      light-sensor@38 {
+        compatible = "rohm,bu27008";
+        reg = <0x38>;
+      };
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/iio/light/ti,opt4001.yaml b/Documentation/devicetree/bindings/iio/light/ti,opt4001.yaml
new file mode 100644 (file)
index 0000000..12b0c7e
--- /dev/null
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/light/ti,opt4001.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments OPT4001 Ambient Light Sensor
+
+maintainers:
+  - Stefan Windfeldt-Prytz <stefan.windfeldt-prytz@axis.com>
+
+description:
+  Ambient light sensor with an i2c interface.
+  Last part of compatible is for the packaging used.
+  Picostar is a 4 pinned SMT and sot-5x3 is a 8 pinned SOT.
+  https://www.ti.com/lit/gpn/opt4001
+
+properties:
+  compatible:
+    enum:
+      - ti,opt4001-picostar
+      - ti,opt4001-sot-5x3
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  vdd-supply:
+    description: Regulator that provides power to the sensor
+
+required:
+  - compatible
+  - reg
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: ti,opt4001-sot-5x3
+    then:
+      properties:
+        interrupts:
+          maxItems: 1
+    else:
+      properties:
+        interrupts: false
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        light-sensor@44 {
+            compatible = "ti,opt4001-sot-5x3";
+            reg = <0x44>;
+            vdd-supply = <&vdd_reg>;
+            interrupt-parent = <&gpio1>;
+            interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
+        };
+    };
+...
diff --git a/Documentation/devicetree/bindings/iio/potentiometer/renesas,x9250.yaml b/Documentation/devicetree/bindings/iio/potentiometer/renesas,x9250.yaml
new file mode 100644 (file)
index 0000000..ab5c09c
--- /dev/null
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/potentiometer/renesas,x9250.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas X9250 quad potentiometers
+
+maintainers:
+  - Herve Codina <herve.codina@bootlin.com>
+
+description:
+  The Renesas X9250 integrates four digitally controlled potentiometers.
+  On each potentiometer, the X9250T has a 100 kOhms total resistance and the
+  X9250U has a 50 kOhms total resistance.
+
+allOf:
+  - $ref: /schemas/spi/spi-peripheral-props.yaml
+
+properties:
+  compatible:
+    enum:
+      - renesas,x9250t
+      - renesas,x9250u
+
+  reg:
+    maxItems: 1
+
+  vcc-supply:
+    description:
+      Regulator for the VCC power supply.
+
+  avp-supply:
+    description:
+      Regulator for the analog V+ power supply.
+
+  avn-supply:
+    description:
+      Regulator for the analog V- power supply.
+
+  '#io-channel-cells':
+    const: 1
+
+  spi-max-frequency:
+    maximum: 2000000
+
+  wp-gpios:
+    maxItems: 1
+    description:
+      GPIO connected to the write-protect pin.
+
+required:
+  - compatible
+  - reg
+  - vcc-supply
+  - avp-supply
+  - avn-supply
+  - '#io-channel-cells'
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        potentiometer@0 {
+            compatible = "renesas,x9250t";
+            reg = <0>;
+            vcc-supply = <&vcc_regulator>;
+            avp-supply = <&avp_regulator>;
+            avn-supply = <&avp_regulator>;
+            wp-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
+            spi-max-frequency = <2000000>;
+            #io-channel-cells = <1>;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml b/Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml
new file mode 100644 (file)
index 0000000..c0a923f
--- /dev/null
@@ -0,0 +1,104 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/pressure/honeywell,mprls0025pa.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Honeywell mprls0025pa pressure sensor
+
+maintainers:
+  - Andreas Klinger <ak@it-klinger.de>
+
+description: |
+  Honeywell pressure sensor of model mprls0025pa.
+
+  This sensor has an I2C and SPI interface. Only the I2C interface is
+  implemented.
+
+  There are many models with different pressure ranges available. The vendor
+  calls them "mpr series". All of them have the identical programming model and
+  differ in the pressure range, unit and transfer function.
+
+  To support different models one need to specify the pressure range as well as
+  the transfer function. Pressure range needs to be converted from its unit to
+  pascal.
+
+  The transfer function defines the ranges of numerical values delivered by the
+  sensor. The minimal range value stands for the minimum pressure and the
+  maximum value also for the maximum pressure with linear relation inside the
+  range.
+
+  Specifications about the devices can be found at:
+    https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/
+      products/sensors/pressure-sensors/board-mount-pressure-sensors/
+      micropressure-mpr-series/documents/
+      sps-siot-mpr-series-datasheet-32332628-ciid-172626.pdf
+
+properties:
+  compatible:
+    const: honeywell,mprls0025pa
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  reset-gpios:
+    description:
+      Optional GPIO for resetting the device.
+      If not present the device is not resetted during the probe.
+    maxItems: 1
+
+  honeywell,pmin-pascal:
+    description:
+      Minimum pressure value the sensor can measure in pascal.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  honeywell,pmax-pascal:
+    description:
+      Maximum pressure value the sensor can measure in pascal.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  honeywell,transfer-function:
+    description: |
+      Transfer function which defines the range of valid values delivered by the
+      sensor.
+      1 - A, 10% to 90% of 2^24 (1677722 .. 15099494)
+      2 - B, 2.5% to 22.5% of 2^24 (419430 .. 3774874)
+      3 - C, 20% to 80% of 2^24 (3355443 .. 13421773)
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  vdd-supply:
+    description: provide VDD power to the sensor.
+
+required:
+  - compatible
+  - reg
+  - honeywell,pmin-pascal
+  - honeywell,pmax-pascal
+  - honeywell,transfer-function
+  - vdd-supply
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        pressure@18 {
+            compatible = "honeywell,mprls0025pa";
+            reg = <0x18>;
+            reset-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
+            interrupt-parent = <&gpio3>;
+            interrupts = <21 IRQ_TYPE_EDGE_FALLING>;
+            honeywell,pmin-pascal = <0>;
+            honeywell,pmax-pascal = <172369>;
+            honeywell,transfer-function = <1>;
+            vdd-supply = <&vcc_3v3>;
+        };
+    };
index 1ff3afca91494e20c195b5325096fae93bf003cb..e450821a741da0c3412cc1d83ce329ea5852a272 100644 (file)
@@ -84,6 +84,7 @@ properties:
           - st,lps35hw
       - description: IMUs
         enum:
+          - st,lsm303d-imu
           - st,lsm9ds0-imu
       - description: Deprecated bindings
         enum:
index d6965a0c1cf30ca0c25867e2d3a4a04003b48712..654d31f65d3602e6e91d9c3ec2005ab08adbe0fa 100644 (file)
@@ -4,7 +4,7 @@
 $id: http://devicetree.org/schemas/iio/temperature/melexis,mlx90614.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Melexis MLX90614 contactless IR temperature sensor
+title: Melexis MLX90614/MLX90615 contactless IR temperature sensor
 
 maintainers:
   - Peter Meerwald <pmeerw@pmeerw.net>
@@ -15,7 +15,9 @@ description: |
 
 properties:
   compatible:
-    const: melexis,mlx90614
+    enum:
+      - melexis,mlx90614
+      - melexis,mlx90615
 
   reg:
     maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml b/Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml
new file mode 100644 (file)
index 0000000..d43002b
--- /dev/null
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/temperature/ti,tmp006.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI TMP006 IR thermopile sensor
+
+maintainers:
+  - Peter Meerwald <pmeerw@pmeerw.net>
+
+description: |
+  TI TMP006 - Infrared Thermopile Sensor in Chip-Scale Package.
+  https://cdn.sparkfun.com/datasheets/Sensors/Temp/tmp006.pdf
+
+properties:
+  compatible:
+    const: ti,tmp006
+
+  reg:
+    maxItems: 1
+
+  vdd-supply:
+    description: provide VDD power to the sensor.
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        temperature-sensor@40 {
+            compatible = "ti,tmp006";
+            reg = <0x40>;
+            vdd-supply = <&ldo4_reg>;
+        };
+    };
index 92117261e1e1d0e985e47fe6fca5814a2e4293db..39e64c7f6360cacfe615f0b65a2ec8e85482c17d 100644 (file)
@@ -166,6 +166,12 @@ properties:
   resets:
     maxItems: 1
 
+  mediatek,broken-save-restore-fw:
+    type: boolean
+    description:
+      Asserts that the firmware on this device has issues saving and restoring
+      GICR registers when the GIC redistributors are powered off.
+
 dependencies:
   mbi-ranges: [ msi-controller ]
   msi-controller: [ mbi-ranges ]
index 8b389314c352656f0209c06c40f8724bd95affd8..e2ffe0a9c26b31177158d38446ff33aeb59973dc 100644 (file)
@@ -49,6 +49,7 @@ properties:
 
         properties:
           data-lanes:
+            minItems: 1
             maxItems: 2
 
         required:
index 769fa5c27b76ee427a46daeef2055a516f29268f..de1d4298893be8b7f3c2090f338484d1bb9d6a5d 100644 (file)
@@ -21,11 +21,22 @@ properties:
 
   st,can-primary:
     description:
-      Primary and secondary mode of the bxCAN peripheral is only relevant
-      if the chip has two CAN peripherals. In that case they share some
-      of the required logic.
+      Primary mode of the bxCAN peripheral is only relevant if the chip has
+      two CAN peripherals in dual CAN configuration. In that case they share
+      some of the required logic.
+      Not to be used if the peripheral is in single CAN configuration.
       To avoid misunderstandings, it should be noted that ST documentation
-      uses the terms master/slave instead of primary/secondary.
+      uses the terms master instead of primary.
+    type: boolean
+
+  st,can-secondary:
+    description:
+      Secondary mode of the bxCAN peripheral is only relevant if the chip
+      has two CAN peripherals in dual CAN configuration. In that case they
+      share some of the required logic.
+      Not to be used if the peripheral is in single CAN configuration.
+      To avoid misunderstandings, it should be noted that ST documentation
+      uses the terms slave instead of secondary.
     type: boolean
 
   reg:
index 36def7128fca8c2e65c3c323b1a09f663376d6f6..13412af7f046640926f7b3d93716beec102af14a 100644 (file)
@@ -36,14 +36,29 @@ properties:
   et0macaddr:
     type: object
     description: First Ethernet interface's MAC address
+    properties:
+      "#nvmem-cell-cells":
+        description: The first argument is a MAC address offset.
+        const: 1
+    additionalProperties: false
 
   et1macaddr:
     type: object
     description: Second Ethernet interface's MAC address
+    properties:
+      "#nvmem-cell-cells":
+        description: The first argument is a MAC address offset.
+        const: 1
+    additionalProperties: false
 
   et2macaddr:
     type: object
     description: Third Ethernet interface's MAC address
+    properties:
+      "#nvmem-cell-cells":
+        description: The first argument is a MAC address offset.
+        const: 1
+    additionalProperties: false
 
 unevaluatedProperties: false
 
index 9876243ff1e85fa403579a61b8838c9f76a7d7c2..99e60d713dace749407ddd4fbb9a85e4c759ee1f 100644 (file)
@@ -4,7 +4,7 @@
 $id: http://devicetree.org/schemas/nvmem/imx-ocotp.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Freescale i.MX6 On-Chip OTP Controller (OCOTP)
+title: Freescale i.MX On-Chip OTP Controller (OCOTP)
 
 maintainers:
   - Anson Huang <Anson.Huang@nxp.com>
@@ -12,7 +12,7 @@ maintainers:
 description: |
   This binding represents the on-chip eFuse OTP controller found on
   i.MX6Q/D, i.MX6DL/S, i.MX6SL, i.MX6SX, i.MX6UL, i.MX6ULL/ULZ, i.MX6SLL,
-  i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM, i.MX8MN and i.MX8MP SoCs.
+  i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM, i.MX8MN i.MX8MP and i.MX93 SoCs.
 
 allOf:
   - $ref: nvmem.yaml#
@@ -32,6 +32,7 @@ properties:
               - fsl,imx7ulp-ocotp
               - fsl,imx8mq-ocotp
               - fsl,imx8mm-ocotp
+              - fsl,imx93-ocotp
           - const: syscon
       - items:
           - enum:
@@ -46,12 +47,6 @@ properties:
   reg:
     maxItems: 1
 
-  "#address-cells":
-    const: 1
-
-  "#size-cells":
-    const: 1
-
   clocks:
     maxItems: 1
 
@@ -61,21 +56,6 @@ required:
   - compatible
   - reg
 
-patternProperties:
-  "^.*@[0-9a-f]+$":
-    type: object
-
-    properties:
-      reg:
-        maxItems: 1
-        description:
-          Offset and size in bytes within the storage device.
-
-    required:
-      - reg
-
-    additionalProperties: false
-
 unevaluatedProperties: false
 
 examples:
diff --git a/Documentation/devicetree/bindings/nvmem/layouts/fixed-cell.yaml b/Documentation/devicetree/bindings/nvmem/layouts/fixed-cell.yaml
new file mode 100644 (file)
index 0000000..e698098
--- /dev/null
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/layouts/fixed-cell.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Fixed offset & size NVMEM cell
+
+maintainers:
+  - RafaÅ‚ MiÅ‚ecki <rafal@milecki.pl>
+  - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+properties:
+  reg:
+    maxItems: 1
+
+  bits:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    items:
+      - minimum: 0
+        maximum: 7
+        description:
+          Offset in bit within the address range specified by reg.
+      - minimum: 1
+        description:
+          Size in bit within the address range specified by reg.
+
+required:
+  - reg
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/nvmem/layouts/fixed-layout.yaml b/Documentation/devicetree/bindings/nvmem/layouts/fixed-layout.yaml
new file mode 100644 (file)
index 0000000..c271537
--- /dev/null
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/layouts/fixed-layout.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVMEM layout for fixed NVMEM cells
+
+description:
+  Many NVMEM devices have hardcoded cells layout (offset and size of defined
+  NVMEM content doesn't change).
+
+  This binding allows defining such NVMEM layout with its cells. It can be used
+  on top of any NVMEM device.
+
+maintainers:
+  - RafaÅ‚ MiÅ‚ecki <rafal@milecki.pl>
+
+properties:
+  compatible:
+    const: fixed-layout
+
+  "#address-cells":
+    const: 1
+
+  "#size-cells":
+    const: 1
+
+patternProperties:
+  "@[a-f0-9]+$":
+    type: object
+    $ref: fixed-cell.yaml
+    unevaluatedProperties: false
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    nvmem-layout {
+        compatible = "fixed-layout";
+        #address-cells = <1>;
+        #size-cells = <1>;
+
+        calibration@4000 {
+            reg = <0x4000 0x100>;
+        };
+    };
index 8512ee538c4c1602f9ff1e094b97ea9b08c817b8..3b40f7880774694aec189213a932f8606ab81f0d 100644 (file)
@@ -18,16 +18,13 @@ description: |
   perform their parsing. The nvmem-layout container is here to describe these.
 
 oneOf:
+  - $ref: fixed-layout.yaml
   - $ref: kontron,sl28-vpd.yaml
   - $ref: onie,tlv-layout.yaml
 
 properties:
   compatible: true
 
-  '#address-cells': false
-
-  '#size-cells': false
-
 required:
   - compatible
 
index d16d42fb98b6a64cb76253355999e90d0f082854..7ec2988b597e8d9b2a73114476b8f20c721c014c 100644 (file)
@@ -27,6 +27,7 @@ properties:
           - enum:
               - mediatek,mt7622-efuse
               - mediatek,mt7623-efuse
+              - mediatek,mt7986-efuse
               - mediatek,mt8173-efuse
               - mediatek,mt8183-efuse
               - mediatek,mt8186-efuse
index 8938eec22b52d2436354d3857c2b91dc89943c3c..a9b822aeaa7edb2737c0ca68358cb8cf3daaa578 100644 (file)
@@ -18,12 +18,6 @@ properties:
       - fsl,imx23-ocotp
       - fsl,imx28-ocotp
 
-  "#address-cells":
-    const: 1
-
-  "#size-cells":
-    const: 1
-
   reg:
     maxItems: 1
 
@@ -35,7 +29,7 @@ required:
   - reg
   - clocks
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
index 75bb93dda9df1ddf81a2e1dd45cec57440e3fd53..9802441006906638acffa30f527606859aba82bd 100644 (file)
@@ -49,23 +49,8 @@ properties:
 patternProperties:
   "@[0-9a-f]+(,[0-7])?$":
     type: object
-
-    properties:
-      reg:
-        maxItems: 1
-        description:
-          Offset and size in bytes within the storage device.
-
-      bits:
-        $ref: /schemas/types.yaml#/definitions/uint32-array
-        items:
-          - minimum: 0
-            maximum: 7
-            description:
-              Offset in bit within the address range specified by reg.
-          - minimum: 1
-            description:
-              Size in bit within the address range specified by reg.
+    $ref: layouts/fixed-cell.yaml
+    deprecated: true
 
 additionalProperties: true
 
@@ -83,24 +68,30 @@ examples:
 
           /* ... */
 
-          /* Data cells */
-          tsens_calibration: calib@404 {
-              reg = <0x404 0x10>;
-          };
-
-          tsens_calibration_bckp: calib_bckp@504 {
-              reg = <0x504 0x11>;
-              bits = <6 128>;
-          };
-
-          pvs_version: pvs-version@6 {
-              reg = <0x6 0x2>;
-              bits = <7 2>;
-          };
-
-          speed_bin: speed-bin@c{
-              reg = <0xc 0x1>;
-              bits = <2 3>;
+          nvmem-layout {
+              compatible = "fixed-layout";
+              #address-cells = <1>;
+              #size-cells = <1>;
+
+              /* Data cells */
+              tsens_calibration: calib@404 {
+                  reg = <0x404 0x10>;
+              };
+
+              tsens_calibration_bckp: calib_bckp@504 {
+                  reg = <0x504 0x11>;
+                  bits = <6 128>;
+              };
+
+              pvs_version: pvs-version@6 {
+                  reg = <0x6 0x2>;
+                  bits = <7 2>;
+              };
+
+              speed_bin: speed-bin@c{
+                  reg = <0xc 0x1>;
+                  bits = <2 3>;
+              };
           };
       };
 
index 8d8503dd934b821cec4fa50b8a0e67d68b6ac7f7..c898c67c243a791a362651235cf5852e5819a44a 100644 (file)
@@ -64,12 +64,6 @@ properties:
   power-domains:
     maxItems: 1
 
-  # Needed if any child nodes are present.
-  "#address-cells":
-    const: 1
-  "#size-cells":
-    const: 1
-
 required:
   - compatible
   - reg
index dce0c7d84ce76b9c21d76fd1ff0149fbea842025..cd980def97b8c36b15a1c45ebfe4c49b99eaea02 100644 (file)
@@ -25,12 +25,6 @@ properties:
   reg:
     maxItems: 1
 
-  "#address-cells":
-    const: 1
-
-  "#size-cells":
-    const: 1
-
   ranges: true
 
 required:
index 38a39c9b8c1cecdba5eb807e6d6a330a6203c29c..1ec0d09bcafa857c05ae722834c9e13bf63ee851 100644 (file)
@@ -17,6 +17,7 @@ properties:
     items:
       - enum:
           - raspberrypi,bootloader-config
+          - raspberrypi,bootloader-public-key
       - const: nvmem-rmem
 
   reg:
diff --git a/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml b/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml
new file mode 100644 (file)
index 0000000..9c6eff7
--- /dev/null
@@ -0,0 +1,122 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/rockchip,otp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip internal OTP (One Time Programmable) memory
+
+maintainers:
+  - Heiko Stuebner <heiko@sntech.de>
+
+properties:
+  compatible:
+    enum:
+      - rockchip,px30-otp
+      - rockchip,rk3308-otp
+      - rockchip,rk3588-otp
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    minItems: 3
+    maxItems: 4
+
+  clock-names:
+    minItems: 3
+    items:
+      - const: otp
+      - const: apb_pclk
+      - const: phy
+      - const: arb
+
+  resets:
+    minItems: 1
+    maxItems: 3
+
+  reset-names:
+    minItems: 1
+    maxItems: 3
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - resets
+  - reset-names
+
+allOf:
+  - $ref: nvmem.yaml#
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - rockchip,px30-otp
+              - rockchip,rk3308-otp
+    then:
+      properties:
+        clocks:
+          maxItems: 3
+        resets:
+          maxItems: 1
+        reset-names:
+          items:
+            - const: phy
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - rockchip,rk3588-otp
+    then:
+      properties:
+        clocks:
+          minItems: 4
+        resets:
+          minItems: 3
+        reset-names:
+          items:
+            - const: otp
+            - const: apb
+            - const: arb
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/px30-cru.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        otp: efuse@ff290000 {
+            compatible = "rockchip,px30-otp";
+            reg = <0x0 0xff290000 0x0 0x4000>;
+            clocks = <&cru SCLK_OTP_USR>, <&cru PCLK_OTP_NS>,
+                     <&cru PCLK_OTP_PHY>;
+            clock-names = "otp", "apb_pclk", "phy";
+            resets = <&cru SRST_OTP_PHY>;
+            reset-names = "phy";
+            #address-cells = <1>;
+            #size-cells = <1>;
+
+            cpu_id: id@7 {
+                reg = <0x07 0x10>;
+            };
+
+            cpu_leakage: cpu-leakage@17 {
+                reg = <0x17 0x1>;
+            };
+
+            performance: performance@1e {
+                reg = <0x1e 0x1>;
+                bits = <4 3>;
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-otp.txt b/Documentation/devicetree/bindings/nvmem/rockchip-otp.txt
deleted file mode 100644 (file)
index 40f649f..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-Rockchip internal OTP (One Time Programmable) memory device tree bindings
-
-Required properties:
-- compatible: Should be one of the following.
-  - "rockchip,px30-otp" - for PX30 SoCs.
-  - "rockchip,rk3308-otp" - for RK3308 SoCs.
-- reg: Should contain the registers location and size
-- clocks: Must contain an entry for each entry in clock-names.
-- clock-names: Should be "otp", "apb_pclk" and "phy".
-- resets: Must contain an entry for each entry in reset-names.
-  See ../../reset/reset.txt for details.
-- reset-names: Should be "phy".
-
-See nvmem.txt for more information.
-
-Example:
-       otp: otp@ff290000 {
-               compatible = "rockchip,px30-otp";
-               reg = <0x0 0xff290000 0x0 0x4000>;
-               #address-cells = <1>;
-               #size-cells = <1>;
-               clocks = <&cru SCLK_OTP_USR>, <&cru PCLK_OTP_NS>,
-                        <&cru PCLK_OTP_PHY>;
-               clock-names = "otp", "apb_pclk", "phy";
-       };
index b8bca0599c452c813a3786d4aba953497c0a0075..efccc5aacbe0cd605c9efb8eac48588a95ba9670 100644 (file)
@@ -14,9 +14,6 @@ allOf:
   - $ref: nvmem.yaml#
 
 properties:
-  "#address-cells": true
-  "#size-cells": true
-
   compatible:
     const: socionext,uniphier-efuse
 
index 8877c2283e9ea3730675373b3e08a613d2661417..da3f1de7d281740b9e2a02f2e1e68645e1208114 100644 (file)
@@ -28,12 +28,6 @@ properties:
   clocks:
     maxItems: 1
 
-  "#address-cells":
-    const: 1
-
-  "#size-cells":
-    const: 1
-
   thermal-calibration:
     type: object
     description: thermal calibration values
index 9bff8ecb653c073089b697f436176d2e2159de0b..d91b639ae7ae75d15eb131f8ebaa409cc5658afe 100644 (file)
@@ -17,20 +17,11 @@ description:
 properties:
   clocks:
     minItems: 3
-    items:
-      - description: PCIe bridge clock.
-      - description: PCIe bus clock.
-      - description: PCIe PHY clock.
-      - description: Additional required clock entry for imx6sx-pcie,
-           imx6sx-pcie-ep, imx8mq-pcie, imx8mq-pcie-ep.
+    maxItems: 4
 
   clock-names:
     minItems: 3
-    items:
-      - const: pcie
-      - const: pcie_bus
-      - enum: [ pcie_phy, pcie_aux ]
-      - enum: [ pcie_inbound_axi, pcie_aux ]
+    maxItems: 4
 
   num-lanes:
     const: 1
index f4a328ec1daa6aac4e1b50b79456cfa1f919e81e..ee155ed5f18118164ae05d56cd12a2b934aad187 100644 (file)
@@ -31,6 +31,19 @@ properties:
       - const: dbi
       - const: addr_space
 
+  clocks:
+    minItems: 3
+    items:
+      - description: PCIe bridge clock.
+      - description: PCIe bus clock.
+      - description: PCIe PHY clock.
+      - description: Additional required clock entry for imx6sx-pcie,
+           imx6sx-pcie-ep, imx8mq-pcie, imx8mq-pcie-ep.
+
+  clock-names:
+    minItems: 3
+    maxItems: 4
+
   interrupts:
     items:
       - description: builtin eDMA interrupter.
@@ -49,6 +62,31 @@ required:
 allOf:
   - $ref: /schemas/pci/snps,dw-pcie-ep.yaml#
   - $ref: /schemas/pci/fsl,imx6q-pcie-common.yaml#
+  - if:
+      properties:
+        compatible:
+          enum:
+            - fsl,imx8mq-pcie-ep
+    then:
+      properties:
+        clocks:
+          minItems: 4
+        clock-names:
+          items:
+            - const: pcie
+            - const: pcie_bus
+            - const: pcie_phy
+            - const: pcie_aux
+    else:
+      properties:
+        clocks:
+          maxItems: 3
+        clock-names:
+          items:
+            - const: pcie
+            - const: pcie_bus
+            - const: pcie_aux
+
 
 unevaluatedProperties: false
 
index 2443641754d3fac2507a61af2406316c67636cf1..81bbb8728f0f97a6db584a8d970c3740449f0655 100644 (file)
@@ -40,6 +40,19 @@ properties:
       - const: dbi
       - const: config
 
+  clocks:
+    minItems: 3
+    items:
+      - description: PCIe bridge clock.
+      - description: PCIe bus clock.
+      - description: PCIe PHY clock.
+      - description: Additional required clock entry for imx6sx-pcie,
+           imx6sx-pcie-ep, imx8mq-pcie, imx8mq-pcie-ep.
+
+  clock-names:
+    minItems: 3
+    maxItems: 4
+
   interrupts:
     items:
       - description: builtin MSI controller.
@@ -77,6 +90,70 @@ required:
 allOf:
   - $ref: /schemas/pci/snps,dw-pcie.yaml#
   - $ref: /schemas/pci/fsl,imx6q-pcie-common.yaml#
+  - if:
+      properties:
+        compatible:
+          enum:
+            - fsl,imx6sx-pcie
+    then:
+      properties:
+        clocks:
+          minItems: 4
+        clock-names:
+          items:
+            - const: pcie
+            - const: pcie_bus
+            - const: pcie_phy
+            - const: pcie_inbound_axi
+
+  - if:
+      properties:
+        compatible:
+          enum:
+            - fsl,imx8mq-pcie
+    then:
+      properties:
+        clocks:
+          minItems: 4
+        clock-names:
+          items:
+            - const: pcie
+            - const: pcie_bus
+            - const: pcie_phy
+            - const: pcie_aux
+
+  - if:
+      properties:
+        compatible:
+          enum:
+            - fsl,imx6q-pcie
+            - fsl,imx6qp-pcie
+            - fsl,imx7d-pcie
+    then:
+      properties:
+        clocks:
+          maxItems: 3
+        clock-names:
+          items:
+            - const: pcie
+            - const: pcie_bus
+            - const: pcie_phy
+
+  - if:
+      properties:
+        compatible:
+          enum:
+            - fsl,imx8mm-pcie
+            - fsl,imx8mp-pcie
+    then:
+      properties:
+        clocks:
+          maxItems: 3
+        clock-names:
+          items:
+            - const: pcie
+            - const: pcie_bus
+            - const: pcie_aux
 
 unevaluatedProperties: false
 
index eb3488d8f9ee61854288c4b43a221fe03e5d7f6e..6a7be42da523c60e8b5d9c5ae8e3c6f2b1bb22db 100644 (file)
@@ -70,6 +70,7 @@ properties:
   dsr-gpios: true
   rng-gpios: true
   dcd-gpios: true
+  rs485-rts-active-high: true
   rts-gpio: true
   power-domains: true
   clock-frequency: true
index a5bb561bfcfbafdcd8f0d0c17be3d3ec1ba9c7bd..31a3024ea7898eba853ef98b300b97c1335a1a24 100644 (file)
@@ -55,7 +55,9 @@ properties:
     description: TDM TX current sense time slot.
 
   '#sound-dai-cells':
-    const: 1
+    # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward
+    # compatibility but is deprecated.
+    enum: [0, 1]
 
 required:
   - compatible
@@ -72,7 +74,7 @@ examples:
      codec: codec@4c {
        compatible = "ti,tas2562";
        reg = <0x4c>;
-       #sound-dai-cells = <1>;
+       #sound-dai-cells = <0>;
        interrupt-parent = <&gpio1>;
        interrupts = <14>;
        shutdown-gpios = <&gpio1 15 0>;
index 26088adb9dc24073828412171f37b634d1fc5e44..8908bf1122e965fe8eaab5c2244ac8d5650407eb 100644 (file)
@@ -57,7 +57,9 @@ properties:
       - 1 # Falling edge
 
   '#sound-dai-cells':
-    const: 1
+    # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward
+    # compatibility but is deprecated.
+    enum: [0, 1]
 
 required:
   - compatible
@@ -74,7 +76,7 @@ examples:
      codec: codec@41 {
        compatible = "ti,tas2770";
        reg = <0x41>;
-       #sound-dai-cells = <1>;
+       #sound-dai-cells = <0>;
        interrupt-parent = <&gpio1>;
        interrupts = <14>;
        reset-gpio = <&gpio1 15 0>;
index 8cba01316855d4ac1bf9b87ed3a975d2c13ac87a..a876545ec87d8c6bc766ee7513fb231d52fc848d 100644 (file)
@@ -50,7 +50,9 @@ properties:
     description: TDM TX voltage sense time slot.
 
   '#sound-dai-cells':
-    const: 1
+    # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward
+    # compatibility but is deprecated.
+    enum: [0, 1]
 
 required:
   - compatible
@@ -67,7 +69,7 @@ examples:
      codec: codec@38 {
        compatible = "ti,tas2764";
        reg = <0x38>;
-       #sound-dai-cells = <1>;
+       #sound-dai-cells = <0>;
        interrupt-parent = <&gpio1>;
        interrupts = <14>;
        reset-gpios = <&gpio1 15 0>;
index f59125bc79d1bfb96cc91cee6f08d1b6785ba891..0b4e21bde5bc1c27fd39835517beb92004c743d0 100644 (file)
@@ -8,7 +8,7 @@ Required properties:
        "ti,tlv320aic32x6" TLV320AIC3206, TLV320AIC3256
        "ti,tas2505" TAS2505, TAS2521
  - reg: I2C slave address
- - supply-*: Required supply regulators are:
+ - *-supply: Required supply regulators are:
     "iov" - digital IO power supply
     "ldoin" - LDO power supply
     "dv" - Digital core power supply
index 993430be355b47318105cceb6a274ce05f250d45..0922d1f71ba8a8ebbbc43feee246b29116929316 100644 (file)
@@ -94,6 +94,7 @@ patternProperties:
             - samsung,exynos4210-sysram
             - samsung,exynos4210-sysram-ns
             - socionext,milbeaut-smp-sram
+            - stericsson,u8500-esram
 
       reg:
         description:
index cae46c4982adf69e3369fa450924df14e03fa804..69a93a0722f07f5c45ec6d5f817eed79231463ab 100644 (file)
@@ -64,7 +64,7 @@ properties:
     description:
       size of memory intended as internal memory for endpoints
       buffers expressed in KB
-    $ref: /schemas/types.yaml#/definitions/uint32
+    $ref: /schemas/types.yaml#/definitions/uint16
 
   cdns,phyrst-a-enable:
     description: Enable resetting of PHY if Rx fail is detected
index 50edc4da780e9caf68f7821bcff9c06ffa80bba2..4f7625955cccccff6964c98cfed9a1dc1f225326 100644 (file)
@@ -287,7 +287,7 @@ properties:
     description:
       High-Speed PHY interface selection between UTMI+ and ULPI when the
       DWC_USB3_HSPHY_INTERFACE has value 3.
-    $ref: /schemas/types.yaml#/definitions/uint8
+    $ref: /schemas/types.yaml#/definitions/string
     enum: [utmi, ulpi]
 
   snps,quirk-frame-length-adjustment:
index 3abe84225613903f373416724b7a0f25e3bcc2f2..1f087e502ca6da92dc30c479057f5a257070e6b5 100644 (file)
@@ -29,7 +29,7 @@ recur_count
 cpoint_name
        Where in the kernel to trigger the action. It can be
        one of INT_HARDWARE_ENTRY, INT_HW_IRQ_EN, INT_TASKLET_ENTRY,
-       FS_DEVRW, MEM_SWAPOUT, TIMERADD, SCSI_QUEUE_RQ, or DIRECT.
+       FS_SUBMIT_BH, MEM_SWAPOUT, TIMERADD, SCSI_QUEUE_RQ, or DIRECT.
 
 cpoint_type
        Indicates the action to be taken on hitting the crash point.
index fbb2b5ada95b38838d8ae6ab97e476c28d3be341..eb252fc972aa95e8d731981a8ea3340b0da0160a 100644 (file)
@@ -72,7 +72,6 @@ Documentation for filesystem implementations.
    befs
    bfs
    btrfs
-   cifs/index
    ceph
    coda
    configfs
@@ -111,6 +110,7 @@ Documentation for filesystem implementations.
    ramfs-rootfs-initramfs
    relay
    romfs
+   smb/index
    spufs/index
    squashfs
    sysfs
index 164960631925d05a4684fc5920e63cf204f57663..447f767c646276551570baa9de4dd19ccda95c61 100644 (file)
@@ -6,8 +6,7 @@ Ramfs, rootfs and initramfs
 
 October 17, 2005
 
-Rob Landley <rob@landley.net>
-=============================
+:Author: Rob Landley <rob@landley.net>
 
 What is ramfs?
 --------------
index d83395354250d9ca02dc19a38cdf9762733ded04..1cf56489ed484dcf77581e6be1faa490e600a3ab 100644 (file)
@@ -147,6 +147,7 @@ replicas continue to be exactly same.
 
 
 3) Setting mount states
+-----------------------
 
        The mount command (util-linux package) can be used to set mount
        states::
@@ -612,6 +613,7 @@ replicas continue to be exactly same.
 
 
 6) Quiz
+-------
 
        A. What is the result of the following command sequence?
 
@@ -673,6 +675,7 @@ replicas continue to be exactly same.
                /mnt/1/test be?
 
 7) FAQ
+------
 
        Q1. Why is bind mount needed? How is it different from symbolic links?
                symbolic links can get stale if the destination mount gets
@@ -841,6 +844,7 @@ replicas continue to be exactly same.
                             tmp  usr tmp usr tmp usr
 
 8) Implementation
+-----------------
 
 8A) Datastructure
 
similarity index 97%
rename from Documentation/filesystems/cifs/cifsroot.rst
rename to Documentation/filesystems/smb/cifsroot.rst
index 4930bb443134aecdc4445b8058d8272bb11aa696..bf2d9db3acb924bb8e86c3ddc0bfdffbc098ed6e 100644 (file)
@@ -59,7 +59,7 @@ the root file system via SMB protocol.
 Enables the kernel to mount the root file system via SMB that are
 located in the <server-ip> and <share> specified in this option.
 
-The default mount options are set in fs/cifs/cifsroot.c.
+The default mount options are set in fs/smb/client/cifsroot.c.
 
 server-ip
        IPv4 address of the server.
index f80f95667ca217a0c87f68ad0a06cfcb1c2db87d..43c968871d995ad4e2ece499a15837a352e8e0ee 100644 (file)
@@ -1,7 +1,7 @@
 .. SPDX-License-Identifier: GPL-2.0
 
 ====
-fpga
+FPGA
 ====
 
 .. toctree::
index 7003bd5aeff4cf711f9fde4b9fdde5c120a79559..6a9ea96c8bcb7013ac97715550d6845bfb188593 100644 (file)
@@ -1,7 +1,7 @@
 .. SPDX-License-Identifier: GPL-2.0
 
 =======
-locking
+Locking
 =======
 
 .. toctree::
index 756be15a49a416d30ec4632a17c0af8e0077dbf0..ecc40fbbcfb8eb63cde4c477d63eeccc6a8c847a 100644 (file)
@@ -28,5 +28,6 @@ fit into other categories.
    oxsemi-tornado
    pci-endpoint-test
    spear-pcie-gadget
+   tps6594-pfsm
    uacce
    xilinx_sdfec
diff --git a/Documentation/misc-devices/tps6594-pfsm.rst b/Documentation/misc-devices/tps6594-pfsm.rst
new file mode 100644 (file)
index 0000000..4ada37c
--- /dev/null
@@ -0,0 +1,87 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=====================================
+Texas Instruments TPS6594 PFSM driver
+=====================================
+
+Author: Julien Panis (jpanis@baylibre.com)
+
+Overview
+========
+
+Strictly speaking, PFSM (Pre-configurable Finite State Machine) is not
+hardware. It is a piece of code.
+
+The TPS6594 PMIC (Power Management IC) integrates a state machine which
+manages operational modes. Depending on the current operational mode,
+some voltage domains remain energized while others can be off.
+
+The PFSM driver can be used to trigger transitions between configured
+states. It also provides R/W access to the device registers.
+
+Supported chips
+---------------
+
+- tps6594-q1
+- tps6593-q1
+- lp8764-q1
+
+Driver location
+===============
+
+drivers/misc/tps6594-pfsm.c
+
+Driver type definitions
+=======================
+
+include/uapi/linux/tps6594_pfsm.h
+
+Driver IOCTLs
+=============
+
+:c:macro::`PMIC_GOTO_STANDBY`
+All device resources are powered down. The processor is off, and
+no voltage domains are energized.
+
+:c:macro::`PMIC_GOTO_LP_STANDBY`
+The digital and analog functions of the PMIC, which are not
+required to be always-on, are turned off (low-power).
+
+:c:macro::`PMIC_UPDATE_PGM`
+Triggers a firmware update.
+
+:c:macro::`PMIC_SET_ACTIVE_STATE`
+One of the operational modes.
+The PMICs are fully functional and supply power to all PDN loads.
+All voltage domains are energized in both MCU and Main processor
+sections.
+
+:c:macro::`PMIC_SET_MCU_ONLY_STATE`
+One of the operational modes.
+Only the power resources assigned to the MCU Safety Island are on.
+
+:c:macro::`PMIC_SET_RETENTION_STATE`
+One of the operational modes.
+Depending on the triggers set, some DDR/GPIO voltage domains can
+remain energized, while all other domains are off to minimize
+total system power.
+
+Driver usage
+============
+
+See available PFSMs::
+
+    # ls /dev/pfsm*
+
+Dump the registers of pages 0 and 1::
+
+    # hexdump -C /dev/pfsm-0-0x48
+
+See PFSM events::
+
+    # cat /proc/interrupts
+
+Userspace code example
+----------------------
+
+samples/pfsm/pfsm-wakeup.c
index cfd8f4117cf3e9a1ef4800653b19d3711fe069d7..c12838ce6b8de2468c81b2d5d18b2fa74317e271 100644 (file)
@@ -52,3 +52,22 @@ Build kernel with:
 
 Optionally, build kernel with PAGE_TABLE_CHECK_ENFORCED in order to have page
 table support without extra kernel parameter.
+
+Implementation notes
+====================
+
+We specifically decided not to use VMA information in order to avoid relying on
+MM states (except for limited "struct page" info). The page table check is a
+separate from Linux-MM state machine that verifies that the user accessible
+pages are not falsely shared.
+
+PAGE_TABLE_CHECK depends on EXCLUSIVE_SYSTEM_RAM. The reason is that without
+EXCLUSIVE_SYSTEM_RAM, users are allowed to map arbitrary physical memory
+regions into the userspace via /dev/mem. At the same time, pages may change
+their properties (e.g., from anonymous pages to named pages) while they are
+still being mapped in the userspace, leading to "corruption" detected by the
+page table check.
+
+Even with EXCLUSIVE_SYSTEM_RAM, I/O pages may be still allowed to be mapped via
+/dev/mem. However, these pages are always considered as named pages, so they
+won't break the logic used in the page table check.
index 129f413ea3496fbd0bde88ce9bf786931d2a23ba..3abc576ff7976b2806819d53f12d1e8c16be6e1f 100644 (file)
@@ -60,22 +60,6 @@ attribute-sets:
         type: nest
         nested-attributes: bitset-bits
 
-  -
-    name: u64-array
-    attributes:
-      -
-        name: u64
-        type: nest
-        multi-attr: true
-        nested-attributes: u64
-  -
-    name: s32-array
-    attributes:
-      -
-        name: s32
-        type: nest
-        multi-attr: true
-        nested-attributes: s32
   -
     name: string
     attributes:
@@ -705,16 +689,16 @@ attribute-sets:
         type: u8
       -
         name: corrected
-        type: nest
-        nested-attributes: u64-array
+        type: binary
+        sub-type: u64
       -
         name: uncorr
-        type: nest
-        nested-attributes: u64-array
+        type: binary
+        sub-type: u64
       -
         name: corr-bits
-        type: nest
-        nested-attributes: u64-array
+        type: binary
+        sub-type: u64
   -
     name: fec
     attributes:
@@ -827,8 +811,8 @@ attribute-sets:
         type: u32
       -
         name: index
-        type: nest
-        nested-attributes: s32-array
+        type: binary
+        sub-type: s32
   -
     name: module
     attributes:
index 614f1a585511487a85339de90e2b675a800e5439..6d89e30f5fd52b1bfe7c1f36f9b5a859ccccfc2b 100644 (file)
@@ -68,6 +68,9 @@ attribute-sets:
         type: nest
         nested-attributes: x509
         multi-attr: true
+      -
+        name: peername
+        type: string
   -
     name: done
     attributes:
@@ -105,6 +108,7 @@ operations:
             - auth-mode
             - peer-identity
             - certificate
+            - peername
     -
       name: done
       doc: Handler reports handshake completion
index adc4bf4f3c5017c4f78647e03ef61101e7f1a689..28925e19622dfa429e8651bdfb391ca001b4f783 100644 (file)
@@ -776,10 +776,11 @@ peer_notif_delay
        Specify the delay, in milliseconds, between each peer
        notification (gratuitous ARP and unsolicited IPv6 Neighbor
        Advertisement) when they are issued after a failover event.
-       This delay should be a multiple of the link monitor interval
-       (arp_interval or miimon, whichever is active). The default
-       value is 0 which means to match the value of the link monitor
-       interval.
+       This delay should be a multiple of the MII link monitor interval
+       (miimon).
+
+       The valid range is 0 - 300000. The default value is 0, which means
+       to match the value of the MII link monitor interval.
 
 prio
        Slave priority. A higher number means higher priority.
index 3a7a714cc08f0a74dbc6de9dfd90f83a566b539e..3354ca3608ee671adc06939d78302420099b3110 100644 (file)
@@ -40,6 +40,7 @@ flow_steering_mode: Device flow steering mode
 ---------------------------------------------
 The flow steering mode parameter controls the flow steering mode of the driver.
 Two modes are supported:
+
 1. 'dmfs' - Device managed flow steering.
 2. 'smfs' - Software/Driver managed flow steering.
 
@@ -99,6 +100,7 @@ between representors and stacked devices.
 By default metadata is enabled on the supported devices in E-switch.
 Metadata is applicable only for E-switch in switchdev mode and
 users may disable it when NONE of the below use cases will be in use:
+
 1. HCA is in Dual/multi-port RoCE mode.
 2. VF/SF representor bonding (Usually used for Live migration)
 3. Stacked devices
@@ -180,7 +182,8 @@ User commands examples:
 
     $ devlink health diagnose pci/0000:82:00.0 reporter tx
 
-NOTE: This command has valid output only when interface is up, otherwise the command has empty output.
+.. note::
+   This command has valid output only when interface is up, otherwise the command has empty output.
 
 - Show number of tx errors indicated, number of recover flows ended successfully,
   is autorecover enabled and graceful period from last recover::
@@ -232,8 +235,9 @@ User commands examples:
 
     $ devlink health dump show pci/0000:82:00.0 reporter fw
 
-NOTE: This command can run only on the PF which has fw tracer ownership,
-running it on other PF or any VF will return "Operation not permitted".
+.. note::
+   This command can run only on the PF which has fw tracer ownership,
+   running it on other PF or any VF will return "Operation not permitted".
 
 fw fatal reporter
 -----------------
@@ -256,7 +260,8 @@ User commands examples:
 
     $ devlink health dump show pci/0000:82:00.1 reporter fw_fatal
 
-NOTE: This command can run only on PF.
+.. note::
+   This command can run only on PF.
 
 vnic reporter
 -------------
@@ -265,28 +270,37 @@ It is responsible for querying the vnic diagnostic counters from fw and displayi
 them in realtime.
 
 Description of the vnic counters:
-total_q_under_processor_handle: number of queues in an error state due to
-an async error or errored command.
-send_queue_priority_update_flow: number of QP/SQ priority/SL update
-events.
-cq_overrun: number of times CQ entered an error state due to an
-overflow.
-async_eq_overrun: number of times an EQ mapped to async events was
-overrun.
-comp_eq_overrun: number of times an EQ mapped to completion events was
-overrun.
-quota_exceeded_command: number of commands issued and failed due to quota
-exceeded.
-invalid_command: number of commands issued and failed dues to any reason
-other than quota exceeded.
-nic_receive_steering_discard: number of packets that completed RX flow
-steering but were discarded due to a mismatch in flow table.
+
+- total_q_under_processor_handle
+        number of queues in an error state due to
+        an async error or errored command.
+- send_queue_priority_update_flow
+        number of QP/SQ priority/SL update events.
+- cq_overrun
+        number of times CQ entered an error state due to an overflow.
+- async_eq_overrun
+        number of times an EQ mapped to async events was overrun.
+        comp_eq_overrun number of times an EQ mapped to completion events was
+        overrun.
+- quota_exceeded_command
+        number of commands issued and failed due to quota exceeded.
+- invalid_command
+        number of commands issued and failed dues to any reason other than quota
+        exceeded.
+- nic_receive_steering_discard
+        number of packets that completed RX flow
+        steering but were discarded due to a mismatch in flow table.
 
 User commands examples:
-- Diagnose PF/VF vnic counters
+
+- Diagnose PF/VF vnic counters::
+
         $ devlink health diagnose pci/0000:82:00.1 reporter vnic
+
 - Diagnose representor vnic counters (performed by supplying devlink port of the
-  representor, which can be obtained via devlink port command)
+  representor, which can be obtained via devlink port command)::
+
         $ devlink health diagnose pci/0000:82:00.1/65537 reporter vnic
 
-NOTE: This command can run over all interfaces such as PF/VF and representor ports.
+.. note::
+   This command can run over all interfaces such as PF/VF and representor ports.
index a164ff074356e48970ef08fb7f2588c6843e156c..5b75c3f7a137b3dbde03903cb2a6a61c0f2facea 100644 (file)
@@ -116,8 +116,8 @@ Contents:
    udplite
    vrf
    vxlan
-   x25-iface
    x25
+   x25-iface
    xfrm_device
    xfrm_proc
    xfrm_sync
index a2817a88e905fa167244cebaf376684f3800faf2..6f5ea1646a4704653a41caee551ed85fdda12f0f 100644 (file)
@@ -53,6 +53,7 @@ fills in a structure that contains the parameters of the request:
         struct socket   *ta_sock;
         tls_done_func_t ta_done;
         void            *ta_data;
+        const char      *ta_peername;
         unsigned int    ta_timeout_ms;
         key_serial_t    ta_keyring;
         key_serial_t    ta_my_cert;
@@ -71,6 +72,10 @@ instantiated a struct file in sock->file.
 has completed. Further explanation of this function is in the "Handshake
 Completion" sesction below.
 
+The consumer can provide a NUL-terminated hostname in the @ta_peername
+field that is sent as part of ClientHello. If no peername is provided,
+the DNS hostname associated with the server's IP address is used instead.
+
 The consumer can fill in the @ta_timeout_ms field to force the servicing
 handshake agent to exit after a number of milliseconds. This enables the
 socket to be fully closed once both the kernel and the handshake agent
index f34e9ec6493729d96745c914879a75cd48abb97f..285cefcfce8761fd3f1e37f3b0a03dd7b53f4e33 100644 (file)
@@ -1,8 +1,7 @@
 .. SPDX-License-Identifier: GPL-2.0
 
-============================-
 X.25 Device Driver Interface
-============================-
+============================
 
 Version 1.1
 
index 7ae1f62fca14f8c5d06bd7d461d54853114063e3..8067236c51ab4208af1789eb907c479891685346 100644 (file)
@@ -1,7 +1,7 @@
 .. SPDX-License-Identifier: GPL-2.0
 
 ======
-pcmcia
+PCMCIA
 ======
 
 .. toctree::
index f73ac9e175a8dd9e94ceeebbf5257018397bcbc7..83614cec9328b62b2333947a5254b1f57519545f 100644 (file)
@@ -127,13 +127,32 @@ the value of ``Message-ID`` to the URL above.
 Updating patch status
 ~~~~~~~~~~~~~~~~~~~~~
 
-It may be tempting to help the maintainers and update the state of your
-own patches when you post a new version or spot a bug. Please **do not**
-do that.
-Interfering with the patch status on patchwork will only cause confusion. Leave
-it to the maintainer to figure out what is the most recent and current
-version that should be applied. If there is any doubt, the maintainer
-will reply and ask what should be done.
+Contributors and reviewers do not have the permissions to update patch
+state directly in patchwork. Patchwork doesn't expose much information
+about the history of the state of patches, therefore having multiple
+people update the state leads to confusion.
+
+Instead of delegating patchwork permissions netdev uses a simple mail
+bot which looks for special commands/lines within the emails sent to
+the mailing list. For example to mark a series as Changes Requested
+one needs to send the following line anywhere in the email thread::
+
+  pw-bot: changes-requested
+
+As a result the bot will set the entire series to Changes Requested.
+This may be useful when author discovers a bug in their own series
+and wants to prevent it from getting applied.
+
+The use of the bot is entirely optional, if in doubt ignore its existence
+completely. Maintainers will classify and update the state of the patches
+themselves. No email should ever be sent to the list with the main purpose
+of communicating with the bot, the bot commands should be seen as metadata.
+
+The use of the bot is restricted to authors of the patches (the ``From:``
+header on patch submission and command must match!), maintainers themselves
+and a handful of senior reviewers. Bot records its activity here:
+
+  https://patchwork.hopto.org/pw-bot.html
 
 Review timelines
 ~~~~~~~~~~~~~~~~
index d46e98c7c1ec6cabe1316c7122cea4a33933927f..bb3f4c4e288563dc1ca850b8f7f86b7b7347a56e 100644 (file)
@@ -551,7 +551,6 @@ These are the steps:
    * IOMMU_SUPPORT
    * S390
    * ZCRYPT
-   * S390_AP_IOMMU
    * VFIO
    * KVM
 
index 8a6860f33b4e7622003687a018816bc06469d5f9..7542220967cb4c3366665ee7a7730b62ae44bcdb 100644 (file)
@@ -1,5 +1,5 @@
 =================================
-brief tutorial on CRC computation
+Brief tutorial on CRC computation
 =================================
 
 A CRC is a long-division remainder.  You add the CRC to the message,
index df510ad0c989bef451443dd503cd70947c378d35..983f91f8f023e073ee0513708126cdede8c745d6 100644 (file)
@@ -1,7 +1,7 @@
 .. SPDX-License-Identifier: GPL-2.0
 
 ======
-timers
+Timers
 ======
 
 .. toctree::
index 479c9eac63352207d51859a65cc229f36022d361..3c9b263de9c24f6b3367bc1a8ae7cd80f06e993c 100644 (file)
@@ -35,7 +35,7 @@ Documentation written by Tom Zanussi
   in place of an explicit value field - this is simply a count of
   event hits.  If 'values' isn't specified, an implicit 'hitcount'
   value will be automatically created and used as the only value.
-  Keys can be any field, or the special string 'stacktrace', which
+  Keys can be any field, or the special string 'common_stacktrace', which
   will use the event's kernel stacktrace as the key.  The keywords
   'keys' or 'key' can be used to specify keys, and the keywords
   'values', 'vals', or 'val' can be used to specify values.  Compound
@@ -54,7 +54,7 @@ Documentation written by Tom Zanussi
   'compatible' if the fields named in the trigger share the same
   number and type of fields and those fields also have the same names.
   Note that any two events always share the compatible 'hitcount' and
-  'stacktrace' fields and can therefore be combined using those
+  'common_stacktrace' fields and can therefore be combined using those
   fields, however pointless that may be.
 
   'hist' triggers add a 'hist' file to each event's subdirectory.
@@ -547,9 +547,9 @@ Extended error information
   the hist trigger display symbolic call_sites, we can have the hist
   trigger additionally display the complete set of kernel stack traces
   that led to each call_site.  To do that, we simply use the special
-  value 'stacktrace' for the key parameter::
+  value 'common_stacktrace' for the key parameter::
 
-    # echo 'hist:keys=stacktrace:values=bytes_req,bytes_alloc:sort=bytes_alloc' > \
+    # echo 'hist:keys=common_stacktrace:values=bytes_req,bytes_alloc:sort=bytes_alloc' > \
            /sys/kernel/tracing/events/kmem/kmalloc/trigger
 
   The above trigger will use the kernel stack trace in effect when an
@@ -561,9 +561,9 @@ Extended error information
   every callpath to a kmalloc for a kernel compile)::
 
     # cat /sys/kernel/tracing/events/kmem/kmalloc/hist
-    # trigger info: hist:keys=stacktrace:vals=bytes_req,bytes_alloc:sort=bytes_alloc:size=2048 [active]
+    # trigger info: hist:keys=common_stacktrace:vals=bytes_req,bytes_alloc:sort=bytes_alloc:size=2048 [active]
 
-    { stacktrace:
+    { common_stacktrace:
          __kmalloc_track_caller+0x10b/0x1a0
          kmemdup+0x20/0x50
          hidraw_report_event+0x8a/0x120 [hid]
@@ -581,7 +581,7 @@ Extended error information
          cpu_startup_entry+0x315/0x3e0
          rest_init+0x7c/0x80
     } hitcount:          3  bytes_req:         21  bytes_alloc:         24
-    { stacktrace:
+    { common_stacktrace:
          __kmalloc_track_caller+0x10b/0x1a0
          kmemdup+0x20/0x50
          hidraw_report_event+0x8a/0x120 [hid]
@@ -596,7 +596,7 @@ Extended error information
          do_IRQ+0x5a/0xf0
          ret_from_intr+0x0/0x30
     } hitcount:          3  bytes_req:         21  bytes_alloc:         24
-    { stacktrace:
+    { common_stacktrace:
          kmem_cache_alloc_trace+0xeb/0x150
          aa_alloc_task_context+0x27/0x40
          apparmor_cred_prepare+0x1f/0x50
@@ -608,7 +608,7 @@ Extended error information
     .
     .
     .
-    { stacktrace:
+    { common_stacktrace:
          __kmalloc+0x11b/0x1b0
          i915_gem_execbuffer2+0x6c/0x2c0 [i915]
          drm_ioctl+0x349/0x670 [drm]
@@ -616,7 +616,7 @@ Extended error information
          SyS_ioctl+0x81/0xa0
          system_call_fastpath+0x12/0x6a
     } hitcount:      17726  bytes_req:   13944120  bytes_alloc:   19593808
-    { stacktrace:
+    { common_stacktrace:
          __kmalloc+0x11b/0x1b0
          load_elf_phdrs+0x76/0xa0
          load_elf_binary+0x102/0x1650
@@ -625,7 +625,7 @@ Extended error information
          SyS_execve+0x3a/0x50
          return_from_execve+0x0/0x23
     } hitcount:      33348  bytes_req:   17152128  bytes_alloc:   20226048
-    { stacktrace:
+    { common_stacktrace:
          kmem_cache_alloc_trace+0xeb/0x150
          apparmor_file_alloc_security+0x27/0x40
          security_file_alloc+0x16/0x20
@@ -636,7 +636,7 @@ Extended error information
          SyS_open+0x1e/0x20
          system_call_fastpath+0x12/0x6a
     } hitcount:    4766422  bytes_req:    9532844  bytes_alloc:   38131376
-    { stacktrace:
+    { common_stacktrace:
          __kmalloc+0x11b/0x1b0
          seq_buf_alloc+0x1b/0x50
          seq_read+0x2cc/0x370
@@ -1026,7 +1026,7 @@ Extended error information
   First we set up an initially paused stacktrace trigger on the
   netif_receive_skb event::
 
-    # echo 'hist:key=stacktrace:vals=len:pause' > \
+    # echo 'hist:key=common_stacktrace:vals=len:pause' > \
            /sys/kernel/tracing/events/net/netif_receive_skb/trigger
 
   Next, we set up an 'enable_hist' trigger on the sched_process_exec
@@ -1060,9 +1060,9 @@ Extended error information
     $ wget https://www.kernel.org/pub/linux/kernel/v3.x/patch-3.19.xz
 
     # cat /sys/kernel/tracing/events/net/netif_receive_skb/hist
-    # trigger info: hist:keys=stacktrace:vals=len:sort=hitcount:size=2048 [paused]
+    # trigger info: hist:keys=common_stacktrace:vals=len:sort=hitcount:size=2048 [paused]
 
-    { stacktrace:
+    { common_stacktrace:
          __netif_receive_skb_core+0x46d/0x990
          __netif_receive_skb+0x18/0x60
          netif_receive_skb_internal+0x23/0x90
@@ -1079,7 +1079,7 @@ Extended error information
          kthread+0xd2/0xf0
          ret_from_fork+0x42/0x70
     } hitcount:         85  len:      28884
-    { stacktrace:
+    { common_stacktrace:
          __netif_receive_skb_core+0x46d/0x990
          __netif_receive_skb+0x18/0x60
          netif_receive_skb_internal+0x23/0x90
@@ -1097,7 +1097,7 @@ Extended error information
          irq_thread+0x11f/0x150
          kthread+0xd2/0xf0
     } hitcount:         98  len:     664329
-    { stacktrace:
+    { common_stacktrace:
          __netif_receive_skb_core+0x46d/0x990
          __netif_receive_skb+0x18/0x60
          process_backlog+0xa8/0x150
@@ -1115,7 +1115,7 @@ Extended error information
          inet_sendmsg+0x64/0xa0
          sock_sendmsg+0x3d/0x50
     } hitcount:        115  len:      13030
-    { stacktrace:
+    { common_stacktrace:
          __netif_receive_skb_core+0x46d/0x990
          __netif_receive_skb+0x18/0x60
          netif_receive_skb_internal+0x23/0x90
@@ -1142,14 +1142,14 @@ Extended error information
   into the histogram.  In order to avoid having to set everything up
   again, we can just clear the histogram first::
 
-    # echo 'hist:key=stacktrace:vals=len:clear' >> \
+    # echo 'hist:key=common_stacktrace:vals=len:clear' >> \
            /sys/kernel/tracing/events/net/netif_receive_skb/trigger
 
   Just to verify that it is in fact cleared, here's what we now see in
   the hist file::
 
     # cat /sys/kernel/tracing/events/net/netif_receive_skb/hist
-    # trigger info: hist:keys=stacktrace:vals=len:sort=hitcount:size=2048 [paused]
+    # trigger info: hist:keys=common_stacktrace:vals=len:sort=hitcount:size=2048 [paused]
 
     Totals:
         Hits: 0
@@ -1485,12 +1485,12 @@ Extended error information
 
   And here's an example that shows how to combine histogram data from
   any two events even if they don't share any 'compatible' fields
-  other than 'hitcount' and 'stacktrace'.  These commands create a
+  other than 'hitcount' and 'common_stacktrace'.  These commands create a
   couple of triggers named 'bar' using those fields::
 
-    # echo 'hist:name=bar:key=stacktrace:val=hitcount' > \
+    # echo 'hist:name=bar:key=common_stacktrace:val=hitcount' > \
            /sys/kernel/tracing/events/sched/sched_process_fork/trigger
-    # echo 'hist:name=bar:key=stacktrace:val=hitcount' > \
+    # echo 'hist:name=bar:key=common_stacktrace:val=hitcount' > \
           /sys/kernel/tracing/events/net/netif_rx/trigger
 
   And displaying the output of either shows some interesting if
@@ -1501,16 +1501,16 @@ Extended error information
 
     # event histogram
     #
-    # trigger info: hist:name=bar:keys=stacktrace:vals=hitcount:sort=hitcount:size=2048 [active]
+    # trigger info: hist:name=bar:keys=common_stacktrace:vals=hitcount:sort=hitcount:size=2048 [active]
     #
 
-    { stacktrace:
+    { common_stacktrace:
              kernel_clone+0x18e/0x330
              kernel_thread+0x29/0x30
              kthreadd+0x154/0x1b0
              ret_from_fork+0x3f/0x70
     } hitcount:          1
-    { stacktrace:
+    { common_stacktrace:
              netif_rx_internal+0xb2/0xd0
              netif_rx_ni+0x20/0x70
              dev_loopback_xmit+0xaa/0xd0
@@ -1528,7 +1528,7 @@ Extended error information
              call_cpuidle+0x3b/0x60
              cpu_startup_entry+0x22d/0x310
     } hitcount:          1
-    { stacktrace:
+    { common_stacktrace:
              netif_rx_internal+0xb2/0xd0
              netif_rx_ni+0x20/0x70
              dev_loopback_xmit+0xaa/0xd0
@@ -1543,7 +1543,7 @@ Extended error information
              SyS_sendto+0xe/0x10
              entry_SYSCALL_64_fastpath+0x12/0x6a
     } hitcount:          2
-    { stacktrace:
+    { common_stacktrace:
              netif_rx_internal+0xb2/0xd0
              netif_rx+0x1c/0x60
              loopback_xmit+0x6c/0xb0
@@ -1561,7 +1561,7 @@ Extended error information
              sock_sendmsg+0x38/0x50
              ___sys_sendmsg+0x14e/0x270
     } hitcount:         76
-    { stacktrace:
+    { common_stacktrace:
              netif_rx_internal+0xb2/0xd0
              netif_rx+0x1c/0x60
              loopback_xmit+0x6c/0xb0
@@ -1579,7 +1579,7 @@ Extended error information
              sock_sendmsg+0x38/0x50
              ___sys_sendmsg+0x269/0x270
     } hitcount:         77
-    { stacktrace:
+    { common_stacktrace:
              netif_rx_internal+0xb2/0xd0
              netif_rx+0x1c/0x60
              loopback_xmit+0x6c/0xb0
@@ -1597,7 +1597,7 @@ Extended error information
              sock_sendmsg+0x38/0x50
              SYSC_sendto+0xef/0x170
     } hitcount:         88
-    { stacktrace:
+    { common_stacktrace:
              kernel_clone+0x18e/0x330
              SyS_clone+0x19/0x20
              entry_SYSCALL_64_fastpath+0x12/0x6a
@@ -1949,7 +1949,7 @@ uninterruptible state::
 
   # cd /sys/kernel/tracing
   # echo 's:block_lat pid_t pid; u64 delta; unsigned long[] stack;' > dynamic_events
-  # echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=stacktrace  if prev_state == 2' >> events/sched/sched_switch/trigger
+  # echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=common_stacktrace  if prev_state == 2' >> events/sched/sched_switch/trigger
   # echo 'hist:keys=prev_pid:delta=common_timestamp.usecs-$ts,s=$st:onmax($delta).trace(block_lat,prev_pid,$delta,$s)' >> events/sched/sched_switch/trigger
   # echo 1 > events/synthetic/block_lat/enable
   # cat trace
index 176e8fc3f31b9393421c9c75073d927911f1b4c2..4ea5b837399ad1cb93f837a0f090bc87ed1f3089 100644 (file)
@@ -180,6 +180,7 @@ Code  Seq#    Include File                                           Comments
 'P'   00-0F  drivers/usb/class/usblp.c                               conflict!
 'P'   01-09  drivers/misc/pci_endpoint_test.c                        conflict!
 'P'   00-0F  xen/privcmd.h                                           conflict!
+'P'   00-05  linux/tps6594_pfsm.h                                    conflict!
 'Q'   all    linux/soundcard.h
 'R'   00-1F  linux/random.h                                          conflict!
 'R'   01     linux/rfkill.h                                          conflict!
@@ -363,7 +364,7 @@ Code  Seq#    Include File                                           Comments
 0xCC  00-0F  drivers/misc/ibmvmc.h                                   pseries VMC driver
 0xCD  01     linux/reiserfs_fs.h
 0xCE  01-02  uapi/linux/cxl_mem.h                                    Compute Express Link Memory Devices
-0xCF  02     fs/cifs/ioctl.c
+0xCF  02     fs/smb/client/cifs_ioctl.h
 0xDB  00-0F  drivers/char/mwave/mwavepub.h
 0xDD  00-3F                                                          ZFCP device driver see drivers/s390/scsi/
                                                                      <mailto:aherrman@de.ibm.com>
index 7e0b87d5aa2e571d8a54ea4df45fc27897afeff5..6969a2962ffe67e9e1a1e87cfaddf25d97d46b3f 100644 (file)
@@ -273,8 +273,8 @@ ABI/API
 L:     linux-api@vger.kernel.org
 F:     include/linux/syscalls.h
 F:     kernel/sys_ni.c
-X:     include/uapi/
 X:     arch/*/include/uapi/
+X:     include/uapi/
 
 ABIT UGURU 1,2 HARDWARE MONITOR DRIVER
 M:     Hans de Goede <hdegoede@redhat.com>
@@ -406,12 +406,6 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/acpi/arm64
 
-ACPI SERIAL MULTI INSTANTIATE DRIVER
-M:     Hans de Goede <hdegoede@redhat.com>
-L:     platform-driver-x86@vger.kernel.org
-S:     Maintained
-F:     drivers/platform/x86/serial-multi-instantiate.c
-
 ACPI PCC(Platform Communication Channel) MAILBOX DRIVER
 M:     Sudeep Holla <sudeep.holla@arm.com>
 L:     linux-acpi@vger.kernel.org
@@ -430,6 +424,12 @@ B: https://bugzilla.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
 F:     drivers/acpi/pmic/
 
+ACPI SERIAL MULTI INSTANTIATE DRIVER
+M:     Hans de Goede <hdegoede@redhat.com>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     drivers/platform/x86/serial-multi-instantiate.c
+
 ACPI THERMAL DRIVER
 M:     Rafael J. Wysocki <rafael@kernel.org>
 R:     Zhang Rui <rui.zhang@intel.com>
@@ -823,6 +823,13 @@ L: linux-crypto@vger.kernel.org
 S:     Maintained
 F:     drivers/crypto/allwinner/
 
+ALLWINNER DMIC DRIVERS
+M:     Ban Tao <fengzheng923@gmail.com>
+L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
+S:     Maintained
+F:     Documentation/devicetree/bindings/sound/allwinner,sun50i-h6-dmic.yaml
+F:     sound/soc/sunxi/sun50i-dmic.c
+
 ALLWINNER HARDWARE SPINLOCK SUPPORT
 M:     Wilken Gottwalt <wilken.gottwalt@posteo.net>
 S:     Maintained
@@ -844,13 +851,6 @@ L: linux-media@vger.kernel.org
 S:     Maintained
 F:     drivers/staging/media/sunxi/cedrus/
 
-ALLWINNER DMIC DRIVERS
-M:     Ban Tao <fengzheng923@gmail.com>
-L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
-S:     Maintained
-F:     Documentation/devicetree/bindings/sound/allwinner,sun50i-h6-dmic.yaml
-F:     sound/soc/sunxi/sun50i-dmic.c
-
 ALPHA PORT
 M:     Richard Henderson <richard.henderson@linaro.org>
 M:     Ivan Kokshaysky <ink@jurassic.park.msu.ru>
@@ -956,7 +956,8 @@ F:  Documentation/networking/device_drivers/ethernet/amazon/ena.rst
 F:     drivers/net/ethernet/amazon/
 
 AMAZON RDMA EFA DRIVER
-M:     Gal Pressman <galpress@amazon.com>
+M:     Michael Margolin <mrgolin@amazon.com>
+R:     Gal Pressman <gal.pressman@linux.dev>
 R:     Yossi Leybovich <sleybo@amazon.com>
 L:     linux-rdma@vger.kernel.org
 S:     Supported
@@ -1026,6 +1027,16 @@ F:       drivers/char/hw_random/geode-rng.c
 F:     drivers/crypto/geode*
 F:     drivers/video/fbdev/geode/
 
+AMD HSMP DRIVER
+M:     Naveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com>
+R:     Carlos Bilbao <carlos.bilbao@amd.com>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     Documentation/arch/x86/amd_hsmp.rst
+F:     arch/x86/include/asm/amd_hsmp.h
+F:     arch/x86/include/uapi/asm/amd_hsmp.h
+F:     drivers/platform/x86/amd/hsmp.c
+
 AMD IOMMU (AMD-VI)
 M:     Joerg Roedel <joro@8bytes.org>
 R:     Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
@@ -1049,6 +1060,13 @@ F:       drivers/gpu/drm/amd/include/vi_structs.h
 F:     include/uapi/linux/kfd_ioctl.h
 F:     include/uapi/linux/kfd_sysfs.h
 
+AMD MP2 I2C DRIVER
+M:     Elie Morisse <syniurge@gmail.com>
+M:     Shyam Sundar S K <shyam-sundar.s-k@amd.com>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     drivers/i2c/busses/i2c-amd-mp2*
+
 AMD PDS CORE DRIVER
 M:     Shannon Nelson <shannon.nelson@amd.com>
 M:     Brett Creeley <brett.creeley@amd.com>
@@ -1058,18 +1076,6 @@ F:       Documentation/networking/device_drivers/ethernet/amd/pds_core.rst
 F:     drivers/net/ethernet/amd/pds_core/
 F:     include/linux/pds/
 
-AMD SPI DRIVER
-M:     Sanjay R Mehta <sanju.mehta@amd.com>
-S:     Maintained
-F:     drivers/spi/spi-amd.c
-
-AMD MP2 I2C DRIVER
-M:     Elie Morisse <syniurge@gmail.com>
-M:     Shyam Sundar S K <shyam-sundar.s-k@amd.com>
-L:     linux-i2c@vger.kernel.org
-S:     Maintained
-F:     drivers/i2c/busses/i2c-amd-mp2*
-
 AMD PMC DRIVER
 M:     Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
 L:     platform-driver-x86@vger.kernel.org
@@ -1083,16 +1089,6 @@ S:       Maintained
 F:     Documentation/ABI/testing/sysfs-amd-pmf
 F:     drivers/platform/x86/amd/pmf/
 
-AMD HSMP DRIVER
-M:     Naveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com>
-R:     Carlos Bilbao <carlos.bilbao@amd.com>
-L:     platform-driver-x86@vger.kernel.org
-S:     Maintained
-F:     Documentation/arch/x86/amd_hsmp.rst
-F:     arch/x86/include/asm/amd_hsmp.h
-F:     arch/x86/include/uapi/asm/amd_hsmp.h
-F:     drivers/platform/x86/amd/hsmp.c
-
 AMD POWERPLAY AND SWSMU
 M:     Evan Quan <evan.quan@amd.com>
 L:     amd-gfx@lists.freedesktop.org
@@ -1121,13 +1117,6 @@ M:       Tom Lendacky <thomas.lendacky@amd.com>
 S:     Supported
 F:     arch/arm64/boot/dts/amd/
 
-AMD XGBE DRIVER
-M:     "Shyam Sundar S K" <Shyam-sundar.S-k@amd.com>
-L:     netdev@vger.kernel.org
-S:     Supported
-F:     arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi
-F:     drivers/net/ethernet/amd/xgbe/
-
 AMD SENSOR FUSION HUB DRIVER
 M:     Basavaraj Natikar <basavaraj.natikar@amd.com>
 L:     linux-input@vger.kernel.org
@@ -1135,6 +1124,18 @@ S:       Maintained
 F:     Documentation/hid/amd-sfh*
 F:     drivers/hid/amd-sfh-hid/
 
+AMD SPI DRIVER
+M:     Sanjay R Mehta <sanju.mehta@amd.com>
+S:     Maintained
+F:     drivers/spi/spi-amd.c
+
+AMD XGBE DRIVER
+M:     "Shyam Sundar S K" <Shyam-sundar.S-k@amd.com>
+L:     netdev@vger.kernel.org
+S:     Supported
+F:     arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi
+F:     drivers/net/ethernet/amd/xgbe/
+
 AMLOGIC DDR PMU DRIVER
 M:     Jiucheng Xu <jiucheng.xu@amlogic.com>
 L:     linux-amlogic@lists.infradead.org
@@ -1169,6 +1170,14 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
 F:     drivers/net/amt.c
 
+ANALOG DEVICES INC AD3552R DRIVER
+M:     Nuno Sá <nuno.sa@analog.com>
+L:     linux-iio@vger.kernel.org
+S:     Supported
+W:     https://ez.analog.com/linux-software-drivers
+F:     Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
+F:     drivers/iio/dac/ad3552r.c
+
 ANALOG DEVICES INC AD4130 DRIVER
 M:     Cosmin Tanislav <cosmin.tanislav@analog.com>
 L:     linux-iio@vger.kernel.org
@@ -1194,14 +1203,6 @@ W:       https://ez.analog.com/linux-software-drivers
 F:     Documentation/devicetree/bindings/iio/adc/adi,ad7292.yaml
 F:     drivers/iio/adc/ad7292.c
 
-ANALOG DEVICES INC AD3552R DRIVER
-M:     Nuno Sá <nuno.sa@analog.com>
-L:     linux-iio@vger.kernel.org
-S:     Supported
-W:     https://ez.analog.com/linux-software-drivers
-F:     Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
-F:     drivers/iio/dac/ad3552r.c
-
 ANALOG DEVICES INC AD7293 DRIVER
 M:     Antoniu Miclaus <antoniu.miclaus@analog.com>
 L:     linux-iio@vger.kernel.org
@@ -1210,23 +1211,6 @@ W:       https://ez.analog.com/linux-software-drivers
 F:     Documentation/devicetree/bindings/iio/dac/adi,ad7293.yaml
 F:     drivers/iio/dac/ad7293.c
 
-ANALOG DEVICES INC AD7768-1 DRIVER
-M:     Michael Hennerich <Michael.Hennerich@analog.com>
-L:     linux-iio@vger.kernel.org
-S:     Supported
-W:     https://ez.analog.com/linux-software-drivers
-F:     Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml
-F:     drivers/iio/adc/ad7768-1.c
-
-ANALOG DEVICES INC AD7780 DRIVER
-M:     Michael Hennerich <Michael.Hennerich@analog.com>
-M:     Renato Lui Geh <renatogeh@gmail.com>
-L:     linux-iio@vger.kernel.org
-S:     Supported
-W:     https://ez.analog.com/linux-software-drivers
-F:     Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml
-F:     drivers/iio/adc/ad7780.c
-
 ANALOG DEVICES INC AD74115 DRIVER
 M:     Cosmin Tanislav <cosmin.tanislav@analog.com>
 L:     linux-iio@vger.kernel.org
@@ -1244,6 +1228,23 @@ F:       Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml
 F:     drivers/iio/addac/ad74413r.c
 F:     include/dt-bindings/iio/addac/adi,ad74413r.h
 
+ANALOG DEVICES INC AD7768-1 DRIVER
+M:     Michael Hennerich <Michael.Hennerich@analog.com>
+L:     linux-iio@vger.kernel.org
+S:     Supported
+W:     https://ez.analog.com/linux-software-drivers
+F:     Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml
+F:     drivers/iio/adc/ad7768-1.c
+
+ANALOG DEVICES INC AD7780 DRIVER
+M:     Michael Hennerich <Michael.Hennerich@analog.com>
+M:     Renato Lui Geh <renatogeh@gmail.com>
+L:     linux-iio@vger.kernel.org
+S:     Supported
+W:     https://ez.analog.com/linux-software-drivers
+F:     Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml
+F:     drivers/iio/adc/ad7780.c
+
 ANALOG DEVICES INC ADA4250 DRIVER
 M:     Antoniu Miclaus <antoniu.miclaus@analog.com>
 L:     linux-iio@vger.kernel.org
@@ -1294,10 +1295,10 @@ F:      drivers/iio/imu/adis16460.c
 ANALOG DEVICES INC ADIS16475 DRIVER
 M:     Nuno Sa <nuno.sa@analog.com>
 L:     linux-iio@vger.kernel.org
-W:     https://ez.analog.com/linux-software-drivers
 S:     Supported
-F:     drivers/iio/imu/adis16475.c
+W:     https://ez.analog.com/linux-software-drivers
 F:     Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml
+F:     drivers/iio/imu/adis16475.c
 
 ANALOG DEVICES INC ADM1177 DRIVER
 M:     Michael Hennerich <Michael.Hennerich@analog.com>
@@ -1315,21 +1316,21 @@ W:      https://ez.analog.com/linux-software-drivers
 F:     Documentation/devicetree/bindings/iio/frequency/adi,admv1013.yaml
 F:     drivers/iio/frequency/admv1013.c
 
-ANALOG DEVICES INC ADMV8818 DRIVER
+ANALOG DEVICES INC ADMV1014 DRIVER
 M:     Antoniu Miclaus <antoniu.miclaus@analog.com>
 L:     linux-iio@vger.kernel.org
 S:     Supported
 W:     https://ez.analog.com/linux-software-drivers
-F:     Documentation/devicetree/bindings/iio/filter/adi,admv8818.yaml
-F:     drivers/iio/filter/admv8818.c
+F:     Documentation/devicetree/bindings/iio/frequency/adi,admv1014.yaml
+F:     drivers/iio/frequency/admv1014.c
 
-ANALOG DEVICES INC ADMV1014 DRIVER
+ANALOG DEVICES INC ADMV8818 DRIVER
 M:     Antoniu Miclaus <antoniu.miclaus@analog.com>
 L:     linux-iio@vger.kernel.org
 S:     Supported
 W:     https://ez.analog.com/linux-software-drivers
-F:     Documentation/devicetree/bindings/iio/frequency/adi,admv1014.yaml
-F:     drivers/iio/frequency/admv1014.c
+F:     Documentation/devicetree/bindings/iio/filter/adi,admv8818.yaml
+F:     drivers/iio/filter/admv8818.c
 
 ANALOG DEVICES INC ADP5061 DRIVER
 M:     Michael Hennerich <Michael.Hennerich@analog.com>
@@ -1351,8 +1352,8 @@ M:        Lars-Peter Clausen <lars@metafoo.de>
 L:     linux-media@vger.kernel.org
 S:     Supported
 W:     https://ez.analog.com/linux-software-drivers
-F:     drivers/media/i2c/adv7180.c
 F:     Documentation/devicetree/bindings/media/i2c/adv7180.yaml
+F:     drivers/media/i2c/adv7180.c
 
 ANALOG DEVICES INC ADV748X DRIVER
 M:     Kieran Bingham <kieran.bingham@ideasonboard.com>
@@ -1371,8 +1372,8 @@ ANALOG DEVICES INC ADV7604 DRIVER
 M:     Hans Verkuil <hverkuil-cisco@xs4all.nl>
 L:     linux-media@vger.kernel.org
 S:     Maintained
-F:     drivers/media/i2c/adv7604*
 F:     Documentation/devicetree/bindings/media/i2c/adv7604.yaml
+F:     drivers/media/i2c/adv7604*
 
 ANALOG DEVICES INC ADV7842 DRIVER
 M:     Hans Verkuil <hverkuil-cisco@xs4all.nl>
@@ -1384,8 +1385,8 @@ ANALOG DEVICES INC ADXRS290 DRIVER
 M:     Nishant Malpani <nish.malpani25@gmail.com>
 L:     linux-iio@vger.kernel.org
 S:     Supported
-F:     drivers/iio/gyro/adxrs290.c
 F:     Documentation/devicetree/bindings/iio/gyroscope/adi,adxrs290.yaml
+F:     drivers/iio/gyro/adxrs290.c
 
 ANALOG DEVICES INC ASOC CODEC DRIVERS
 M:     Lars-Peter Clausen <lars@metafoo.de>
@@ -1600,7 +1601,7 @@ F:        drivers/media/i2c/ar0521.c
 
 ARASAN NAND CONTROLLER DRIVER
 M:     Miquel Raynal <miquel.raynal@bootlin.com>
-M:     Naga Sureshkumar Relli <nagasure@xilinx.com>
+R:     Michal Simek <michal.simek@amd.com>
 L:     linux-mtd@lists.infradead.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/mtd/arasan,nand-controller.yaml
@@ -1625,6 +1626,17 @@ S:       Maintained
 F:     drivers/net/arcnet/
 F:     include/uapi/linux/if_arcnet.h
 
+ARM AND ARM64 SoC SUB-ARCHITECTURES (COMMON PARTS)
+M:     Arnd Bergmann <arnd@arndb.de>
+M:     Olof Johansson <olof@lixom.net>
+M:     soc@kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+C:     irc://irc.libera.chat/armlinux
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git
+F:     arch/arm/boot/dts/Makefile
+F:     arch/arm64/boot/dts/Makefile
+
 ARM ARCHITECTED TIMER DRIVER
 M:     Mark Rutland <mark.rutland@arm.com>
 M:     Marc Zyngier <maz@kernel.org>
@@ -1666,10 +1678,7 @@ F:       drivers/power/reset/arm-versatile-reboot.c
 F:     drivers/soc/versatile/
 
 ARM KOMEDA DRM-KMS DRIVER
-M:     James (Qian) Wang <james.qian.wang@arm.com>
 M:     Liviu Dudau <liviu.dudau@arm.com>
-M:     Mihail Atanassov <mihail.atanassov@arm.com>
-L:     Mali DP Maintainers <malidp@foss.arm.com>
 S:     Supported
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 F:     Documentation/devicetree/bindings/display/arm,komeda.yaml
@@ -1690,8 +1699,6 @@ F:        include/uapi/drm/panfrost_drm.h
 
 ARM MALI-DP DRM DRIVER
 M:     Liviu Dudau <liviu.dudau@arm.com>
-M:     Brian Starkey <brian.starkey@arm.com>
-L:     Mali DP Maintainers <malidp@foss.arm.com>
 S:     Supported
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 F:     Documentation/devicetree/bindings/display/arm,malidp.yaml
@@ -1738,22 +1745,6 @@ S:       Odd Fixes
 F:     drivers/amba/
 F:     include/linux/amba/bus.h
 
-ARM PRIMECELL PL35X NAND CONTROLLER DRIVER
-M:     Miquel Raynal <miquel.raynal@bootlin.com>
-M:     Naga Sureshkumar Relli <nagasure@xilinx.com>
-L:     linux-mtd@lists.infradead.org
-S:     Maintained
-F:     Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml
-F:     drivers/mtd/nand/raw/pl35x-nand-controller.c
-
-ARM PRIMECELL PL35X SMC DRIVER
-M:     Miquel Raynal <miquel.raynal@bootlin.com>
-M:     Naga Sureshkumar Relli <nagasure@xilinx.com>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     Maintained
-F:     Documentation/devicetree/bindings/memory-controllers/arm,pl35x-smc.yaml
-F:     drivers/memory/pl353-smc.c
-
 ARM PRIMECELL CLCD PL110 DRIVER
 M:     Russell King <linux@armlinux.org.uk>
 S:     Odd Fixes
@@ -1771,6 +1762,22 @@ S:       Odd Fixes
 F:     drivers/mmc/host/mmci.*
 F:     include/linux/amba/mmci.h
 
+ARM PRIMECELL PL35X NAND CONTROLLER DRIVER
+M:     Miquel Raynal <miquel.raynal@bootlin.com>
+R:     Michal Simek <michal.simek@amd.com>
+L:     linux-mtd@lists.infradead.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml
+F:     drivers/mtd/nand/raw/pl35x-nand-controller.c
+
+ARM PRIMECELL PL35X SMC DRIVER
+M:     Miquel Raynal <miquel.raynal@bootlin.com>
+R:     Michal Simek <michal.simek@amd.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     Documentation/devicetree/bindings/memory-controllers/arm,pl35x-smc.yaml
+F:     drivers/memory/pl353-smc.c
+
 ARM PRIMECELL SSP PL022 SPI DRIVER
 M:     Linus Walleij <linus.walleij@linaro.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1807,17 +1814,6 @@ F:       Documentation/devicetree/bindings/iommu/arm,smmu*
 F:     drivers/iommu/arm/
 F:     drivers/iommu/io-pgtable-arm*
 
-ARM AND ARM64 SoC SUB-ARCHITECTURES (COMMON PARTS)
-M:     Arnd Bergmann <arnd@arndb.de>
-M:     Olof Johansson <olof@lixom.net>
-M:     soc@kernel.org
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     Maintained
-C:     irc://irc.libera.chat/armlinux
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git
-F:     arch/arm/boot/dts/Makefile
-F:     arch/arm64/boot/dts/Makefile
-
 ARM SUB-ARCHITECTURES
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
@@ -1869,9 +1865,9 @@ M:        Chen-Yu Tsai <wens@csie.org>
 M:     Jernej Skrabec <jernej.skrabec@gmail.com>
 M:     Samuel Holland <samuel@sholland.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:     linux-sunxi@lists.linux.dev
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git
-L:     linux-sunxi@lists.linux.dev
 F:     arch/arm/mach-sunxi/
 F:     arch/arm64/boot/dts/allwinner/
 F:     drivers/clk/sunxi-ng/
@@ -1934,6 +1930,15 @@ F:       arch/arm/mach-alpine/
 F:     arch/arm64/boot/dts/amazon/
 F:     drivers/*/*alpine*
 
+ARM/APPLE MACHINE SOUND DRIVERS
+M:     Martin PoviÅ¡er <povik+lin@cutebit.org>
+L:     asahi@lists.linux.dev
+L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
+S:     Maintained
+F:     Documentation/devicetree/bindings/sound/apple,*
+F:     sound/soc/apple/*
+F:     sound/soc/codecs/cs42l83-i2c.c
+
 ARM/APPLE MACHINE SUPPORT
 M:     Hector Martin <marcan@marcan.st>
 M:     Sven Peter <sven@svenpeter.dev>
@@ -1961,7 +1966,7 @@ F:        Documentation/devicetree/bindings/nvmem/apple,efuses.yaml
 F:     Documentation/devicetree/bindings/pci/apple,pcie.yaml
 F:     Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
 F:     Documentation/devicetree/bindings/power/apple*
-F:     Documentation/devicetree/bindings/pwm/pwm-apple.yaml
+F:     Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml
 F:     Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
 F:     arch/arm64/boot/dts/apple/
 F:     drivers/bluetooth/hci_bcm4377.c
@@ -1985,15 +1990,6 @@ F:       include/dt-bindings/pinctrl/apple.h
 F:     include/linux/apple-mailbox.h
 F:     include/linux/soc/apple/*
 
-ARM/APPLE MACHINE SOUND DRIVERS
-M:     Martin PoviÅ¡er <povik+lin@cutebit.org>
-L:     asahi@lists.linux.dev
-L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
-S:     Maintained
-F:     Documentation/devicetree/bindings/sound/apple,*
-F:     sound/soc/apple/*
-F:     sound/soc/codecs/cs42l83-i2c.c
-
 ARM/ARTPEC MACHINE SUPPORT
 M:     Jesper Nilsson <jesper.nilsson@axis.com>
 M:     Lars Persson <lars.persson@axis.com>
@@ -2109,19 +2105,19 @@ S:      Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/coresight/linux.git
 F:     Documentation/ABI/testing/sysfs-bus-coresight-devices-*
 F:     Documentation/devicetree/bindings/arm/arm,coresight-*.yaml
-F:     Documentation/devicetree/bindings/arm/qcom,coresight-*.yaml
 F:     Documentation/devicetree/bindings/arm/arm,embedded-trace-extension.yaml
 F:     Documentation/devicetree/bindings/arm/arm,trace-buffer-extension.yaml
+F:     Documentation/devicetree/bindings/arm/qcom,coresight-*.yaml
 F:     Documentation/trace/coresight/*
 F:     drivers/hwtracing/coresight/*
 F:     include/dt-bindings/arm/coresight-cti-dt.h
 F:     include/linux/coresight*
 F:     samples/coresight/*
-F:     tools/perf/tests/shell/coresight/*
 F:     tools/perf/arch/arm/util/auxtrace.c
 F:     tools/perf/arch/arm/util/cs-etm.c
 F:     tools/perf/arch/arm/util/cs-etm.h
 F:     tools/perf/arch/arm/util/pmu.c
+F:     tools/perf/tests/shell/coresight/*
 F:     tools/perf/util/cs-etm-decoder/*
 F:     tools/perf/util/cs-etm.*
 
@@ -2156,9 +2152,9 @@ F:        Documentation/devicetree/bindings/leds/cznic,turris-omnia-leds.yaml
 F:     Documentation/devicetree/bindings/watchdog/armada-37xx-wdt.txt
 F:     drivers/bus/moxtet.c
 F:     drivers/firmware/turris-mox-rwtm.c
+F:     drivers/gpio/gpio-moxtet.c
 F:     drivers/leds/leds-turris-omnia.c
 F:     drivers/mailbox/armada-37xx-rwtm-mailbox.c
-F:     drivers/gpio/gpio-moxtet.c
 F:     drivers/watchdog/armada_37xx_wdt.c
 F:     include/dt-bindings/bus/moxtet.h
 F:     include/linux/armada-37xx-rwtm-mailbox.h
@@ -2188,10 +2184,10 @@ R:      NXP Linux Team <linux-imx@nxp.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
-X:     drivers/media/i2c/
 F:     arch/arm64/boot/dts/freescale/
 X:     arch/arm64/boot/dts/freescale/fsl-*
 X:     arch/arm64/boot/dts/freescale/qoriq-*
+X:     drivers/media/i2c/
 N:     imx
 N:     mxs
 
@@ -2245,12 +2241,12 @@ ARM/HPE GXP ARCHITECTURE
 M:     Jean-Marie Verdun <verdun@hpe.com>
 M:     Nick Hawkins <nick.hawkins@hpe.com>
 S:     Maintained
-F:     Documentation/hwmon/gxp-fan-ctrl.rst
 F:     Documentation/devicetree/bindings/arm/hpe,gxp.yaml
 F:     Documentation/devicetree/bindings/hwmon/hpe,gxp-fan-ctrl.yaml
 F:     Documentation/devicetree/bindings/i2c/hpe,gxp-i2c.yaml
 F:     Documentation/devicetree/bindings/spi/hpe,gxp-spifi.yaml
 F:     Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml
+F:     Documentation/hwmon/gxp-fan-ctrl.rst
 F:     arch/arm/boot/dts/hpe-bmc*
 F:     arch/arm/boot/dts/hpe-gxp*
 F:     arch/arm/mach-hpe/
@@ -2275,9 +2271,9 @@ M:        Krzysztof Halasa <khalasa@piap.pl>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
-F:     Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion*
 F:     Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
 F:     Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
+F:     Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion*
 F:     Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml
 F:     arch/arm/boot/dts/intel-ixp*
 F:     arch/arm/mach-ixp4xx/
@@ -2434,6 +2430,15 @@ X:       drivers/net/wireless/atmel/
 N:     at91
 N:     atmel
 
+ARM/MICROCHIP (ARM64) SoC support
+M:     Conor Dooley <conor@kernel.org>
+M:     Nicolas Ferre <nicolas.ferre@microchip.com>
+M:     Claudiu Beznea <claudiu.beznea@microchip.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Supported
+T:     git https://git.kernel.org/pub/scm/linux/kernel/git/at91/linux.git
+F:     arch/arm64/boot/dts/microchip/
+
 ARM/Microchip Sparx5 SoC support
 M:     Lars Povlsen <lars.povlsen@microchip.com>
 M:     Steen Hegelund <Steen.Hegelund@microchip.com>
@@ -2441,22 +2446,14 @@ M:      Daniel Machon <daniel.machon@microchip.com>
 M:     UNGLinuxDriver@microchip.com
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
-T:     git git://github.com/microchip-ung/linux-upstream.git
-F:     arch/arm64/boot/dts/microchip/
+F:     arch/arm64/boot/dts/microchip/sparx*
 F:     drivers/net/ethernet/microchip/vcap/
 F:     drivers/pinctrl/pinctrl-microchip-sgpio.c
 N:     sparx5
 
-Microchip Timer Counter Block (TCB) Capture Driver
-M:     Kamel Bouhara <kamel.bouhara@bootlin.com>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-L:     linux-iio@vger.kernel.org
-S:     Maintained
-F:     drivers/counter/microchip-tcb-capture.c
-
-ARM/MILBEAUT ARCHITECTURE
-M:     Taichi Sugaya <sugaya.taichi@socionext.com>
-M:     Takao Orito <orito.takao@socionext.com>
+ARM/MILBEAUT ARCHITECTURE
+M:     Taichi Sugaya <sugaya.taichi@socionext.com>
+M:     Takao Orito <orito.takao@socionext.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/boot/dts/milbeaut*
@@ -2525,8 +2522,8 @@ F:        Documentation/devicetree/bindings/rtc/nuvoton,nct3018y.yaml
 F:     arch/arm/boot/dts/nuvoton-npcm*
 F:     arch/arm/mach-npcm/
 F:     arch/arm64/boot/dts/nuvoton/
-F:     drivers/*/*npcm*
 F:     drivers/*/*/*npcm*
+F:     drivers/*/*npcm*
 F:     drivers/rtc/rtc-nct3018y.c
 F:     include/dt-bindings/clock/nuvoton,npcm7xx-clock.h
 F:     include/dt-bindings/clock/nuvoton,npcm845-clk.h
@@ -2569,6 +2566,12 @@ F:       arch/arm/mach-oxnas/
 F:     drivers/power/reset/oxnas-restart.c
 N:     oxnas
 
+ARM/QUALCOMM CHROMEBOOK SUPPORT
+R:     cros-qcom-dts-watchers@chromium.org
+F:     arch/arm64/boot/dts/qcom/sc7180*
+F:     arch/arm64/boot/dts/qcom/sc7280*
+F:     arch/arm64/boot/dts/qcom/sdm845-cheza*
+
 ARM/QUALCOMM SUPPORT
 M:     Andy Gross <agross@kernel.org>
 M:     Bjorn Andersson <andersson@kernel.org>
@@ -2602,22 +2605,16 @@ F:      drivers/pci/controller/dwc/pcie-qcom.c
 F:     drivers/phy/qualcomm/
 F:     drivers/power/*/msm*
 F:     drivers/reset/reset-qcom-*
-F:     drivers/ufs/host/ufs-qcom*
 F:     drivers/spi/spi-geni-qcom.c
 F:     drivers/spi/spi-qcom-qspi.c
 F:     drivers/spi/spi-qup.c
 F:     drivers/tty/serial/msm_serial.c
+F:     drivers/ufs/host/ufs-qcom*
 F:     drivers/usb/dwc3/dwc3-qcom.c
 F:     include/dt-bindings/*/qcom*
 F:     include/linux/*/qcom*
 F:     include/linux/soc/qcom/
 
-ARM/QUALCOMM CHROMEBOOK SUPPORT
-R:     cros-qcom-dts-watchers@chromium.org
-F:     arch/arm64/boot/dts/qcom/sc7180*
-F:     arch/arm64/boot/dts/qcom/sc7280*
-F:     arch/arm64/boot/dts/qcom/sdm845-cheza*
-
 ARM/RDA MICRO ARCHITECTURE
 M:     Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -2709,9 +2706,9 @@ R:        Alim Akhtar <alim.akhtar@samsung.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-samsung-soc@vger.kernel.org
 S:     Maintained
-C:     irc://irc.libera.chat/linux-exynos
 Q:     https://patchwork.kernel.org/project/linux-samsung-soc/list/
 B:     mailto:linux-samsung-soc@vger.kernel.org
+C:     irc://irc.libera.chat/linux-exynos
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git
 F:     Documentation/arm/samsung/
 F:     Documentation/devicetree/bindings/arm/samsung/
@@ -2811,8 +2808,8 @@ M:        Patrice Chotard <patrice.chotard@foss.st.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 W:     http://www.stlinux.com
-F:     Documentation/devicetree/bindings/spi/st,ssc-spi.yaml
 F:     Documentation/devicetree/bindings/i2c/st,sti-i2c.yaml
+F:     Documentation/devicetree/bindings/spi/st,ssc-spi.yaml
 F:     arch/arm/boot/dts/sti*
 F:     arch/arm/mach-sti/
 F:     drivers/ata/ahci_st.c
@@ -2959,15 +2956,15 @@ T:      git git://git.kernel.org/pub/scm/linux/kernel/git/iwamatsu/linux-visconti.git
 F:     Documentation/devicetree/bindings/arm/toshiba.yaml
 F:     Documentation/devicetree/bindings/clock/toshiba,tmpv770x-pipllct.yaml
 F:     Documentation/devicetree/bindings/clock/toshiba,tmpv770x-pismu.yaml
-F:     Documentation/devicetree/bindings/net/toshiba,visconti-dwmac.yaml
 F:     Documentation/devicetree/bindings/gpio/toshiba,gpio-visconti.yaml
+F:     Documentation/devicetree/bindings/net/toshiba,visconti-dwmac.yaml
 F:     Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml
 F:     Documentation/devicetree/bindings/pinctrl/toshiba,visconti-pinctrl.yaml
 F:     Documentation/devicetree/bindings/watchdog/toshiba,visconti-wdt.yaml
 F:     arch/arm64/boot/dts/toshiba/
 F:     drivers/clk/visconti/
-F:     drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
 F:     drivers/gpio/gpio-visconti.c
+F:     drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
 F:     drivers/pci/controller/dwc/pcie-visconti.c
 F:     drivers/pinctrl/visconti/
 F:     drivers/watchdog/visconti_wdt.c
@@ -3112,6 +3109,13 @@ S:       Maintained
 F:     Documentation/devicetree/bindings/net/asix,ax88796c.yaml
 F:     drivers/net/ethernet/asix/ax88796c_*
 
+ASPEED CRYPTO DRIVER
+M:     Neal Liu <neal_liu@aspeedtech.com>
+L:     linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
+S:     Maintained
+F:     Documentation/devicetree/bindings/crypto/aspeed,*
+F:     drivers/crypto/aspeed/
+
 ASPEED PECI CONTROLLER
 M:     Iwona Winiarska <iwona.winiarska@intel.com>
 L:     linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
@@ -3156,6 +3160,13 @@ S:       Maintained
 F:     Documentation/devicetree/bindings/spi/aspeed,ast2600-fmc.yaml
 F:     drivers/spi/spi-aspeed-smc.c
 
+ASPEED USB UDC DRIVER
+M:     Neal Liu <neal_liu@aspeedtech.com>
+L:     linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
+S:     Maintained
+F:     Documentation/devicetree/bindings/usb/aspeed,ast2600-udc.yaml
+F:     drivers/usb/gadget/udc/aspeed_udc.c
+
 ASPEED VIDEO ENGINE DRIVER
 M:     Eddie James <eajames@linux.ibm.com>
 L:     linux-media@vger.kernel.org
@@ -3164,19 +3175,11 @@ S:      Maintained
 F:     Documentation/devicetree/bindings/media/aspeed-video.txt
 F:     drivers/media/platform/aspeed/
 
-ASPEED USB UDC DRIVER
-M:     Neal Liu <neal_liu@aspeedtech.com>
-L:     linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
-S:     Maintained
-F:     Documentation/devicetree/bindings/usb/aspeed,ast2600-udc.yaml
-F:     drivers/usb/gadget/udc/aspeed_udc.c
-
-ASPEED CRYPTO DRIVER
-M:     Neal Liu <neal_liu@aspeedtech.com>
-L:     linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
+ASUS EC HARDWARE MONITOR DRIVER
+M:     Eugene Shalygin <eugene.shalygin@gmail.com>
+L:     linux-hwmon@vger.kernel.org
 S:     Maintained
-F:     Documentation/devicetree/bindings/crypto/aspeed,*
-F:     drivers/crypto/aspeed/
+F:     drivers/hwmon/asus-ec-sensors.c
 
 ASUS NOTEBOOKS AND EEEPC ACPI/WMI EXTRAS DRIVERS
 M:     Corentin Chary <corentin.chary@gmail.com>
@@ -3194,6 +3197,12 @@ S:       Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git
 F:     drivers/platform/x86/asus-tf103c-dock.c
 
+ASUS WIRELESS RADIO CONTROL DRIVER
+M:     João Paulo Rechi Vita <jprvita@gmail.com>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     drivers/platform/x86/asus-wireless.c
+
 ASUS WMI HARDWARE MONITOR DRIVER
 M:     Ed Brindley <kernel@maidavale.org>
 M:     Denis Pauk <pauk.denis@gmail.com>
@@ -3201,18 +3210,6 @@ L:       linux-hwmon@vger.kernel.org
 S:     Maintained
 F:     drivers/hwmon/asus_wmi_sensors.c
 
-ASUS EC HARDWARE MONITOR DRIVER
-M:     Eugene Shalygin <eugene.shalygin@gmail.com>
-L:     linux-hwmon@vger.kernel.org
-S:     Maintained
-F:     drivers/hwmon/asus-ec-sensors.c
-
-ASUS WIRELESS RADIO CONTROL DRIVER
-M:     João Paulo Rechi Vita <jprvita@gmail.com>
-L:     platform-driver-x86@vger.kernel.org
-S:     Maintained
-F:     drivers/platform/x86/asus-wireless.c
-
 ASYMMETRIC KEYS
 M:     David Howells <dhowells@redhat.com>
 L:     keyrings@vger.kernel.org
@@ -3352,10 +3349,10 @@ R:      Boqun Feng <boqun.feng@gmail.com>
 R:     Mark Rutland <mark.rutland@arm.com>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
+F:     Documentation/atomic_*.txt
 F:     arch/*/include/asm/atomic*.h
 F:     include/*/atomic*.h
 F:     include/linux/refcount.h
-F:     Documentation/atomic_*.txt
 F:     scripts/atomic/
 
 ATTO EXPRESSSAS SAS/SATA RAID SCSI DRIVER
@@ -3548,7 +3545,7 @@ F:        Documentation/filesystems/befs.rst
 F:     fs/befs/
 
 BFQ I/O SCHEDULER
-M:     Paolo Valente <paolo.valente@linaro.org>
+M:     Paolo Valente <paolo.valente@unimore.it>
 M:     Jens Axboe <axboe@kernel.dk>
 L:     linux-block@vger.kernel.org
 S:     Maintained
@@ -3649,50 +3646,6 @@ S:       Maintained
 F:     Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml
 F:     drivers/iio/accel/bma400*
 
-BPF [GENERAL] (Safe Dynamic Programs and Tools)
-M:     Alexei Starovoitov <ast@kernel.org>
-M:     Daniel Borkmann <daniel@iogearbox.net>
-M:     Andrii Nakryiko <andrii@kernel.org>
-R:     Martin KaFai Lau <martin.lau@linux.dev>
-R:     Song Liu <song@kernel.org>
-R:     Yonghong Song <yhs@fb.com>
-R:     John Fastabend <john.fastabend@gmail.com>
-R:     KP Singh <kpsingh@kernel.org>
-R:     Stanislav Fomichev <sdf@google.com>
-R:     Hao Luo <haoluo@google.com>
-R:     Jiri Olsa <jolsa@kernel.org>
-L:     bpf@vger.kernel.org
-S:     Supported
-W:     https://bpf.io/
-Q:     https://patchwork.kernel.org/project/netdevbpf/list/?delegate=121173
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
-F:     Documentation/bpf/
-F:     Documentation/networking/filter.rst
-F:     Documentation/userspace-api/ebpf/
-F:     arch/*/net/*
-F:     include/linux/bpf*
-F:     include/linux/btf*
-F:     include/linux/filter.h
-F:     include/trace/events/xdp.h
-F:     include/uapi/linux/bpf*
-F:     include/uapi/linux/btf*
-F:     include/uapi/linux/filter.h
-F:     kernel/bpf/
-F:     kernel/trace/bpf_trace.c
-F:     lib/test_bpf.c
-F:     net/bpf/
-F:     net/core/filter.c
-F:     net/sched/act_bpf.c
-F:     net/sched/cls_bpf.c
-F:     samples/bpf/
-F:     scripts/bpf_doc.py
-F:     scripts/pahole-flags.sh
-F:     scripts/pahole-version.sh
-F:     tools/bpf/
-F:     tools/lib/bpf/
-F:     tools/testing/selftests/bpf/
-
 BPF JIT for ARM
 M:     Shubham Bansal <illusionist.neo@gmail.com>
 L:     bpf@vger.kernel.org
@@ -3771,79 +3724,79 @@ S:      Supported
 F:     arch/x86/net/
 X:     arch/x86/net/bpf_jit_comp32.c
 
+BPF [BTF]
+M:     Martin KaFai Lau <martin.lau@linux.dev>
+L:     bpf@vger.kernel.org
+S:     Maintained
+F:     include/linux/btf*
+F:     kernel/bpf/btf.c
+
 BPF [CORE]
 M:     Alexei Starovoitov <ast@kernel.org>
 M:     Daniel Borkmann <daniel@iogearbox.net>
 R:     John Fastabend <john.fastabend@gmail.com>
 L:     bpf@vger.kernel.org
 S:     Maintained
-F:     kernel/bpf/verifier.c
-F:     kernel/bpf/tnum.c
-F:     kernel/bpf/core.c
-F:     kernel/bpf/syscall.c
-F:     kernel/bpf/dispatcher.c
-F:     kernel/bpf/trampoline.c
 F:     include/linux/bpf*
 F:     include/linux/filter.h
 F:     include/linux/tnum.h
+F:     kernel/bpf/core.c
+F:     kernel/bpf/dispatcher.c
+F:     kernel/bpf/syscall.c
+F:     kernel/bpf/tnum.c
+F:     kernel/bpf/trampoline.c
+F:     kernel/bpf/verifier.c
 
-BPF [BTF]
-M:     Martin KaFai Lau <martin.lau@linux.dev>
-L:     bpf@vger.kernel.org
-S:     Maintained
-F:     kernel/bpf/btf.c
-F:     include/linux/btf*
-
-BPF [TRACING]
-M:     Song Liu <song@kernel.org>
-R:     Jiri Olsa <jolsa@kernel.org>
+BPF [DOCUMENTATION] (Related to Standardization)
+R:     David Vernet <void@manifault.com>
 L:     bpf@vger.kernel.org
+L:     bpf@ietf.org
 S:     Maintained
-F:     kernel/trace/bpf_trace.c
-F:     kernel/bpf/stackmap.c
+F:     Documentation/bpf/instruction-set.rst
 
-BPF [NETWORKING] (tc BPF, sock_addr)
-M:     Martin KaFai Lau <martin.lau@linux.dev>
+BPF [GENERAL] (Safe Dynamic Programs and Tools)
+M:     Alexei Starovoitov <ast@kernel.org>
 M:     Daniel Borkmann <daniel@iogearbox.net>
+M:     Andrii Nakryiko <andrii@kernel.org>
+R:     Martin KaFai Lau <martin.lau@linux.dev>
+R:     Song Liu <song@kernel.org>
+R:     Yonghong Song <yhs@fb.com>
 R:     John Fastabend <john.fastabend@gmail.com>
+R:     KP Singh <kpsingh@kernel.org>
+R:     Stanislav Fomichev <sdf@google.com>
+R:     Hao Luo <haoluo@google.com>
+R:     Jiri Olsa <jolsa@kernel.org>
 L:     bpf@vger.kernel.org
-L:     netdev@vger.kernel.org
-S:     Maintained
+S:     Supported
+W:     https://bpf.io/
+Q:     https://patchwork.kernel.org/project/netdevbpf/list/?delegate=121173
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
+F:     Documentation/bpf/
+F:     Documentation/networking/filter.rst
+F:     Documentation/userspace-api/ebpf/
+F:     arch/*/net/*
+F:     include/linux/bpf*
+F:     include/linux/btf*
+F:     include/linux/filter.h
+F:     include/trace/events/xdp.h
+F:     include/uapi/linux/bpf*
+F:     include/uapi/linux/btf*
+F:     include/uapi/linux/filter.h
+F:     kernel/bpf/
+F:     kernel/trace/bpf_trace.c
+F:     lib/test_bpf.c
+F:     net/bpf/
 F:     net/core/filter.c
 F:     net/sched/act_bpf.c
 F:     net/sched/cls_bpf.c
-
-BPF [NETWORKING] (struct_ops, reuseport)
-M:     Martin KaFai Lau <martin.lau@linux.dev>
-L:     bpf@vger.kernel.org
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     kernel/bpf/bpf_struct*
-
-BPF [SECURITY & LSM] (Security Audit and Enforcement using BPF)
-M:     KP Singh <kpsingh@kernel.org>
-R:     Florent Revest <revest@chromium.org>
-R:     Brendan Jackman <jackmanb@chromium.org>
-L:     bpf@vger.kernel.org
-S:     Maintained
-F:     Documentation/bpf/prog_lsm.rst
-F:     include/linux/bpf_lsm.h
-F:     kernel/bpf/bpf_lsm.c
-F:     security/bpf/
-
-BPF [STORAGE & CGROUPS]
-M:     Martin KaFai Lau <martin.lau@linux.dev>
-L:     bpf@vger.kernel.org
-S:     Maintained
-F:     kernel/bpf/cgroup.c
-F:     kernel/bpf/*storage.c
-F:     kernel/bpf/bpf_lru*
-
-BPF [RINGBUF]
-M:     Andrii Nakryiko <andrii@kernel.org>
-L:     bpf@vger.kernel.org
-S:     Maintained
-F:     kernel/bpf/ringbuf.c
+F:     samples/bpf/
+F:     scripts/bpf_doc.py
+F:     scripts/pahole-flags.sh
+F:     scripts/pahole-version.sh
+F:     tools/bpf/
+F:     tools/lib/bpf/
+F:     tools/testing/selftests/bpf/
 
 BPF [ITERATOR]
 M:     Yonghong Song <yhs@fb.com>
@@ -3870,12 +3823,45 @@ L:      bpf@vger.kernel.org
 S:     Maintained
 F:     tools/lib/bpf/
 
-BPF [TOOLING] (bpftool)
-M:     Quentin Monnet <quentin@isovalent.com>
+BPF [MISC]
+L:     bpf@vger.kernel.org
+S:     Odd Fixes
+K:     (?:\b|_)bpf(?:\b|_)
+
+BPF [NETWORKING] (struct_ops, reuseport)
+M:     Martin KaFai Lau <martin.lau@linux.dev>
+L:     bpf@vger.kernel.org
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     kernel/bpf/bpf_struct*
+
+BPF [NETWORKING] (tc BPF, sock_addr)
+M:     Martin KaFai Lau <martin.lau@linux.dev>
+M:     Daniel Borkmann <daniel@iogearbox.net>
+R:     John Fastabend <john.fastabend@gmail.com>
+L:     bpf@vger.kernel.org
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     net/core/filter.c
+F:     net/sched/act_bpf.c
+F:     net/sched/cls_bpf.c
+
+BPF [RINGBUF]
+M:     Andrii Nakryiko <andrii@kernel.org>
+L:     bpf@vger.kernel.org
+S:     Maintained
+F:     kernel/bpf/ringbuf.c
+
+BPF [SECURITY & LSM] (Security Audit and Enforcement using BPF)
+M:     KP Singh <kpsingh@kernel.org>
+R:     Florent Revest <revest@chromium.org>
+R:     Brendan Jackman <jackmanb@chromium.org>
 L:     bpf@vger.kernel.org
 S:     Maintained
-F:     kernel/bpf/disasm.*
-F:     tools/bpf/bpftool/
+F:     Documentation/bpf/prog_lsm.rst
+F:     include/linux/bpf_lsm.h
+F:     kernel/bpf/bpf_lsm.c
+F:     security/bpf/
 
 BPF [SELFTESTS] (Test Runners & Infrastructure)
 M:     Andrii Nakryiko <andrii@kernel.org>
@@ -3884,17 +3870,28 @@ L:      bpf@vger.kernel.org
 S:     Maintained
 F:     tools/testing/selftests/bpf/
 
-BPF [DOCUMENTATION] (Related to Standardization)
-R:     David Vernet <void@manifault.com>
+BPF [STORAGE & CGROUPS]
+M:     Martin KaFai Lau <martin.lau@linux.dev>
 L:     bpf@vger.kernel.org
-L:     bpf@ietf.org
 S:     Maintained
-F:     Documentation/bpf/instruction-set.rst
+F:     kernel/bpf/*storage.c
+F:     kernel/bpf/bpf_lru*
+F:     kernel/bpf/cgroup.c
 
-BPF [MISC]
+BPF [TOOLING] (bpftool)
+M:     Quentin Monnet <quentin@isovalent.com>
 L:     bpf@vger.kernel.org
-S:     Odd Fixes
-K:     (?:\b|_)bpf(?:\b|_)
+S:     Maintained
+F:     kernel/bpf/disasm.*
+F:     tools/bpf/bpftool/
+
+BPF [TRACING]
+M:     Song Liu <song@kernel.org>
+R:     Jiri Olsa <jolsa@kernel.org>
+L:     bpf@vger.kernel.org
+S:     Maintained
+F:     kernel/bpf/stackmap.c
+F:     kernel/trace/bpf_trace.c
 
 BROADCOM B44 10/100 ETHERNET DRIVER
 M:     Michael Chan <michael.chan@broadcom.com>
@@ -3913,34 +3910,6 @@ F:       drivers/net/dsa/bcm_sf2*
 F:     include/linux/dsa/brcm.h
 F:     include/linux/platform_data/b53.h
 
-BROADCOM BCMBCA ARM ARCHITECTURE
-M:     William Zhang <william.zhang@broadcom.com>
-M:     Anand Gore <anand.gore@broadcom.com>
-M:     Kursad Oney <kursad.oney@broadcom.com>
-M:     Florian Fainelli <f.fainelli@gmail.com>
-M:     RafaÅ‚ MiÅ‚ecki <rafal@milecki.pl>
-R:     Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     Maintained
-T:     git https://github.com/broadcom/stblinux.git
-F:     Documentation/devicetree/bindings/arm/bcm/brcm,bcmbca.yaml
-F:     arch/arm64/boot/dts/broadcom/bcmbca/*
-N:     bcmbca
-N:     bcm[9]?47622
-N:     bcm[9]?4912
-N:     bcm[9]?63138
-N:     bcm[9]?63146
-N:     bcm[9]?63148
-N:     bcm[9]?63158
-N:     bcm[9]?63178
-N:     bcm[9]?6756
-N:     bcm[9]?6813
-N:     bcm[9]?6846
-N:     bcm[9]?6855
-N:     bcm[9]?6856
-N:     bcm[9]?6858
-N:     bcm[9]?6878
-
 BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE
 M:     Florian Fainelli <f.fainelli@gmail.com>
 R:     Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
@@ -4038,11 +4007,39 @@ N:      brcmstb
 N:     bcm7038
 N:     bcm7120
 
+BROADCOM BCMBCA ARM ARCHITECTURE
+M:     William Zhang <william.zhang@broadcom.com>
+M:     Anand Gore <anand.gore@broadcom.com>
+M:     Kursad Oney <kursad.oney@broadcom.com>
+M:     Florian Fainelli <f.fainelli@gmail.com>
+M:     RafaÅ‚ MiÅ‚ecki <rafal@milecki.pl>
+R:     Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+T:     git https://github.com/broadcom/stblinux.git
+F:     Documentation/devicetree/bindings/arm/bcm/brcm,bcmbca.yaml
+F:     arch/arm64/boot/dts/broadcom/bcmbca/*
+N:     bcmbca
+N:     bcm[9]?47622
+N:     bcm[9]?4912
+N:     bcm[9]?63138
+N:     bcm[9]?63146
+N:     bcm[9]?63148
+N:     bcm[9]?63158
+N:     bcm[9]?63178
+N:     bcm[9]?6756
+N:     bcm[9]?6813
+N:     bcm[9]?6846
+N:     bcm[9]?6855
+N:     bcm[9]?6856
+N:     bcm[9]?6858
+N:     bcm[9]?6878
+
 BROADCOM BDC DRIVER
 M:     Justin Chen <justinpopo6@gmail.com>
 M:     Al Cooper <alcooperx@gmail.com>
-L:     linux-usb@vger.kernel.org
 R:     Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
+L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/usb/brcm,bdc.yaml
 F:     drivers/usb/gadget/udc/bdc/
@@ -4064,10 +4061,10 @@ F:      arch/mips/bmips/*
 F:     arch/mips/boot/dts/brcm/bcm*.dts*
 F:     arch/mips/include/asm/mach-bmips/*
 F:     arch/mips/kernel/*bmips*
-F:     drivers/soc/bcm/bcm63xx
 F:     drivers/irqchip/irq-bcm63*
 F:     drivers/irqchip/irq-bcm7*
 F:     drivers/irqchip/irq-brcmstb*
+F:     drivers/soc/bcm/bcm63xx
 F:     include/linux/bcm963xx_nvram.h
 F:     include/linux/bcm963xx_tag.h
 
@@ -4349,9 +4346,9 @@ M:        Florian Fainelli <f.fainelli@gmail.com>
 R:     Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
 L:     netdev@vger.kernel.org
 S:     Supported
+F:     Documentation/devicetree/bindings/net/brcm,systemport.yaml
 F:     drivers/net/ethernet/broadcom/bcmsysport.*
 F:     drivers/net/ethernet/broadcom/unimac.h
-F:     Documentation/devicetree/bindings/net/brcm,systemport.yaml
 
 BROADCOM TG3 GIGABIT ETHERNET DRIVER
 M:     Siva Reddy Kallam <siva.kallam@broadcom.com>
@@ -4483,29 +4480,6 @@ W:       https://github.com/Cascoda/ca8210-linux.git
 F:     Documentation/devicetree/bindings/net/ieee802154/ca8210.txt
 F:     drivers/net/ieee802154/ca8210.c
 
-CANAAN/KENDRYTE K210 SOC FPIOA DRIVER
-M:     Damien Le Moal <dlemoal@kernel.org>
-L:     linux-riscv@lists.infradead.org
-L:     linux-gpio@vger.kernel.org (pinctrl driver)
-F:     Documentation/devicetree/bindings/pinctrl/canaan,k210-fpioa.yaml
-F:     drivers/pinctrl/pinctrl-k210.c
-
-CANAAN/KENDRYTE K210 SOC RESET CONTROLLER DRIVER
-M:     Damien Le Moal <dlemoal@kernel.org>
-L:     linux-kernel@vger.kernel.org
-L:     linux-riscv@lists.infradead.org
-S:     Maintained
-F:     Documentation/devicetree/bindings/reset/canaan,k210-rst.yaml
-F:     drivers/reset/reset-k210.c
-
-CANAAN/KENDRYTE K210 SOC SYSTEM CONTROLLER DRIVER
-M:     Damien Le Moal <dlemoal@kernel.org>
-L:     linux-riscv@lists.infradead.org
-S:     Maintained
-F:      Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml
-F:     drivers/soc/canaan/
-F:     include/soc/canaan/
-
 CACHEFILES: FS-CACHE BACKEND FOR CACHING ON MOUNTED FILESYSTEMS
 M:     David Howells <dhowells@redhat.com>
 L:     linux-cachefs@redhat.com (moderated for non-subscribers)
@@ -4627,6 +4601,29 @@ F:       Documentation/networking/j1939.rst
 F:     include/uapi/linux/can/j1939.h
 F:     net/can/j1939/
 
+CANAAN/KENDRYTE K210 SOC FPIOA DRIVER
+M:     Damien Le Moal <dlemoal@kernel.org>
+L:     linux-riscv@lists.infradead.org
+L:     linux-gpio@vger.kernel.org (pinctrl driver)
+F:     Documentation/devicetree/bindings/pinctrl/canaan,k210-fpioa.yaml
+F:     drivers/pinctrl/pinctrl-k210.c
+
+CANAAN/KENDRYTE K210 SOC RESET CONTROLLER DRIVER
+M:     Damien Le Moal <dlemoal@kernel.org>
+L:     linux-kernel@vger.kernel.org
+L:     linux-riscv@lists.infradead.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/reset/canaan,k210-rst.yaml
+F:     drivers/reset/reset-k210.c
+
+CANAAN/KENDRYTE K210 SOC SYSTEM CONTROLLER DRIVER
+M:     Damien Le Moal <dlemoal@kernel.org>
+L:     linux-riscv@lists.infradead.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml
+F:     drivers/soc/canaan/
+F:     include/soc/canaan/
+
 CAPABILITIES
 M:     Serge Hallyn <serge@hallyn.com>
 L:     linux-security-module@vger.kernel.org
@@ -4686,8 +4683,8 @@ F:        arch/arm64/boot/dts/cavium/thunder2-99xx*
 
 CBS/ETF/TAPRIO QDISCS
 M:     Vinicius Costa Gomes <vinicius.gomes@intel.com>
-S:     Maintained
 L:     netdev@vger.kernel.org
+S:     Maintained
 F:     net/sched/sch_cbs.c
 F:     net/sched/sch_etf.c
 F:     net/sched/sch_taprio.c
@@ -4710,10 +4707,10 @@ CCTRNG ARM TRUSTZONE CRYPTOCELL TRUE RANDOM NUMBER GENERATOR (TRNG) DRIVER
 M:     Hadar Gat <hadar.gat@arm.com>
 L:     linux-crypto@vger.kernel.org
 S:     Supported
+W:     https://developer.arm.com/products/system-ip/trustzone-cryptocell/cryptocell-700-family
+F:     Documentation/devicetree/bindings/rng/arm-cctrng.yaml
 F:     drivers/char/hw_random/cctrng.c
 F:     drivers/char/hw_random/cctrng.h
-F:     Documentation/devicetree/bindings/rng/arm-cctrng.yaml
-W:     https://developer.arm.com/products/system-ip/trustzone-cryptocell/cryptocell-700-family
 
 CEC FRAMEWORK
 M:     Hans Verkuil <hverkuil-cisco@xs4all.nl>
@@ -4873,13 +4870,6 @@ S:       Maintained
 F:     Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml
 F:     sound/soc/codecs/cros_ec_codec.*
 
-CHROMEOS EC UART DRIVER
-M:     Bhanu Prakash Maiya <bhanumaiya@chromium.org>
-R:     Benson Leung <bleung@chromium.org>
-R:     Tzung-Bi Shih <tzungbi@kernel.org>
-S:     Maintained
-F:     drivers/platform/chrome/cros_ec_uart.c
-
 CHROMEOS EC SUBDRIVERS
 M:     Benson Leung <bleung@chromium.org>
 R:     Guenter Roeck <groeck@chromium.org>
@@ -4889,13 +4879,12 @@ F:      drivers/power/supply/cros_usbpd-charger.c
 N:     cros_ec
 N:     cros-ec
 
-CHROMEOS EC USB TYPE-C DRIVER
-M:     Prashant Malani <pmalani@chromium.org>
-L:     chrome-platform@lists.linux.dev
+CHROMEOS EC UART DRIVER
+M:     Bhanu Prakash Maiya <bhanumaiya@chromium.org>
+R:     Benson Leung <bleung@chromium.org>
+R:     Tzung-Bi Shih <tzungbi@kernel.org>
 S:     Maintained
-F:     drivers/platform/chrome/cros_ec_typec.*
-F:     drivers/platform/chrome/cros_typec_switch.c
-F:     drivers/platform/chrome/cros_typec_vdm.*
+F:     drivers/platform/chrome/cros_ec_uart.c
 
 CHROMEOS EC USB PD NOTIFY DRIVER
 M:     Prashant Malani <pmalani@chromium.org>
@@ -4904,6 +4893,14 @@ S:       Maintained
 F:     drivers/platform/chrome/cros_usbpd_notify.c
 F:     include/linux/platform_data/cros_usbpd_notify.h
 
+CHROMEOS EC USB TYPE-C DRIVER
+M:     Prashant Malani <pmalani@chromium.org>
+L:     chrome-platform@lists.linux.dev
+S:     Maintained
+F:     drivers/platform/chrome/cros_ec_typec.*
+F:     drivers/platform/chrome/cros_typec_switch.c
+F:     drivers/platform/chrome/cros_typec_vdm.*
+
 CHROMEOS HPS DRIVER
 M:     Dan Callaghan <dcallagh@chromium.org>
 R:     Sami Kyöstilä <skyostil@chromium.org>
@@ -4921,7 +4918,6 @@ F:        drivers/media/cec/i2c/ch7322.c
 CIRRUS LOGIC AUDIO CODEC DRIVERS
 M:     James Schulman <james.schulman@cirrus.com>
 M:     David Rhodes <david.rhodes@cirrus.com>
-M:     Lucas Tanure <tanureal@opensource.cirrus.com>
 M:     Richard Fitzgerald <rf@opensource.cirrus.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 L:     patches@opensource.cirrus.com
@@ -5021,6 +5017,18 @@ M:       Nelson Escobar <neescoba@cisco.com>
 S:     Supported
 F:     drivers/infiniband/hw/usnic/
 
+CLANG CONTROL FLOW INTEGRITY SUPPORT
+M:     Sami Tolvanen <samitolvanen@google.com>
+M:     Kees Cook <keescook@chromium.org>
+R:     Nathan Chancellor <nathan@kernel.org>
+R:     Nick Desaulniers <ndesaulniers@google.com>
+L:     llvm@lists.linux.dev
+S:     Supported
+B:     https://github.com/ClangBuiltLinux/linux/issues
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
+F:     include/linux/cfi.h
+F:     kernel/cfi.c
+
 CLANG-FORMAT FILE
 M:     Miguel Ojeda <ojeda@kernel.org>
 S:     Maintained
@@ -5041,18 +5049,6 @@ F:       scripts/Makefile.clang
 F:     scripts/clang-tools/
 K:     \b(?i:clang|llvm)\b
 
-CLANG CONTROL FLOW INTEGRITY SUPPORT
-M:     Sami Tolvanen <samitolvanen@google.com>
-M:     Kees Cook <keescook@chromium.org>
-R:     Nathan Chancellor <nathan@kernel.org>
-R:     Nick Desaulniers <ndesaulniers@google.com>
-L:     llvm@lists.linux.dev
-S:     Supported
-B:     https://github.com/ClangBuiltLinux/linux/issues
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
-F:     include/linux/cfi.h
-F:     kernel/cfi.c
-
 CLK API
 M:     Russell King <linux@armlinux.org.uk>
 L:     linux-clk@vger.kernel.org
@@ -5143,7 +5139,7 @@ X:        drivers/clk/clkdev.c
 
 COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3)
 M:     Steve French <sfrench@samba.org>
-R:     Paulo Alcantara <pc@cjr.nz> (DFS, global name space)
+R:     Paulo Alcantara <pc@manguebit.com> (DFS, global name space)
 R:     Ronnie Sahlberg <lsahlber@redhat.com> (directory leases, sparse files)
 R:     Shyam Prasad N <sprasad@microsoft.com> (multichannel)
 R:     Tom Talpey <tom@talpey.com> (RDMA, smbdirect)
@@ -5153,8 +5149,8 @@ S:        Supported
 W:     https://wiki.samba.org/index.php/LinuxCIFS
 T:     git git://git.samba.org/sfrench/cifs-2.6.git
 F:     Documentation/admin-guide/cifs/
-F:     fs/cifs/
-F:     fs/smbfs_common/
+F:     fs/smb/client/
+F:     fs/smb/common/
 F:     include/uapi/linux/cifs
 
 COMPACTPCI HOTPLUG CORE
@@ -5223,8 +5219,8 @@ CONTEXT TRACKING
 M:     Frederic Weisbecker <frederic@kernel.org>
 M:     "Paul E. McKenney" <paulmck@kernel.org>
 S:     Maintained
-F:     kernel/context_tracking.c
 F:     include/linux/context_tracking*
+F:     kernel/context_tracking.c
 
 CONTROL GROUP (CGROUP)
 M:     Tejun Heo <tj@kernel.org>
@@ -5385,8 +5381,8 @@ F:        drivers/cpuidle/cpuidle-big_little.c
 
 CPUIDLE DRIVER - ARM EXYNOS
 M:     Daniel Lezcano <daniel.lezcano@linaro.org>
-R:     Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
 M:     Kukjin Kim <kgene@kernel.org>
+R:     Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
 L:     linux-pm@vger.kernel.org
 L:     linux-samsung-soc@vger.kernel.org
 S:     Supported
@@ -5407,8 +5403,8 @@ M:        Ulf Hansson <ulf.hansson@linaro.org>
 L:     linux-pm@vger.kernel.org
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
-F:     drivers/cpuidle/cpuidle-psci.h
 F:     drivers/cpuidle/cpuidle-psci-domain.c
+F:     drivers/cpuidle/cpuidle-psci.h
 
 CPUIDLE DRIVER - DT IDLE PM DOMAIN
 M:     Ulf Hansson <ulf.hansson@linaro.org>
@@ -5552,19 +5548,19 @@ S:      Supported
 W:     http://www.chelsio.com
 F:     drivers/crypto/chelsio
 
-CXGB4 INLINE CRYPTO DRIVER
-M:     Ayush Sawal <ayush.sawal@chelsio.com>
+CXGB4 ETHERNET DRIVER (CXGB4)
+M:     Raju Rangoju <rajur@chelsio.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.chelsio.com
-F:     drivers/net/ethernet/chelsio/inline_crypto/
+F:     drivers/net/ethernet/chelsio/cxgb4/
 
-CXGB4 ETHERNET DRIVER (CXGB4)
-M:     Raju Rangoju <rajur@chelsio.com>
+CXGB4 INLINE CRYPTO DRIVER
+M:     Ayush Sawal <ayush.sawal@chelsio.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.chelsio.com
-F:     drivers/net/ethernet/chelsio/cxgb4/
+F:     drivers/net/ethernet/chelsio/inline_crypto/
 
 CXGB4 ISCSI DRIVER (CXGB4I)
 M:     Varun Prakash <varun@chelsio.com>
@@ -5621,16 +5617,6 @@ CYCLADES PC300 DRIVER
 S:     Orphan
 F:     drivers/net/wan/pc300*
 
-CYPRESS_FIRMWARE MEDIA DRIVER
-M:     Antti Palosaari <crope@iki.fi>
-L:     linux-media@vger.kernel.org
-S:     Maintained
-W:     https://linuxtv.org
-W:     http://palosaari.fi/linux/
-Q:     http://patchwork.linuxtv.org/project/linux-media/list/
-T:     git git://linuxtv.org/anttip/media_tree.git
-F:     drivers/media/common/cypress_firmware*
-
 CYPRESS CY8C95X0 PINCTRL DRIVER
 M:     Patrick Rudolph <patrick.rudolph@9elements.com>
 L:     linux-gpio@vger.kernel.org
@@ -5650,6 +5636,16 @@ S:       Maintained
 F:     Documentation/devicetree/bindings/input/cypress-sf.yaml
 F:     drivers/input/keyboard/cypress-sf.c
 
+CYPRESS_FIRMWARE MEDIA DRIVER
+M:     Antti Palosaari <crope@iki.fi>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+W:     https://linuxtv.org
+W:     http://palosaari.fi/linux/
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+T:     git git://linuxtv.org/anttip/media_tree.git
+F:     drivers/media/common/cypress_firmware*
+
 CYTTSP TOUCHSCREEN DRIVER
 M:     Linus Walleij <linus.walleij@linaro.org>
 L:     linux-input@vger.kernel.org
@@ -5816,11 +5812,6 @@ S:       Maintained
 F:     Documentation/driver-api/dcdbas.rst
 F:     drivers/platform/x86/dell/dcdbas.*
 
-DELL WMI DESCRIPTOR DRIVER
-L:     Dell.Client.Kernel@dell.com
-S:     Maintained
-F:     drivers/platform/x86/dell/dell-wmi-descriptor.c
-
 DELL WMI DDV DRIVER
 M:     Armin Wolf <W_Armin@gmx.de>
 S:     Maintained
@@ -5828,13 +5819,17 @@ F:      Documentation/ABI/testing/debugfs-dell-wmi-ddv
 F:     Documentation/ABI/testing/sysfs-platform-dell-wmi-ddv
 F:     drivers/platform/x86/dell/dell-wmi-ddv.c
 
-DELL WMI SYSMAN DRIVER
-M:     Prasanth Ksr <prasanth.ksr@dell.com>
+DELL WMI DESCRIPTOR DRIVER
+L:     Dell.Client.Kernel@dell.com
+S:     Maintained
+F:     drivers/platform/x86/dell/dell-wmi-descriptor.c
+
+DELL WMI HARDWARE PRIVACY SUPPORT
+M:     Perry Yuan <Perry.Yuan@dell.com>
 L:     Dell.Client.Kernel@dell.com
 L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
-F:     Documentation/ABI/testing/sysfs-class-firmware-attributes
-F:     drivers/platform/x86/dell/dell-wmi-sysman/
+F:     drivers/platform/x86/dell/dell-wmi-privacy.c
 
 DELL WMI NOTIFICATIONS DRIVER
 M:     Matthew Garrett <mjg59@srcf.ucam.org>
@@ -5842,20 +5837,13 @@ M:      Pali Rohár <pali@kernel.org>
 S:     Maintained
 F:     drivers/platform/x86/dell/dell-wmi-base.c
 
-DELL WMI HARDWARE PRIVACY SUPPORT
-M:     Perry Yuan <Perry.Yuan@dell.com>
+DELL WMI SYSMAN DRIVER
+M:     Prasanth Ksr <prasanth.ksr@dell.com>
 L:     Dell.Client.Kernel@dell.com
 L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
-F:     drivers/platform/x86/dell/dell-wmi-privacy.c
-
-DELTA ST MEDIA DRIVER
-M:     Hugues Fruchet <hugues.fruchet@foss.st.com>
-L:     linux-media@vger.kernel.org
-S:     Supported
-W:     https://linuxtv.org
-T:     git git://linuxtv.org/media_tree.git
-F:     drivers/media/platform/st/sti/delta
+F:     Documentation/ABI/testing/sysfs-class-firmware-attributes
+F:     drivers/platform/x86/dell/dell-wmi-sysman/
 
 DELTA AHE-50DC FAN CONTROL MODULE DRIVER
 M:     Zev Weiss <zev@bewilderbeest.net>
@@ -5879,6 +5867,14 @@ F:       Documentation/devicetree/bindings/reset/delta,tn48m-reset.yaml
 F:     drivers/gpio/gpio-tn48m.c
 F:     include/dt-bindings/reset/delta,tn48m-reset.h
 
+DELTA ST MEDIA DRIVER
+M:     Hugues Fruchet <hugues.fruchet@foss.st.com>
+L:     linux-media@vger.kernel.org
+S:     Supported
+W:     https://linuxtv.org
+T:     git git://linuxtv.org/media_tree.git
+F:     drivers/media/platform/st/sti/delta
+
 DENALI NAND DRIVER
 L:     linux-mtd@lists.infradead.org
 S:     Orphan
@@ -5891,13 +5887,6 @@ S:       Maintained
 F:     drivers/dma/dw-edma/
 F:     include/linux/dma/edma.h
 
-DESIGNWARE XDATA IP DRIVER
-M:     Gustavo Pimentel <gustavo.pimentel@synopsys.com>
-L:     linux-pci@vger.kernel.org
-S:     Maintained
-F:     Documentation/misc-devices/dw-xdata-pcie.rst
-F:     drivers/misc/dw-xdata-pcie.c
-
 DESIGNWARE USB2 DRD IP DRIVER
 M:     Minas Harutyunyan <hminas@synopsys.com>
 L:     linux-usb@vger.kernel.org
@@ -5911,6 +5900,13 @@ L:       linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/dwc3/
 
+DESIGNWARE XDATA IP DRIVER
+M:     Gustavo Pimentel <gustavo.pimentel@synopsys.com>
+L:     linux-pci@vger.kernel.org
+S:     Maintained
+F:     Documentation/misc-devices/dw-xdata-pcie.rst
+F:     drivers/misc/dw-xdata-pcie.c
+
 DEVANTECH SRF ULTRASONIC RANGER IIO DRIVER
 M:     Andreas Klinger <ak@it-klinger.de>
 L:     linux-iio@vger.kernel.org
@@ -6019,9 +6015,9 @@ W:        http://www.dialog-semiconductor.com/products
 F:     Documentation/devicetree/bindings/input/da90??-onkey.txt
 F:     Documentation/devicetree/bindings/input/dlg,da72??.txt
 F:     Documentation/devicetree/bindings/mfd/da90*.txt
-F:     Documentation/devicetree/bindings/mfd/da90*.yaml
-F:     Documentation/devicetree/bindings/regulator/dlg,da9*.yaml
+F:     Documentation/devicetree/bindings/mfd/dlg,da90*.yaml
 F:     Documentation/devicetree/bindings/regulator/da92*.txt
+F:     Documentation/devicetree/bindings/regulator/dlg,da9*.yaml
 F:     Documentation/devicetree/bindings/regulator/slg51000.txt
 F:     Documentation/devicetree/bindings/sound/da[79]*.txt
 F:     Documentation/devicetree/bindings/thermal/da90??-thermal.txt
@@ -6140,6 +6136,12 @@ F:       include/linux/dma/
 F:     include/linux/dmaengine.h
 F:     include/linux/of_dma.h
 
+DMA MAPPING BENCHMARK
+M:     Xiang Chen <chenxiang66@hisilicon.com>
+L:     iommu@lists.linux.dev
+F:     kernel/dma/map_benchmark.c
+F:     tools/testing/selftests/dma/
+
 DMA MAPPING HELPERS
 M:     Christoph Hellwig <hch@lst.de>
 M:     Marek Szyprowski <m.szyprowski@samsung.com>
@@ -6150,17 +6152,11 @@ W:      http://git.infradead.org/users/hch/dma-mapping.git
 T:     git git://git.infradead.org/users/hch/dma-mapping.git
 F:     include/asm-generic/dma-mapping.h
 F:     include/linux/dma-direct.h
-F:     include/linux/dma-mapping.h
 F:     include/linux/dma-map-ops.h
+F:     include/linux/dma-mapping.h
 F:     include/linux/swiotlb.h
 F:     kernel/dma/
 
-DMA MAPPING BENCHMARK
-M:     Xiang Chen <chenxiang66@hisilicon.com>
-L:     iommu@lists.linux.dev
-F:     kernel/dma/map_benchmark.c
-F:     tools/testing/selftests/dma/
-
 DMA-BUF HEAPS FRAMEWORK
 M:     Sumit Semwal <sumit.semwal@linaro.org>
 R:     Benjamin Gaignard <benjamin.gaignard@collabora.com>
@@ -6218,6 +6214,7 @@ X:        Documentation/devicetree/
 X:     Documentation/driver-api/media/
 X:     Documentation/firmware-guide/acpi/
 X:     Documentation/i2c/
+X:     Documentation/netlink/
 X:     Documentation/power/
 X:     Documentation/spi/
 X:     Documentation/userspace-api/media/
@@ -6350,6 +6347,25 @@ S:       Maintained
 F:     drivers/soc/ti/smartreflex.c
 F:     include/linux/power/smartreflex.h
 
+DRM ACCEL DRIVERS FOR INTEL VPU
+M:     Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
+M:     Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com>
+L:     dri-devel@lists.freedesktop.org
+S:     Supported
+T:     git git://anongit.freedesktop.org/drm/drm-misc
+F:     drivers/accel/ivpu/
+F:     include/uapi/drm/ivpu_accel.h
+
+DRM COMPUTE ACCELERATORS DRIVERS AND FRAMEWORK
+M:     Oded Gabbay <ogabbay@kernel.org>
+L:     dri-devel@lists.freedesktop.org
+S:     Maintained
+C:     irc://irc.oftc.net/dri-devel
+T:     git https://git.kernel.org/pub/scm/linux/kernel/git/ogabbay/accel.git
+F:     Documentation/accel/
+F:     drivers/accel/
+F:     include/drm/drm_accel.h
+
 DRM DRIVER FOR ALLWINNER DE2 AND DE3 ENGINE
 M:     Maxime Ripard <mripard@kernel.org>
 M:     Chen-Yu Tsai <wens@csie.org>
@@ -6432,6 +6448,21 @@ S:       Maintained
 F:     Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.yaml
 F:     drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
 
+DRM DRIVER FOR FIRMWARE FRAMEBUFFERS
+M:     Thomas Zimmermann <tzimmermann@suse.de>
+M:     Javier Martinez Canillas <javierm@redhat.com>
+L:     dri-devel@lists.freedesktop.org
+S:     Maintained
+T:     git git://anongit.freedesktop.org/drm/drm-misc
+F:     drivers/gpu/drm/drm_aperture.c
+F:     drivers/gpu/drm/tiny/ofdrm.c
+F:     drivers/gpu/drm/tiny/simpledrm.c
+F:     drivers/video/aperture.c
+F:     drivers/video/nomodeset.c
+F:     include/drm/drm_aperture.h
+F:     include/linux/aperture.h
+F:     include/video/nomodeset.h
+
 DRM DRIVER FOR GENERIC EDP PANELS
 R:     Douglas Anderson <dianders@chromium.org>
 F:     Documentation/devicetree/bindings/display/panel/panel-edp.yaml
@@ -6466,6 +6497,14 @@ T:       git git://anongit.freedesktop.org/drm/drm-misc
 F:     Documentation/devicetree/bindings/display/himax,hx8357d.txt
 F:     drivers/gpu/drm/tiny/hx8357d.c
 
+DRM DRIVER FOR HYPERV SYNTHETIC VIDEO DEVICE
+M:     Deepak Rawat <drawat.floss@gmail.com>
+L:     linux-hyperv@vger.kernel.org
+L:     dri-devel@lists.freedesktop.org
+S:     Maintained
+T:     git git://anongit.freedesktop.org/drm/drm-misc
+F:     drivers/gpu/drm/hyperv
+
 DRM DRIVER FOR ILITEK ILI9225 PANELS
 M:     David Lechner <david@lechnology.com>
 S:     Maintained
@@ -6495,11 +6534,11 @@ F:      drivers/gpu/drm/logicvc/
 DRM DRIVER FOR LVDS PANELS
 M:     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 L:     dri-devel@lists.freedesktop.org
-T:     git git://anongit.freedesktop.org/drm/drm-misc
 S:     Maintained
-F:     drivers/gpu/drm/panel/panel-lvds.c
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 F:     Documentation/devicetree/bindings/display/lvds.yaml
 F:     Documentation/devicetree/bindings/display/panel/panel-lvds.yaml
+F:     drivers/gpu/drm/panel/panel-lvds.c
 
 DRM DRIVER FOR MANTIX MLAF057WE51 PANELS
 M:     Guido Günther <agx@sigxcpu.org>
@@ -6608,13 +6647,6 @@ T:       git git://anongit.freedesktop.org/drm/drm-misc
 F:     Documentation/devicetree/bindings/display/repaper.txt
 F:     drivers/gpu/drm/tiny/repaper.c
 
-DRM DRIVER FOR SOLOMON SSD130X OLED DISPLAYS
-M:     Javier Martinez Canillas <javierm@redhat.com>
-S:     Maintained
-T:     git git://anongit.freedesktop.org/drm/drm-misc
-F:     Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
-F:     drivers/gpu/drm/solomon/ssd130x*
-
 DRM DRIVER FOR QEMU'S CIRRUS DEVICE
 M:     Dave Airlie <airlied@redhat.com>
 M:     Gerd Hoffmann <kraxel@redhat.com>
@@ -6663,29 +6695,6 @@ S:       Maintained
 F:     Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml
 F:     drivers/gpu/drm/panel/panel-samsung-s6d27a1.c
 
-DRM DRIVER FOR SITRONIX ST7703 PANELS
-M:     Guido Günther <agx@sigxcpu.org>
-R:     Purism Kernel Team <kernel@puri.sm>
-R:     Ondrej Jirman <megous@megous.com>
-S:     Maintained
-F:     Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml
-F:     drivers/gpu/drm/panel/panel-sitronix-st7703.c
-
-DRM DRIVER FOR FIRMWARE FRAMEBUFFERS
-M:     Thomas Zimmermann <tzimmermann@suse.de>
-M:     Javier Martinez Canillas <javierm@redhat.com>
-L:     dri-devel@lists.freedesktop.org
-S:     Maintained
-T:     git git://anongit.freedesktop.org/drm/drm-misc
-F:     drivers/gpu/drm/drm_aperture.c
-F:     drivers/gpu/drm/tiny/ofdrm.c
-F:     drivers/gpu/drm/tiny/simpledrm.c
-F:     drivers/video/aperture.c
-F:     drivers/video/nomodeset.c
-F:     include/drm/drm_aperture.h
-F:     include/linux/aperture.h
-F:     include/video/nomodeset.h
-
 DRM DRIVER FOR SITRONIX ST7586 PANELS
 M:     David Lechner <david@lechnology.com>
 S:     Maintained
@@ -6699,6 +6708,14 @@ S:       Maintained
 F:     Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml
 F:     drivers/gpu/drm/panel/panel-sitronix-st7701.c
 
+DRM DRIVER FOR SITRONIX ST7703 PANELS
+M:     Guido Günther <agx@sigxcpu.org>
+R:     Purism Kernel Team <kernel@puri.sm>
+R:     Ondrej Jirman <megous@megous.com>
+S:     Maintained
+F:     Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml
+F:     drivers/gpu/drm/panel/panel-sitronix-st7703.c
+
 DRM DRIVER FOR SITRONIX ST7735R PANELS
 M:     David Lechner <david@lechnology.com>
 S:     Maintained
@@ -6706,6 +6723,13 @@ T:       git git://anongit.freedesktop.org/drm/drm-misc
 F:     Documentation/devicetree/bindings/display/sitronix,st7735r.yaml
 F:     drivers/gpu/drm/tiny/st7735r.c
 
+DRM DRIVER FOR SOLOMON SSD130X OLED DISPLAYS
+M:     Javier Martinez Canillas <javierm@redhat.com>
+S:     Maintained
+T:     git git://anongit.freedesktop.org/drm/drm-misc
+F:     Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
+F:     drivers/gpu/drm/solomon/ssd130x*
+
 DRM DRIVER FOR ST-ERICSSON MCDE
 M:     Linus Walleij <linus.walleij@linaro.org>
 S:     Maintained
@@ -6804,25 +6828,6 @@ F:       include/drm/drm*
 F:     include/linux/vga*
 F:     include/uapi/drm/drm*
 
-DRM COMPUTE ACCELERATORS DRIVERS AND FRAMEWORK
-M:     Oded Gabbay <ogabbay@kernel.org>
-L:     dri-devel@lists.freedesktop.org
-S:     Maintained
-C:     irc://irc.oftc.net/dri-devel
-T:     git https://git.kernel.org/pub/scm/linux/kernel/git/ogabbay/accel.git
-F:     Documentation/accel/
-F:     drivers/accel/
-F:     include/drm/drm_accel.h
-
-DRM ACCEL DRIVERS FOR INTEL VPU
-M:     Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
-M:     Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com>
-L:     dri-devel@lists.freedesktop.org
-S:     Supported
-T:     git git://anongit.freedesktop.org/drm/drm-misc
-F:     drivers/accel/ivpu/
-F:     include/uapi/drm/ivpu_accel.h
-
 DRM DRIVERS FOR ALLWINNER A10
 M:     Maxime Ripard <mripard@kernel.org>
 M:     Chen-Yu Tsai <wens@csie.org>
@@ -6926,14 +6931,6 @@ T:       git git://anongit.freedesktop.org/drm/drm-misc
 F:     Documentation/devicetree/bindings/display/hisilicon/
 F:     drivers/gpu/drm/hisilicon/
 
-DRM DRIVER FOR HYPERV SYNTHETIC VIDEO DEVICE
-M:     Deepak Rawat <drawat.floss@gmail.com>
-L:     linux-hyperv@vger.kernel.org
-L:     dri-devel@lists.freedesktop.org
-S:     Maintained
-T:     git git://anongit.freedesktop.org/drm/drm-misc
-F:     drivers/gpu/drm/hyperv
-
 DRM DRIVERS FOR LIMA
 M:     Qiang Yu <yuq825@gmail.com>
 L:     dri-devel@lists.freedesktop.org
@@ -7085,6 +7082,14 @@ T:       git git://anongit.freedesktop.org/drm/drm-misc
 F:     Documentation/devicetree/bindings/display/xlnx/
 F:     drivers/gpu/drm/xlnx/
 
+DRM GPU SCHEDULER
+M:     Luben Tuikov <luben.tuikov@amd.com>
+L:     dri-devel@lists.freedesktop.org
+S:     Maintained
+T:     git git://anongit.freedesktop.org/drm/drm-misc
+F:     drivers/gpu/drm/scheduler/
+F:     include/drm/gpu_scheduler.h
+
 DRM PANEL DRIVERS
 M:     Neil Armstrong <neil.armstrong@linaro.org>
 R:     Sam Ravnborg <sam@ravnborg.org>
@@ -7113,14 +7118,6 @@ T:       git git://anongit.freedesktop.org/drm/drm-misc
 F:     drivers/gpu/drm/ttm/
 F:     include/drm/ttm/
 
-DRM GPU SCHEDULER
-M:     Luben Tuikov <luben.tuikov@amd.com>
-L:     dri-devel@lists.freedesktop.org
-S:     Maintained
-T:     git git://anongit.freedesktop.org/drm/drm-misc
-F:     drivers/gpu/drm/scheduler/
-F:     include/drm/gpu_scheduler.h
-
 DSBR100 USB FM RADIO DRIVER
 M:     Alexey Klimov <klimov.linux@gmail.com>
 L:     linux-media@vger.kernel.org
@@ -7248,10 +7245,10 @@ F:      drivers/media/usb/dvb-usb-v2/usb_urb.c
 
 DYNAMIC DEBUG
 M:     Jason Baron <jbaron@akamai.com>
+M:     Jim Cromie <jim.cromie@gmail.com>
 S:     Maintained
 F:     include/linux/dynamic_debug.h
 F:     lib/dynamic_debug.c
-M:     Jim Cromie <jim.cromie@gmail.com>
 F:     lib/test_dynamic_debug.c
 
 DYNAMIC INTERRUPT MODERATION
@@ -7261,6 +7258,15 @@ F:       Documentation/networking/net_dim.rst
 F:     include/linux/dim.h
 F:     lib/dim/
 
+DYNAMIC THERMAL POWER MANAGEMENT (DTPM)
+M:     Daniel Lezcano <daniel.lezcano@kernel.org>
+L:     linux-pm@vger.kernel.org
+S:     Supported
+B:     https://bugzilla.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
+F:     drivers/powercap/dtpm*
+F:     include/linux/dtpm.h
+
 DZ DECSTATION DZ11 SERIAL DRIVER
 M:     "Maciej W. Rozycki" <macro@orcam.me.uk>
 S:     Maintained
@@ -7599,22 +7605,22 @@ W:      http://www.broadcom.com
 F:     drivers/infiniband/hw/ocrdma/
 F:     include/uapi/rdma/ocrdma-abi.h
 
-EMULEX/BROADCOM LPFC FC/FCOE SCSI DRIVER
+EMULEX/BROADCOM EFCT FC/FCOE SCSI TARGET DRIVER
 M:     James Smart <james.smart@broadcom.com>
-M:     Dick Kennedy <dick.kennedy@broadcom.com>
+M:     Ram Vegesna <ram.vegesna@broadcom.com>
 L:     linux-scsi@vger.kernel.org
+L:     target-devel@vger.kernel.org
 S:     Supported
 W:     http://www.broadcom.com
-F:     drivers/scsi/lpfc/
+F:     drivers/scsi/elx/
 
-EMULEX/BROADCOM EFCT FC/FCOE SCSI TARGET DRIVER
+EMULEX/BROADCOM LPFC FC/FCOE SCSI DRIVER
 M:     James Smart <james.smart@broadcom.com>
-M:     Ram Vegesna <ram.vegesna@broadcom.com>
+M:     Dick Kennedy <dick.kennedy@broadcom.com>
 L:     linux-scsi@vger.kernel.org
-L:     target-devel@vger.kernel.org
 S:     Supported
 W:     http://www.broadcom.com
-F:     drivers/scsi/elx/
+F:     drivers/scsi/lpfc/
 
 ENE CB710 FLASH CARD READER DRIVER
 M:     MichaÅ‚ MirosÅ‚aw <mirq-linux@rere.qmqm.pl>
@@ -7707,8 +7713,8 @@ F:        drivers/net/mdio/of_mdio.c
 F:     drivers/net/pcs/
 F:     drivers/net/phy/
 F:     include/dt-bindings/net/qca-ar803x.h
-F:     include/linux/linkmode.h
 F:     include/linux/*mdio*.h
+F:     include/linux/linkmode.h
 F:     include/linux/mdio/*.h
 F:     include/linux/mii.h
 F:     include/linux/of_net.h
@@ -7771,8 +7777,8 @@ M:        Mimi Zohar <zohar@linux.ibm.com>
 L:     linux-integrity@vger.kernel.org
 S:     Supported
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git
-F:     security/integrity/evm/
 F:     security/integrity/
+F:     security/integrity/evm/
 
 EXTENSIBLE FIRMWARE INTERFACE (EFI)
 M:     Ard Biesheuvel <ardb@kernel.org>
@@ -7803,8 +7809,8 @@ EXTRA BOOT CONFIG
 M:     Masami Hiramatsu <mhiramat@kernel.org>
 L:     linux-kernel@vger.kernel.org
 L:     linux-trace-kernel@vger.kernel.org
-Q:     https://patchwork.kernel.org/project/linux-trace-kernel/list/
 S:     Maintained
+Q:     https://patchwork.kernel.org/project/linux-trace-kernel/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git
 F:     Documentation/admin-guide/bootconfig.rst
 F:     fs/proc/bootconfig.c
@@ -8091,21 +8097,6 @@ F:       Documentation/fpga/
 F:     drivers/fpga/
 F:     include/linux/fpga/
 
-INTEL MAX10 BMC SECURE UPDATES
-M:     Russ Weight <russell.h.weight@intel.com>
-L:     linux-fpga@vger.kernel.org
-S:     Maintained
-F:     Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
-F:     drivers/fpga/intel-m10-bmc-sec-update.c
-
-MICROCHIP POLARFIRE FPGA DRIVERS
-M:     Conor Dooley <conor.dooley@microchip.com>
-R:     Ivan Bornyakov <i.bornyakov@metrotek.ru>
-L:     linux-fpga@vger.kernel.org
-S:     Supported
-F:     Documentation/devicetree/bindings/fpga/microchip,mpf-spi-fpga-mgr.yaml
-F:     drivers/fpga/microchip-spi.c
-
 FPU EMULATOR
 M:     Bill Metzenthen <billm@melbpc.org.au>
 S:     Maintained
@@ -8114,9 +8105,9 @@ F:        arch/x86/math-emu/
 
 FRAMEBUFFER CORE
 M:     Daniel Vetter <daniel@ffwll.ch>
-F:     drivers/video/fbdev/core/
 S:     Odd Fixes
 T:     git git://anongit.freedesktop.org/drm/drm-misc
+F:     drivers/video/fbdev/core/
 
 FRAMEBUFFER LAYER
 M:     Helge Deller <deller@gmx.de>
@@ -8171,6 +8162,7 @@ F:        include/linux/spi/spi-fsl-dspi.h
 
 FREESCALE ENETC ETHERNET DRIVERS
 M:     Claudiu Manoil <claudiu.manoil@nxp.com>
+M:     Vladimir Oltean <vladimir.oltean@nxp.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/freescale/enetc/
@@ -8493,15 +8485,15 @@ M:      Masami Hiramatsu <mhiramat@kernel.org>
 R:     Mark Rutland <mark.rutland@arm.com>
 L:     linux-kernel@vger.kernel.org
 L:     linux-trace-kernel@vger.kernel.org
-Q:     https://patchwork.kernel.org/project/linux-trace-kernel/list/
 S:     Maintained
+Q:     https://patchwork.kernel.org/project/linux-trace-kernel/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git
 F:     Documentation/trace/ftrace*
-F:     kernel/trace/ftrace*
-F:     kernel/trace/fgraph.c
 F:     arch/*/*/*/*ftrace*
 F:     arch/*/*/*ftrace*
 F:     include/*/ftrace.h
+F:     kernel/trace/fgraph.c
+F:     kernel/trace/ftrace*
 F:     samples/ftrace
 
 FUNGIBLE ETHERNET DRIVERS
@@ -8542,10 +8534,10 @@ GATEWORKS SYSTEM CONTROLLER (GSC) DRIVER
 M:     Tim Harvey <tharvey@gateworks.com>
 S:     Maintained
 F:     Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml
-F:     drivers/mfd/gateworks-gsc.c
-F:     include/linux/mfd/gsc.h
 F:     Documentation/hwmon/gsc-hwmon.rst
 F:     drivers/hwmon/gsc-hwmon.c
+F:     drivers/mfd/gateworks-gsc.c
+F:     include/linux/mfd/gsc.h
 F:     include/linux/platform_data/gsc_hwmon.h
 
 GCC PLUGINS
@@ -8673,8 +8665,8 @@ R:        Andy Shevchenko <andy@kernel.org>
 S:     Maintained
 F:     lib/string.c
 F:     lib/string_helpers.c
-F:     lib/test_string.c
 F:     lib/test-string_helpers.c
+F:     lib/test_string.c
 
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:     "Michael S. Tsirkin" <mst@redhat.com>
@@ -9157,12 +9149,11 @@ L:      linux-input@vger.kernel.org
 S:     Maintained
 F:     drivers/hid/hid-logitech-*
 
-HID++ LOGITECH DRIVERS
-R:     Filipe Laíns <lains@riseup.net>
-R:     Bastien Nocera <hadess@hadess.net>
+HID PHOENIX RC FLIGHT CONTROLLER
+M:     Marcus Folkesson <marcus.folkesson@gmail.com>
 L:     linux-input@vger.kernel.org
 S:     Maintained
-F:     drivers/hid/hid-logitech-hidpp.c
+F:     drivers/hid/hid-pxrc.c
 
 HID PLAYSTATION DRIVER
 M:     Roderick Colenbrander <roderick.colenbrander@sony.com>
@@ -9170,12 +9161,6 @@ L:       linux-input@vger.kernel.org
 S:     Supported
 F:     drivers/hid/hid-playstation.c
 
-HID PHOENIX RC FLIGHT CONTROLLER
-M:     Marcus Folkesson <marcus.folkesson@gmail.com>
-L:     linux-input@vger.kernel.org
-S:     Maintained
-F:     drivers/hid/hid-pxrc.c
-
 HID SENSOR HUB DRIVERS
 M:     Jiri Kosina <jikos@kernel.org>
 M:     Jonathan Cameron <jic23@kernel.org>
@@ -9202,6 +9187,13 @@ S:       Maintained
 F:     drivers/hid/wacom.h
 F:     drivers/hid/wacom_*
 
+HID++ LOGITECH DRIVERS
+R:     Filipe Laíns <lains@riseup.net>
+R:     Bastien Nocera <hadess@hadess.net>
+L:     linux-input@vger.kernel.org
+S:     Maintained
+F:     drivers/hid/hid-logitech-hidpp.c
+
 HIGH-RESOLUTION TIMERS, CLOCKEVENTS
 M:     Thomas Gleixner <tglx@linutronix.de>
 L:     linux-kernel@vger.kernel.org
@@ -9226,6 +9218,12 @@ W:       http://www.highpoint-tech.com
 F:     Documentation/scsi/hptiop.rst
 F:     drivers/scsi/hptiop.c
 
+HIKEY960 ONBOARD USB GPIO HUB DRIVER
+M:     John Stultz <jstultz@google.com>
+L:     linux-kernel@vger.kernel.org
+S:     Maintained
+F:     drivers/misc/hisi_hikey_usb.c
+
 HIMAX HX83112B TOUCHSCREEN SUPPORT
 M:     Job Noorman <job@noorman.info>
 L:     linux-input@vger.kernel.org
@@ -9274,6 +9272,12 @@ F:       drivers/crypto/hisilicon/hpre/hpre.h
 F:     drivers/crypto/hisilicon/hpre/hpre_crypto.c
 F:     drivers/crypto/hisilicon/hpre/hpre_main.c
 
+HISILICON HNS3 PMU DRIVER
+M:     Guangbin Huang <huangguangbin2@huawei.com>
+S:     Supported
+F:     Documentation/admin-guide/perf/hns3-pmu.rst
+F:     drivers/perf/hisilicon/hns3_pmu.c
+
 HISILICON I2C CONTROLLER DRIVER
 M:     Yicong Yang <yangyicong@hisilicon.com>
 L:     linux-i2c@vger.kernel.org
@@ -9306,12 +9310,6 @@ W:       http://www.hisilicon.com
 F:     Documentation/devicetree/bindings/net/hisilicon*.txt
 F:     drivers/net/ethernet/hisilicon/
 
-HIKEY960 ONBOARD USB GPIO HUB DRIVER
-M:     John Stultz <jstultz@google.com>
-L:     linux-kernel@vger.kernel.org
-S:     Maintained
-F:     drivers/misc/hisi_hikey_usb.c
-
 HISILICON PMU DRIVER
 M:     Shaokun Zhang <zhangshaokun@hisilicon.com>
 M:     Jonathan Cameron <jonathan.cameron@huawei.com>
@@ -9321,12 +9319,6 @@ F:       Documentation/admin-guide/perf/hisi-pcie-pmu.rst
 F:     Documentation/admin-guide/perf/hisi-pmu.rst
 F:     drivers/perf/hisilicon
 
-HISILICON HNS3 PMU DRIVER
-M:     Guangbin Huang <huangguangbin2@huawei.com>
-S:     Supported
-F:     Documentation/admin-guide/perf/hns3-pmu.rst
-F:     drivers/perf/hisilicon/hns3_pmu.c
-
 HISILICON PTT DRIVER
 M:     Yicong Yang <yangyicong@hisilicon.com>
 M:     Jonathan Cameron <jonathan.cameron@huawei.com>
@@ -9350,17 +9342,9 @@ F:       drivers/crypto/hisilicon/qm.c
 F:     drivers/crypto/hisilicon/sgl.c
 F:     include/linux/hisi_acc_qm.h
 
-HISILICON ZIP Controller DRIVER
-M:     Yang Shen <shenyang39@huawei.com>
-M:     Zhou Wang <wangzhou1@hisilicon.com>
-L:     linux-crypto@vger.kernel.org
-S:     Maintained
-F:     Documentation/ABI/testing/debugfs-hisi-zip
-F:     drivers/crypto/hisilicon/zip/
-
 HISILICON ROCE DRIVER
 M:     Haoyue Xu <xuhaoyue1@hisilicon.com>
-M:     Wenpeng Liang <liangwenpeng@huawei.com>
+M:     Junxian Huang <huangjunxian6@hisilicon.com>
 L:     linux-rdma@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/infiniband/hisilicon-hns-roce.txt
@@ -9416,6 +9400,14 @@ S:       Maintained
 W:     http://www.hisilicon.com
 F:     drivers/spi/spi-hisi-sfc-v3xx.c
 
+HISILICON ZIP Controller DRIVER
+M:     Yang Shen <shenyang39@huawei.com>
+M:     Zhou Wang <wangzhou1@hisilicon.com>
+L:     linux-crypto@vger.kernel.org
+S:     Maintained
+F:     Documentation/ABI/testing/debugfs-hisi-zip
+F:     drivers/crypto/hisilicon/zip/
+
 HMM - Heterogeneous Memory Management
 M:     Jérôme Glisse <jglisse@redhat.com>
 L:     linux-mm@kvack.org
@@ -9426,6 +9418,13 @@ F:       lib/test_hmm*
 F:     mm/hmm*
 F:     tools/testing/selftests/mm/*hmm*
 
+HONEYWELL MPRLS0025PA PRESSURE SENSOR SERIES IIO DRIVER
+M:     Andreas Klinger <ak@it-klinger.de>
+L:     linux-iio@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml
+F:     drivers/iio/pressure/mprls0025pa.c
+
 HOST AP DRIVER
 M:     Jouni Malinen <j@w1.fi>
 L:     linux-wireless@vger.kernel.org
@@ -9492,9 +9491,9 @@ F:        drivers/input/touchscreen/htcpen.c
 HTE SUBSYSTEM
 M:     Dipen Patel <dipenp@nvidia.com>
 L:     timestamp@lists.linux.dev
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/pateldipen1984/linux.git
-Q:     https://patchwork.kernel.org/project/timestamp/list/
 S:     Maintained
+Q:     https://patchwork.kernel.org/project/timestamp/list/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/pateldipen1984/linux.git
 F:     Documentation/devicetree/bindings/timestamp/
 F:     Documentation/driver-api/hte/
 F:     drivers/hte/
@@ -9589,8 +9588,8 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git
 F:     Documentation/ABI/stable/sysfs-bus-vmbus
 F:     Documentation/ABI/testing/debugfs-hyperv
 F:     Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
-F:     Documentation/virt/hyperv
 F:     Documentation/networking/device_drivers/ethernet/microsoft/netvsc.rst
+F:     Documentation/virt/hyperv
 F:     arch/arm64/hyperv
 F:     arch/arm64/include/asm/hyperv-tlfs.h
 F:     arch/arm64/include/asm/mshyperv.h
@@ -9772,6 +9771,12 @@ L:       linux-i2c@vger.kernel.org
 S:     Maintained
 F:     drivers/i2c/i2c-stub.c
 
+I3C DRIVER FOR ASPEED AST2600
+M:     Jeremy Kerr <jk@codeconstruct.com.au>
+S:     Maintained
+F:     Documentation/devicetree/bindings/i3c/aspeed,ast2600-i3c.yaml
+F:     drivers/i3c/master/ast2600-i3c-master.c
+
 I3C DRIVER FOR CADENCE I3C MASTER IP
 M:     PrzemysÅ‚aw Gaj <pgaj@cadence.com>
 S:     Maintained
@@ -9783,12 +9788,6 @@ S:       Orphan
 F:     Documentation/devicetree/bindings/i3c/snps,dw-i3c-master.yaml
 F:     drivers/i3c/master/dw*
 
-I3C DRIVER FOR ASPEED AST2600
-M:     Jeremy Kerr <jk@codeconstruct.com.au>
-S:     Maintained
-F:     Documentation/devicetree/bindings/i3c/aspeed,ast2600-i3c.yaml
-F:     drivers/i3c/master/ast2600-i3c-master.c
-
 I3C SUBSYSTEM
 M:     Alexandre Belloni <alexandre.belloni@bootlin.com>
 L:     linux-i3c@lists.infradead.org (moderated for non-subscribers)
@@ -9867,6 +9866,11 @@ L:       netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/ibm/ibmvnic.*
 
+IBM Power VFIO Support
+M:     Timothy Pearson <tpearson@raptorengineering.com>
+S:     Supported
+F:     drivers/vfio/vfio_iommu_spapr_tce.c
+
 IBM Power Virtual Ethernet Device Driver
 M:     Nick Child <nnac123@linux.ibm.com>
 L:     netdev@vger.kernel.org
@@ -9912,11 +9916,6 @@ F:       drivers/crypto/vmx/ghash*
 F:     drivers/crypto/vmx/ppc-xlate.pl
 F:     drivers/crypto/vmx/vmx.c
 
-IBM Power VFIO Support
-M:     Timothy Pearson <tpearson@raptorengineering.com>
-S:     Supported
-F:     drivers/vfio/vfio_iommu_spapr_tce.c
-
 IBM ServeRAID RAID DRIVER
 S:     Orphan
 F:     drivers/scsi/ips.*
@@ -9984,6 +9983,10 @@ F:       include/net/nl802154.h
 F:     net/ieee802154/
 F:     net/mac802154/
 
+IFCVF VIRTIO DATA PATH ACCELERATOR
+R:     Zhu Lingshan <lingshan.zhu@intel.com>
+F:     drivers/vdpa/ifcvf/
+
 IFE PROTOCOL
 M:     Yotam Gigi <yotam.gi@gmail.com>
 M:     Jamal Hadi Salim <jhs@mojatatu.com>
@@ -10119,7 +10122,7 @@ S:      Maintained
 F:     Documentation/process/kernel-docs.rst
 
 INDUSTRY PACK SUBSYSTEM (IPACK)
-M:     Samuel Iglesias Gonsalvez <siglesias@igalia.com>
+M:     Vaibhav Gupta <vaibhavgupta40@gmail.com>
 M:     Jens Taprogge <jens.taprogge@taprogge.org>
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     industrypack-devel@lists.sourceforge.net
@@ -10248,8 +10251,8 @@ M:      Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
 L:     linux-integrity@vger.kernel.org
 S:     Supported
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git
-F:     security/integrity/ima/
 F:     security/integrity/
+F:     security/integrity/ima/
 
 INTEL 810/815 FRAMEBUFFER DRIVER
 M:     Antonino Daplas <adaplas@gmail.com>
@@ -10257,6 +10260,13 @@ L:     linux-fbdev@vger.kernel.org
 S:     Maintained
 F:     drivers/video/fbdev/i810/
 
+INTEL 8254 COUNTER DRIVER
+M:     William Breathitt Gray <william.gray@linaro.org>
+L:     linux-iio@vger.kernel.org
+S:     Maintained
+F:     drivers/counter/i8254.c
+F:     include/linux/i8254.h
+
 INTEL 8255 GPIO DRIVER
 M:     William Breathitt Gray <william.gray@linaro.org>
 L:     linux-gpio@vger.kernel.org
@@ -10403,14 +10413,6 @@ S:     Supported
 Q:     https://patchwork.kernel.org/project/linux-dmaengine/list/
 F:     drivers/dma/ioat*
 
-INTEL IDXD DRIVER
-M:     Fenghua Yu <fenghua.yu@intel.com>
-M:     Dave Jiang <dave.jiang@intel.com>
-L:     dmaengine@vger.kernel.org
-S:     Supported
-F:     drivers/dma/idxd/*
-F:     include/uapi/linux/idxd.h
-
 INTEL IDLE DRIVER
 M:     Jacob Pan <jacob.jun.pan@linux.intel.com>
 M:     Len Brown <lenb@kernel.org>
@@ -10420,6 +10422,14 @@ B:     https://bugzilla.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git
 F:     drivers/idle/intel_idle.c
 
+INTEL IDXD DRIVER
+M:     Fenghua Yu <fenghua.yu@intel.com>
+M:     Dave Jiang <dave.jiang@intel.com>
+L:     dmaengine@vger.kernel.org
+S:     Supported
+F:     drivers/dma/idxd/*
+F:     include/uapi/linux/idxd.h
+
 INTEL IN FIELD SCAN (IFS) DEVICE
 M:     Jithu Joseph <jithu.joseph@intel.com>
 R:     Ashok Raj <ashok.raj@intel.com>
@@ -10466,18 +10476,18 @@ F:    Documentation/admin-guide/media/ipu3_rcb.svg
 F:     Documentation/userspace-api/media/v4l/pixfmt-meta-intel-ipu3.rst
 F:     drivers/staging/media/ipu3/
 
-INTEL IXP4XX CRYPTO SUPPORT
-M:     Corentin Labbe <clabbe@baylibre.com>
-L:     linux-crypto@vger.kernel.org
-S:     Maintained
-F:     drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
-
 INTEL ISHTP ECLITE DRIVER
 M:     Sumesh K Naduvalath <sumesh.k.naduvalath@intel.com>
 L:     platform-driver-x86@vger.kernel.org
 S:     Supported
 F:     drivers/platform/x86/intel/ishtp_eclite.c
 
+INTEL IXP4XX CRYPTO SUPPORT
+M:     Corentin Labbe <clabbe@baylibre.com>
+L:     linux-crypto@vger.kernel.org
+S:     Maintained
+F:     drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
+
 INTEL IXP4XX QMGR, NPE, ETHERNET and HSS SUPPORT
 M:     Krzysztof Halasa <khalasa@piap.pl>
 S:     Maintained
@@ -10556,6 +10566,13 @@ F:     drivers/hwmon/intel-m10-bmc-hwmon.c
 F:     drivers/mfd/intel-m10-bmc*
 F:     include/linux/mfd/intel-m10-bmc.h
 
+INTEL MAX10 BMC SECURE UPDATES
+M:     Russ Weight <russell.h.weight@intel.com>
+L:     linux-fpga@vger.kernel.org
+S:     Maintained
+F:     Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
+F:     drivers/fpga/intel-m10-bmc-sec-update.c
+
 INTEL P-Unit IPC DRIVER
 M:     Zha Qipeng <qipeng.zha@intel.com>
 L:     platform-driver-x86@vger.kernel.org
@@ -10603,6 +10620,13 @@ L:     linux-pm@vger.kernel.org
 S:     Supported
 F:     drivers/cpufreq/intel_pstate.c
 
+INTEL PTP DFL ToD DRIVER
+M:     Tianfei Zhang <tianfei.zhang@intel.com>
+L:     linux-fpga@vger.kernel.org
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/ptp/ptp_dfl_tod.c
+
 INTEL QUADRATURE ENCODER PERIPHERAL DRIVER
 M:     Jarkko Nikula <jarkko.nikula@linux.intel.com>
 L:     linux-iio@vger.kernel.org
@@ -10621,6 +10645,21 @@ F:     drivers/platform/x86/intel/sdsi.c
 F:     tools/arch/x86/intel_sdsi/
 F:     tools/testing/selftests/drivers/sdsi/
 
+INTEL SGX
+M:     Jarkko Sakkinen <jarkko@kernel.org>
+R:     Dave Hansen <dave.hansen@linux.intel.com>
+L:     linux-sgx@vger.kernel.org
+S:     Supported
+Q:     https://patchwork.kernel.org/project/intel-sgx/list/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/sgx
+F:     Documentation/arch/x86/sgx.rst
+F:     arch/x86/entry/vdso/vsgx.S
+F:     arch/x86/include/asm/sgx.h
+F:     arch/x86/include/uapi/asm/sgx.h
+F:     arch/x86/kernel/cpu/sgx/*
+F:     tools/testing/selftests/sgx/*
+K:     \bSGX_
+
 INTEL SKYLAKE INT3472 ACPI DEVICE DRIVER
 M:     Daniel Scally <djrscally@gmail.com>
 S:     Maintained
@@ -10638,13 +10677,13 @@ INTEL STRATIX10 FIRMWARE DRIVERS
 M:     Dinh Nguyen <dinguyen@kernel.org>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git
 F:     Documentation/ABI/testing/sysfs-devices-platform-stratix10-rsu
 F:     Documentation/devicetree/bindings/firmware/intel,stratix10-svc.txt
 F:     drivers/firmware/stratix10-rsu.c
 F:     drivers/firmware/stratix10-svc.c
 F:     include/linux/firmware/intel/stratix10-smc.h
 F:     include/linux/firmware/intel/stratix10-svc-client.h
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git
 
 INTEL TELEMETRY DRIVER
 M:     Rajneesh Bhardwaj <irenic.rajneesh@gmail.com>
@@ -10729,21 +10768,6 @@ F:     Documentation/arch/x86/intel_txt.rst
 F:     arch/x86/kernel/tboot.c
 F:     include/linux/tboot.h
 
-INTEL SGX
-M:     Jarkko Sakkinen <jarkko@kernel.org>
-R:     Dave Hansen <dave.hansen@linux.intel.com>
-L:     linux-sgx@vger.kernel.org
-S:     Supported
-Q:     https://patchwork.kernel.org/project/intel-sgx/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/sgx
-F:     Documentation/arch/x86/sgx.rst
-F:     arch/x86/entry/vdso/vsgx.S
-F:     arch/x86/include/asm/sgx.h
-F:     arch/x86/include/uapi/asm/sgx.h
-F:     arch/x86/kernel/cpu/sgx/*
-F:     tools/testing/selftests/sgx/*
-K:     \bSGX_
-
 INTERCONNECT API
 M:     Georgi Djakov <djakov@kernel.org>
 L:     linux-pm@vger.kernel.org
@@ -10812,18 +10836,6 @@ F:     drivers/iommu/dma-iommu.h
 F:     drivers/iommu/iova.c
 F:     include/linux/iova.h
 
-IOMMUFD
-M:     Jason Gunthorpe <jgg@nvidia.com>
-M:     Kevin Tian <kevin.tian@intel.com>
-L:     iommu@lists.linux.dev
-S:     Maintained
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd.git
-F:     Documentation/userspace-api/iommufd.rst
-F:     drivers/iommu/iommufd/
-F:     include/linux/iommufd.h
-F:     include/uapi/linux/iommufd.h
-F:     tools/testing/selftests/iommu/
-
 IOMMU SUBSYSTEM
 M:     Joerg Roedel <joro@8bytes.org>
 M:     Will Deacon <will@kernel.org>
@@ -10839,6 +10851,18 @@ F:     include/linux/iova.h
 F:     include/linux/of_iommu.h
 F:     include/uapi/linux/iommu.h
 
+IOMMUFD
+M:     Jason Gunthorpe <jgg@nvidia.com>
+M:     Kevin Tian <kevin.tian@intel.com>
+L:     iommu@lists.linux.dev
+S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd.git
+F:     Documentation/userspace-api/iommufd.rst
+F:     drivers/iommu/iommufd/
+F:     include/linux/iommufd.h
+F:     include/uapi/linux/iommufd.h
+F:     tools/testing/selftests/iommu/
+
 IOSYS-MAP HELPERS
 M:     Thomas Zimmermann <tzimmermann@suse.de>
 L:     dri-devel@lists.freedesktop.org
@@ -10853,11 +10877,11 @@ L:    io-uring@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.dk/linux-block
 T:     git git://git.kernel.dk/liburing
-F:     io_uring/
 F:     include/linux/io_uring.h
 F:     include/linux/io_uring_types.h
 F:     include/trace/events/io_uring.h
 F:     include/uapi/linux/io_uring.h
+F:     io_uring/
 F:     tools/io_uring/
 
 IPMI SUBSYSTEM
@@ -10866,8 +10890,8 @@ L:      openipmi-developer@lists.sourceforge.net (moderated for non-subscribers)
 S:     Supported
 W:     http://openipmi.sourceforge.net/
 T:     git https://github.com/cminyard/linux-ipmi.git for-next
-F:     Documentation/driver-api/ipmi.rst
 F:     Documentation/devicetree/bindings/ipmi/
+F:     Documentation/driver-api/ipmi.rst
 F:     drivers/char/ipmi/
 F:     include/linux/ipmi*
 F:     include/uapi/linux/ipmi*
@@ -10919,8 +10943,8 @@ M:      Thomas Gleixner <tglx@linutronix.de>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
-F:     kernel/irq/
 F:     include/linux/group_cpus.h
+F:     kernel/irq/
 F:     lib/group_cpus.c
 
 IRQCHIP DRIVERS
@@ -11258,6 +11282,7 @@ L:      linux-nfs@vger.kernel.org
 S:     Supported
 W:     http://nfs.sourceforge.net/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux.git
+F:     Documentation/filesystems/nfs/
 F:     fs/exportfs/
 F:     fs/lockd/
 F:     fs/nfs_common/
@@ -11273,7 +11298,6 @@ F:      include/trace/misc/sunrpc.h
 F:     include/uapi/linux/nfsd/
 F:     include/uapi/linux/sunrpc/
 F:     net/sunrpc/
-F:     Documentation/filesystems/nfs/
 
 KERNEL REGRESSIONS
 M:     Thorsten Leemhuis <linux@leemhuis.info>
@@ -11300,9 +11324,9 @@ R:      Tom Talpey <tom@talpey.com>
 L:     linux-cifs@vger.kernel.org
 S:     Maintained
 T:     git git://git.samba.org/ksmbd.git
-F:     Documentation/filesystems/cifs/ksmbd.rst
-F:     fs/ksmbd/
-F:     fs/smbfs_common/
+F:     Documentation/filesystems/smb/ksmbd.rst
+F:     fs/smb/common/
+F:     fs/smb/server/
 
 KERNEL UNIT TESTING FRAMEWORK (KUnit)
 M:     Brendan Higgins <brendanhiggins@google.com>
@@ -11394,77 +11418,36 @@ M:    Christian Borntraeger <borntraeger@linux.ibm.com>
 M:     Janosch Frank <frankja@linux.ibm.com>
 M:     Claudio Imbrenda <imbrenda@linux.ibm.com>
 R:     David Hildenbrand <david@redhat.com>
-L:     kvm@vger.kernel.org
-S:     Supported
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux.git
-F:     Documentation/virt/kvm/s390*
-F:     arch/s390/include/asm/gmap.h
-F:     arch/s390/include/asm/kvm*
-F:     arch/s390/include/uapi/asm/kvm*
-F:     arch/s390/include/uapi/asm/uvdevice.h
-F:     arch/s390/kernel/uv.c
-F:     arch/s390/kvm/
-F:     arch/s390/mm/gmap.c
-F:     drivers/s390/char/uvdevice.c
-F:     tools/testing/selftests/drivers/s390x/uvdevice/
-F:     tools/testing/selftests/kvm/*/s390x/
-F:     tools/testing/selftests/kvm/s390x/
-
-KERNEL VIRTUAL MACHINE FOR X86 (KVM/x86)
-M:     Sean Christopherson <seanjc@google.com>
-M:     Paolo Bonzini <pbonzini@redhat.com>
-L:     kvm@vger.kernel.org
-S:     Supported
-T:     git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
-F:     arch/x86/include/asm/kvm*
-F:     arch/x86/include/asm/svm.h
-F:     arch/x86/include/asm/vmx*.h
-F:     arch/x86/include/uapi/asm/kvm*
-F:     arch/x86/include/uapi/asm/svm.h
-F:     arch/x86/include/uapi/asm/vmx.h
-F:     arch/x86/kvm/
-F:     arch/x86/kvm/*/
-
-KVM PARAVIRT (KVM/paravirt)
-M:     Paolo Bonzini <pbonzini@redhat.com>
-R:     Wanpeng Li <wanpengli@tencent.com>
-R:     Vitaly Kuznetsov <vkuznets@redhat.com>
-L:     kvm@vger.kernel.org
-S:     Supported
-T:     git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
-F:     arch/x86/kernel/kvm.c
-F:     arch/x86/kernel/kvmclock.c
-F:     arch/x86/include/asm/pvclock-abi.h
-F:     include/linux/kvm_para.h
-F:     include/uapi/linux/kvm_para.h
-F:     include/uapi/asm-generic/kvm_para.h
-F:     include/asm-generic/kvm_para.h
-F:     arch/um/include/asm/kvm_para.h
-F:     arch/x86/include/asm/kvm_para.h
-F:     arch/x86/include/uapi/asm/kvm_para.h
-
-KVM X86 HYPER-V (KVM/hyper-v)
-M:     Vitaly Kuznetsov <vkuznets@redhat.com>
-M:     Sean Christopherson <seanjc@google.com>
-M:     Paolo Bonzini <pbonzini@redhat.com>
-L:     kvm@vger.kernel.org
-S:     Supported
-T:     git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
-F:     arch/x86/kvm/hyperv.*
-F:     arch/x86/kvm/kvm_onhyperv.*
-F:     arch/x86/kvm/svm/hyperv.*
-F:     arch/x86/kvm/svm/svm_onhyperv.*
-F:     arch/x86/kvm/vmx/hyperv.*
+L:     kvm@vger.kernel.org
+S:     Supported
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux.git
+F:     Documentation/virt/kvm/s390*
+F:     arch/s390/include/asm/gmap.h
+F:     arch/s390/include/asm/kvm*
+F:     arch/s390/include/uapi/asm/kvm*
+F:     arch/s390/include/uapi/asm/uvdevice.h
+F:     arch/s390/kernel/uv.c
+F:     arch/s390/kvm/
+F:     arch/s390/mm/gmap.c
+F:     drivers/s390/char/uvdevice.c
+F:     tools/testing/selftests/drivers/s390x/uvdevice/
+F:     tools/testing/selftests/kvm/*/s390x/
+F:     tools/testing/selftests/kvm/s390x/
 
-KVM X86 Xen (KVM/Xen)
-M:     David Woodhouse <dwmw2@infradead.org>
-M:     Paul Durrant <paul@xen.org>
+KERNEL VIRTUAL MACHINE FOR X86 (KVM/x86)
 M:     Sean Christopherson <seanjc@google.com>
 M:     Paolo Bonzini <pbonzini@redhat.com>
 L:     kvm@vger.kernel.org
 S:     Supported
 T:     git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
-F:     arch/x86/kvm/xen.*
+F:     arch/x86/include/asm/kvm*
+F:     arch/x86/include/asm/svm.h
+F:     arch/x86/include/asm/vmx*.h
+F:     arch/x86/include/uapi/asm/kvm*
+F:     arch/x86/include/uapi/asm/svm.h
+F:     arch/x86/include/uapi/asm/vmx.h
+F:     arch/x86/kvm/
+F:     arch/x86/kvm/*/
 
 KERNFS
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -11504,14 +11487,6 @@ F:     include/keys/trusted-type.h
 F:     include/keys/trusted_tpm.h
 F:     security/keys/trusted-keys/
 
-KEYS-TRUSTED-TEE
-M:     Sumit Garg <sumit.garg@linaro.org>
-L:     linux-integrity@vger.kernel.org
-L:     keyrings@vger.kernel.org
-S:     Supported
-F:     include/keys/trusted_tee.h
-F:     security/keys/trusted-keys/trusted_tee.c
-
 KEYS-TRUSTED-CAAM
 M:     Ahmad Fatoum <a.fatoum@pengutronix.de>
 R:     Pengutronix Kernel Team <kernel@pengutronix.de>
@@ -11521,6 +11496,14 @@ S:     Maintained
 F:     include/keys/trusted_caam.h
 F:     security/keys/trusted-keys/trusted_caam.c
 
+KEYS-TRUSTED-TEE
+M:     Sumit Garg <sumit.garg@linaro.org>
+L:     linux-integrity@vger.kernel.org
+L:     keyrings@vger.kernel.org
+S:     Supported
+F:     include/keys/trusted_tee.h
+F:     security/keys/trusted-keys/trusted_tee.c
+
 KEYS/KEYRINGS
 M:     David Howells <dhowells@redhat.com>
 M:     Jarkko Sakkinen <jarkko@kernel.org>
@@ -11583,8 +11566,8 @@ L:      linux-amlogic@lists.infradead.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
 F:     drivers/mfd/khadas-mcu.c
-F:     include/linux/mfd/khadas-mcu.h
 F:     drivers/thermal/khadas_mcu_fan.c
+F:     include/linux/mfd/khadas-mcu.h
 
 KIONIX/ROHM KX022A ACCELEROMETER
 M:     Matti Vaittinen <mazziesaccount@gmail.com>
@@ -11621,8 +11604,8 @@ M:      "David S. Miller" <davem@davemloft.net>
 M:     Masami Hiramatsu <mhiramat@kernel.org>
 L:     linux-kernel@vger.kernel.org
 L:     linux-trace-kernel@vger.kernel.org
-Q:     https://patchwork.kernel.org/project/linux-trace-kernel/list/
 S:     Maintained
+Q:     https://patchwork.kernel.org/project/linux-trace-kernel/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git
 F:     Documentation/trace/kprobes.rst
 F:     include/asm-generic/kprobes.h
@@ -11656,6 +11639,47 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/leds/backlight/kinetic,ktz8866.yaml
 F:     drivers/video/backlight/ktz8866.c
 
+KVM PARAVIRT (KVM/paravirt)
+M:     Paolo Bonzini <pbonzini@redhat.com>
+R:     Wanpeng Li <wanpengli@tencent.com>
+R:     Vitaly Kuznetsov <vkuznets@redhat.com>
+L:     kvm@vger.kernel.org
+S:     Supported
+T:     git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
+F:     arch/um/include/asm/kvm_para.h
+F:     arch/x86/include/asm/kvm_para.h
+F:     arch/x86/include/asm/pvclock-abi.h
+F:     arch/x86/include/uapi/asm/kvm_para.h
+F:     arch/x86/kernel/kvm.c
+F:     arch/x86/kernel/kvmclock.c
+F:     include/asm-generic/kvm_para.h
+F:     include/linux/kvm_para.h
+F:     include/uapi/asm-generic/kvm_para.h
+F:     include/uapi/linux/kvm_para.h
+
+KVM X86 HYPER-V (KVM/hyper-v)
+M:     Vitaly Kuznetsov <vkuznets@redhat.com>
+M:     Sean Christopherson <seanjc@google.com>
+M:     Paolo Bonzini <pbonzini@redhat.com>
+L:     kvm@vger.kernel.org
+S:     Supported
+T:     git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
+F:     arch/x86/kvm/hyperv.*
+F:     arch/x86/kvm/kvm_onhyperv.*
+F:     arch/x86/kvm/svm/hyperv.*
+F:     arch/x86/kvm/svm/svm_onhyperv.*
+F:     arch/x86/kvm/vmx/hyperv.*
+
+KVM X86 Xen (KVM/Xen)
+M:     David Woodhouse <dwmw2@infradead.org>
+M:     Paul Durrant <paul@xen.org>
+M:     Sean Christopherson <seanjc@google.com>
+M:     Paolo Bonzini <pbonzini@redhat.com>
+L:     kvm@vger.kernel.org
+S:     Supported
+T:     git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
+F:     arch/x86/kvm/xen.*
+
 L3MDEV
 M:     David Ahern <dsahern@kernel.org>
 L:     netdev@vger.kernel.org
@@ -11897,9 +11921,9 @@ F:      scripts/spdxexclude
 LINEAR RANGES HELPERS
 M:     Mark Brown <broonie@kernel.org>
 R:     Matti Vaittinen <mazziesaccount@gmail.com>
+F:     include/linux/linear_range.h
 F:     lib/linear_ranges.c
 F:     lib/test_linear_ranges.c
-F:     include/linux/linear_range.h
 
 LINUX FOR POWER MACINTOSH
 M:     Benjamin Herrenschmidt <benh@kernel.crashing.org>
@@ -12026,11 +12050,11 @@ M:    Joel Stanley <joel@jms.id.au>
 S:     Maintained
 F:     Documentation/devicetree/bindings/*/litex,*.yaml
 F:     arch/openrisc/boot/dts/or1klitex.dts
-F:     include/linux/litex.h
-F:     drivers/tty/serial/liteuart.c
-F:     drivers/soc/litex/*
-F:     drivers/net/ethernet/litex/*
 F:     drivers/mmc/host/litex_mmc.c
+F:     drivers/net/ethernet/litex/*
+F:     drivers/soc/litex/*
+F:     drivers/tty/serial/liteuart.c
+F:     include/linux/litex.h
 N:     litex
 
 LIVE PATCHING
@@ -12159,10 +12183,17 @@ R:    WANG Xuerui <kernel@xen0n.name>
 L:     loongarch@lists.linux.dev
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git
-F:     arch/loongarch/
-F:     drivers/*/*loongarch*
 F:     Documentation/loongarch/
 F:     Documentation/translations/zh_CN/loongarch/
+F:     arch/loongarch/
+F:     drivers/*/*loongarch*
+
+LOONGSON GPIO DRIVER
+M:     Yinbo Zhu <zhuyinbo@loongson.cn>
+L:     linux-gpio@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml
+F:     drivers/gpio/gpio-loongson-64bit.c
 
 LOONGSON LS2X I2C DRIVER
 M:     Binbin Zhou <zhoubinbin@loongson.cn>
@@ -12171,6 +12202,14 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/i2c/loongson,ls2x-i2c.yaml
 F:     drivers/i2c/busses/i2c-ls2x.c
 
+LOONGSON-2 SOC SERIES CLOCK DRIVER
+M:     Yinbo Zhu <zhuyinbo@loongson.cn>
+L:     linux-clk@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml
+F:     drivers/clk/clk-loongson2.c
+F:     include/dt-bindings/clock/loongson,ls2k-clk.h
+
 LOONGSON-2 SOC SERIES GUTS DRIVER
 M:     Yinbo Zhu <zhuyinbo@loongson.cn>
 L:     loongarch@lists.linux.dev
@@ -12186,21 +12225,6 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/pinctrl/loongson,ls2k-pinctrl.yaml
 F:     drivers/pinctrl/pinctrl-loongson2.c
 
-LOONGSON GPIO DRIVER
-M:     Yinbo Zhu <zhuyinbo@loongson.cn>
-L:     linux-gpio@vger.kernel.org
-S:     Maintained
-F:     Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml
-F:     drivers/gpio/gpio-loongson-64bit.c
-
-LOONGSON-2 SOC SERIES CLOCK DRIVER
-M:     Yinbo Zhu <zhuyinbo@loongson.cn>
-L:     linux-clk@vger.kernel.org
-S:     Maintained
-F:     Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml
-F:     drivers/clk/clk-loongson2.c
-F:     include/dt-bindings/clock/loongson,ls2k-clk.h
-
 LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
 M:     Sathya Prakash <sathya.prakash@broadcom.com>
 M:     Sreekanth Reddy <sreekanth.reddy@broadcom.com>
@@ -12361,20 +12385,26 @@ MAILBOX API
 M:     Jassi Brar <jassisinghbrar@gmail.com>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
+F:     Documentation/devicetree/bindings/mailbox/
 F:     drivers/mailbox/
+F:     include/dt-bindings/mailbox/
 F:     include/linux/mailbox_client.h
 F:     include/linux/mailbox_controller.h
-F:     include/dt-bindings/mailbox/
-F:     Documentation/devicetree/bindings/mailbox/
 
 MAILBOX ARM MHUv2
 M:     Viresh Kumar <viresh.kumar@linaro.org>
 M:     Tushar Khandelwal <Tushar.Khandelwal@arm.com>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
+F:     Documentation/devicetree/bindings/mailbox/arm,mhuv2.yaml
 F:     drivers/mailbox/arm_mhuv2.c
 F:     include/linux/mailbox/arm_mhuv2_message.h
-F:     Documentation/devicetree/bindings/mailbox/arm,mhuv2.yaml
+
+MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
+M:     Michael Kerrisk <mtk.manpages@gmail.com>
+L:     linux-man@vger.kernel.org
+S:     Maintained
+W:     http://www.kernel.org/doc/man-pages
 
 MANAGEMENT COMPONENT TRANSPORT PROTOCOL (MCTP)
 M:     Jeremy Kerr <jk@codeconstruct.com.au>
@@ -12388,12 +12418,6 @@ F:     include/net/mctpdevice.h
 F:     include/net/netns/mctp.h
 F:     net/mctp/
 
-MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
-M:     Michael Kerrisk <mtk.manpages@gmail.com>
-L:     linux-man@vger.kernel.org
-S:     Maintained
-W:     http://www.kernel.org/doc/man-pages
-
 MAPLE TREE
 M:     Liam R. Howlett <Liam.Howlett@oracle.com>
 L:     linux-mm@kvack.org
@@ -12425,8 +12449,8 @@ F:      include/linux/platform_data/mv88e6xxx.h
 MARVELL ARMADA 3700 PHY DRIVERS
 M:     Miquel Raynal <miquel.raynal@bootlin.com>
 S:     Maintained
-F:     Documentation/devicetree/bindings/phy/phy-mvebu-comphy.txt
 F:     Documentation/devicetree/bindings/phy/marvell,armada-3700-utmi-phy.yaml
+F:     Documentation/devicetree/bindings/phy/phy-mvebu-comphy.txt
 F:     drivers/phy/marvell/phy-mvebu-a3700-comphy.c
 F:     drivers/phy/marvell/phy-mvebu-a3700-utmi.c
 
@@ -12528,6 +12552,13 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/mtd/marvell-nand.txt
 F:     drivers/mtd/nand/raw/marvell_nand.c
 
+MARVELL OCTEON ENDPOINT DRIVER
+M:     Veerasenareddy Burru <vburru@marvell.com>
+M:     Abhijit Ayarekar <aayarekar@marvell.com>
+L:     netdev@vger.kernel.org
+S:     Supported
+F:     drivers/net/ethernet/marvell/octeon_ep
+
 MARVELL OCTEONTX2 PHYSICAL FUNCTION DRIVER
 M:     Sunil Goutham <sgoutham@marvell.com>
 M:     Geetha sowjanya <gakula@marvell.com>
@@ -12575,13 +12606,6 @@ S:     Supported
 F:     Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml
 F:     drivers/mmc/host/sdhci-xenon*
 
-MARVELL OCTEON ENDPOINT DRIVER
-M:     Veerasenareddy Burru <vburru@marvell.com>
-M:     Abhijit Ayarekar <aayarekar@marvell.com>
-L:     netdev@vger.kernel.org
-S:     Supported
-F:     drivers/net/ethernet/marvell/octeon_ep
-
 MATROX FRAMEBUFFER DRIVER
 L:     linux-fbdev@vger.kernel.org
 S:     Orphan
@@ -12781,12 +12805,6 @@ L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/phy/mxl-gpy.c
 
-MCBA MICROCHIP CAN BUS ANALYZER TOOL DRIVER
-R:     Yasushi SHOJI <yashi@spacecubics.com>
-L:     linux-can@vger.kernel.org
-S:     Maintained
-F:     drivers/net/can/usb/mcba_usb.c
-
 MCAN MMIO DEVICE DRIVER
 M:     Chandrasekar Ramakrishnan <rcsekar@samsung.com>
 L:     linux-can@vger.kernel.org
@@ -12796,6 +12814,12 @@ F:     drivers/net/can/m_can/m_can.c
 F:     drivers/net/can/m_can/m_can.h
 F:     drivers/net/can/m_can/m_can_platform.c
 
+MCBA MICROCHIP CAN BUS ANALYZER TOOL DRIVER
+R:     Yasushi SHOJI <yashi@spacecubics.com>
+L:     linux-can@vger.kernel.org
+S:     Maintained
+F:     drivers/net/can/usb/mcba_usb.c
+
 MCP2221A MICROCHIP USB-HID TO I2C BRIDGE DRIVER
 M:     Rishi Gupta <gupt21@gmail.com>
 L:     linux-i2c@vger.kernel.org
@@ -13204,13 +13228,6 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/clock/mediatek,mt7621-sysc.yaml
 F:     drivers/clk/ralink/clk-mt7621.c
 
-MEDIATEK MT7621/28/88 I2C DRIVER
-M:     Stefan Roese <sr@denx.de>
-L:     linux-i2c@vger.kernel.org
-S:     Maintained
-F:     Documentation/devicetree/bindings/i2c/mediatek,mt7621-i2c.yaml
-F:     drivers/i2c/busses/i2c-mt7621.c
-
 MEDIATEK MT7621 PCIE CONTROLLER DRIVER
 M:     Sergio Paracuellos <sergio.paracuellos@gmail.com>
 S:     Maintained
@@ -13223,6 +13240,13 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/phy/mediatek,mt7621-pci-phy.yaml
 F:     drivers/phy/ralink/phy-mt7621-pci.c
 
+MEDIATEK MT7621/28/88 I2C DRIVER
+M:     Stefan Roese <sr@denx.de>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/i2c/mediatek,mt7621-i2c.yaml
+F:     drivers/i2c/busses/i2c-mt7621.c
+
 MEDIATEK NAND CONTROLLER DRIVER
 L:     linux-mtd@lists.infradead.org
 S:     Orphan
@@ -13482,10 +13506,22 @@ MEMORY FREQUENCY SCALING DRIVERS FOR NVIDIA TEGRA
 M:     Dmitry Osipenko <digetx@gmail.com>
 L:     linux-pm@vger.kernel.org
 L:     linux-tegra@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git
 S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git
 F:     drivers/devfreq/tegra30-devfreq.c
 
+MEMORY HOT(UN)PLUG
+M:     David Hildenbrand <david@redhat.com>
+M:     Oscar Salvador <osalvador@suse.de>
+L:     linux-mm@kvack.org
+S:     Maintained
+F:     Documentation/admin-guide/mm/memory-hotplug.rst
+F:     Documentation/core-api/memory-hotplug.rst
+F:     drivers/base/memory.c
+F:     include/linux/memory_hotplug.h
+F:     mm/memory_hotplug.c
+F:     tools/testing/selftests/memory-hotplug/
+
 MEMORY MANAGEMENT
 M:     Andrew Morton <akpm@linux-foundation.org>
 L:     linux-mm@kvack.org
@@ -13504,30 +13540,6 @@ F:     mm/
 F:     tools/mm/
 F:     tools/testing/selftests/mm/
 
-VMALLOC
-M:     Andrew Morton <akpm@linux-foundation.org>
-R:     Uladzislau Rezki <urezki@gmail.com>
-R:     Christoph Hellwig <hch@infradead.org>
-R:     Lorenzo Stoakes <lstoakes@gmail.com>
-L:     linux-mm@kvack.org
-S:     Maintained
-W:     http://www.linux-mm.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
-F:     include/linux/vmalloc.h
-F:     mm/vmalloc.c
-
-MEMORY HOT(UN)PLUG
-M:     David Hildenbrand <david@redhat.com>
-M:     Oscar Salvador <osalvador@suse.de>
-L:     linux-mm@kvack.org
-S:     Maintained
-F:     Documentation/admin-guide/mm/memory-hotplug.rst
-F:     Documentation/core-api/memory-hotplug.rst
-F:     drivers/base/memory.c
-F:     include/linux/memory_hotplug.h
-F:     mm/memory_hotplug.c
-F:     tools/testing/selftests/memory-hotplug/
-
 MEMORY TECHNOLOGY DEVICES (MTD)
 M:     Miquel Raynal <miquel.raynal@bootlin.com>
 M:     Richard Weinberger <richard@nod.at>
@@ -13638,6 +13650,12 @@ W:     http://www.monstr.eu/fdt/
 T:     git git://git.monstr.eu/linux-2.6-microblaze.git
 F:     arch/microblaze/
 
+MICROBLAZE TMR INJECT
+M:     Appana Durga Kedareswara rao <appana.durga.kedareswara.rao@amd.com>
+S:     Supported
+F:     Documentation/devicetree/bindings/misc/xlnx,tmr-inject.yaml
+F:     drivers/misc/xilinx_tmr_inject.c
+
 MICROBLAZE TMR MANAGER
 M:     Appana Durga Kedareswara rao <appana.durga.kedareswara.rao@amd.com>
 S:     Supported
@@ -13645,12 +13663,6 @@ F:     Documentation/ABI/testing/sysfs-driver-xilinx-tmr-manager
 F:     Documentation/devicetree/bindings/misc/xlnx,tmr-manager.yaml
 F:     drivers/misc/xilinx_tmr_manager.c
 
-MICROBLAZE TMR INJECT
-M:     Appana Durga Kedareswara rao <appana.durga.kedareswara.rao@amd.com>
-S:     Supported
-F:     Documentation/devicetree/bindings/misc/xlnx,tmr-inject.yaml
-F:     drivers/misc/xilinx_tmr_inject.c
-
 MICROCHIP AT91 DMA DRIVERS
 M:     Ludovic Desroches <ludovic.desroches@microchip.com>
 M:     Tudor Ambarus <tudor.ambarus@linaro.org>
@@ -13726,10 +13738,10 @@ L:    linux-media@vger.kernel.org
 S:     Supported
 F:     Documentation/devicetree/bindings/media/atmel,isc.yaml
 F:     Documentation/devicetree/bindings/media/microchip,xisc.yaml
-F:     drivers/staging/media/deprecated/atmel/atmel-isc*
-F:     drivers/staging/media/deprecated/atmel/atmel-sama*-isc*
 F:     drivers/media/platform/microchip/microchip-isc*
 F:     drivers/media/platform/microchip/microchip-sama*-isc*
+F:     drivers/staging/media/deprecated/atmel/atmel-isc*
+F:     drivers/staging/media/deprecated/atmel/atmel-sama*-isc*
 F:     include/linux/atmel-isc-media.h
 
 MICROCHIP ISI DRIVER
@@ -13748,15 +13760,8 @@ F:     Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml
 F:     Documentation/devicetree/bindings/net/dsa/microchip,lan937x.yaml
 F:     drivers/net/dsa/microchip/*
 F:     include/linux/dsa/ksz_common.h
-F:     include/linux/platform_data/microchip-ksz.h
-F:     net/dsa/tag_ksz.c
-
-MICROCHIP LAN87xx/LAN937x T1 PHY DRIVER
-M:     Arun Ramadoss <arun.ramadoss@microchip.com>
-R:     UNGLinuxDriver@microchip.com
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     drivers/net/phy/microchip_t1.c
+F:     include/linux/platform_data/microchip-ksz.h
+F:     net/dsa/tag_ksz.c
 
 MICROCHIP LAN743X ETHERNET DRIVER
 M:     Bryan Whitehead <bryan.whitehead@microchip.com>
@@ -13765,6 +13770,13 @@ L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/microchip/lan743x_*
 
+MICROCHIP LAN87xx/LAN937x T1 PHY DRIVER
+M:     Arun Ramadoss <arun.ramadoss@microchip.com>
+R:     UNGLinuxDriver@microchip.com
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/phy/microchip_t1.c
+
 MICROCHIP LAN966X ETHERNET DRIVER
 M:     Horatiu Vultur <horatiu.vultur@microchip.com>
 M:     UNGLinuxDriver@microchip.com
@@ -13806,14 +13818,6 @@ S:     Supported
 F:     Documentation/devicetree/bindings/mtd/atmel-nand.txt
 F:     drivers/mtd/nand/raw/atmel/*
 
-MICROCHIP PCI1XXXX GP DRIVER
-M:     Kumaravel Thiagarajan <kumaravel.thiagarajan@microchip.com>
-L:     linux-gpio@vger.kernel.org
-S:     Supported
-F:     drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c
-F:     drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.h
-F:     drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c
-
 MICROCHIP OTPC DRIVER
 M:     Claudiu Beznea <claudiu.beznea@microchip.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -13822,6 +13826,14 @@ F:     Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
 F:     drivers/nvmem/microchip-otpc.c
 F:     include/dt-bindings/nvmem/microchip,sama7g5-otpc.h
 
+MICROCHIP PCI1XXXX GP DRIVER
+M:     Kumaravel Thiagarajan <kumaravel.thiagarajan@microchip.com>
+L:     linux-gpio@vger.kernel.org
+S:     Supported
+F:     drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c
+F:     drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.h
+F:     drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c
+
 MICROCHIP PCI1XXXX I2C DRIVER
 M:     Tharun Kumar P <tharunkumar.pasumarthi@microchip.com>
 M:     Kumaravel Thiagarajan <kumaravel.thiagarajan@microchip.com>
@@ -13837,6 +13849,14 @@ L:     linux-serial@vger.kernel.org
 S:     Maintained
 F:     drivers/tty/serial/8250/8250_pci1xxxx.c
 
+MICROCHIP POLARFIRE FPGA DRIVERS
+M:     Conor Dooley <conor.dooley@microchip.com>
+R:     Vladimir Georgiev <v.georgiev@metrotek.ru>
+L:     linux-fpga@vger.kernel.org
+S:     Supported
+F:     Documentation/devicetree/bindings/fpga/microchip,mpf-spi-fpga-mgr.yaml
+F:     drivers/fpga/microchip-spi.c
+
 MICROCHIP PWM DRIVER
 M:     Claudiu Beznea <claudiu.beznea@microchip.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -13858,6 +13878,12 @@ M:     Claudiu Beznea <claudiu.beznea@microchip.com>
 S:     Supported
 F:     drivers/power/reset/at91-sama5d2_shdwc.c
 
+MICROCHIP SOC DRIVERS
+M:     Conor Dooley <conor@kernel.org>
+S:     Supported
+T:     git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
+F:     drivers/soc/microchip/
+
 MICROCHIP SPI DRIVER
 M:     Tudor Ambarus <tudor.ambarus@linaro.org>
 S:     Supported
@@ -13871,11 +13897,12 @@ F:    Documentation/devicetree/bindings/misc/atmel-ssc.txt
 F:     drivers/misc/atmel-ssc.c
 F:     include/linux/atmel-ssc.h
 
-MICROCHIP SOC DRIVERS
-M:     Conor Dooley <conor@kernel.org>
-S:     Supported
-T:     git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
-F:     drivers/soc/microchip/
+Microchip Timer Counter Block (TCB) Capture Driver
+M:     Kamel Bouhara <kamel.bouhara@bootlin.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:     linux-iio@vger.kernel.org
+S:     Maintained
+F:     drivers/counter/microchip-tcb-capture.c
 
 MICROCHIP USB251XB DRIVER
 M:     Richard Leitner <richard.leitner@skidata.com>
@@ -13992,6 +14019,12 @@ L:     platform-driver-x86@vger.kernel.org
 S:     Supported
 F:     drivers/platform/surface/surfacepro3_button.c
 
+MICROSOFT SURFACE SYSTEM AGGREGATOR HUB DRIVER
+M:     Maximilian Luz <luzmaximilian@gmail.com>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     drivers/platform/surface/surface_aggregator_hub.c
+
 MICROSOFT SURFACE SYSTEM AGGREGATOR SUBSYSTEM
 M:     Maximilian Luz <luzmaximilian@gmail.com>
 L:     platform-driver-x86@vger.kernel.org
@@ -14007,12 +14040,6 @@ F:     include/linux/surface_acpi_notify.h
 F:     include/linux/surface_aggregator/
 F:     include/uapi/linux/surface_aggregator/
 
-MICROSOFT SURFACE SYSTEM AGGREGATOR HUB DRIVER
-M:     Maximilian Luz <luzmaximilian@gmail.com>
-L:     platform-driver-x86@vger.kernel.org
-S:     Maintained
-F:     drivers/platform/surface/surface_aggregator_hub.c
-
 MICROTEK X6 SCANNER
 M:     Oliver Neukum <oliver@neukum.org>
 S:     Maintained
@@ -14178,11 +14205,11 @@ L:    linux-modules@vger.kernel.org
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git modules-next
-F:     include/linux/module.h
 F:     include/linux/kmod.h
+F:     include/linux/module.h
 F:     kernel/module/
-F:     scripts/module*
 F:     lib/test_kmod.c
+F:     scripts/module*
 F:     tools/testing/selftests/kmod/
 
 MONOLITHIC POWER SYSTEM PMIC DRIVER
@@ -14558,6 +14585,7 @@ T:      git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
 F:     Documentation/devicetree/bindings/net/
 F:     drivers/connector/
 F:     drivers/net/
+X:     drivers/net/wireless/
 F:     include/dt-bindings/net/
 F:     include/linux/etherdevice.h
 F:     include/linux/fcdevice.h
@@ -14607,6 +14635,7 @@ B:      mailto:netdev@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
 F:     Documentation/core-api/netlink.rst
+F:     Documentation/netlink/
 F:     Documentation/networking/
 F:     Documentation/process/maintainer-netdev.rst
 F:     Documentation/userspace-api/netlink/
@@ -14621,6 +14650,7 @@ F:      include/uapi/linux/netdevice.h
 F:     lib/net_utils.c
 F:     lib/random32.c
 F:     net/
+X:     net/bluetooth/
 F:     tools/net/
 F:     tools/testing/selftests/net/
 
@@ -14771,6 +14801,7 @@ L:      linux-nfs@vger.kernel.org
 S:     Maintained
 W:     http://client.linux-nfs.org
 T:     git git://git.linux-nfs.org/projects/trondmy/linux-nfs.git
+F:     Documentation/filesystems/nfs/
 F:     fs/lockd/
 F:     fs/nfs/
 F:     fs/nfs_common/
@@ -14780,7 +14811,6 @@ F:      include/linux/sunrpc/
 F:     include/uapi/linux/nfs*
 F:     include/uapi/linux/sunrpc/
 F:     net/sunrpc/
-F:     Documentation/filesystems/nfs/
 
 NILFS2 FILESYSTEM
 M:     Ryusuke Konishi <konishi.ryusuke@gmail.com>
@@ -14920,6 +14950,7 @@ F:      drivers/ntb/hw/intel/
 
 NTFS FILESYSTEM
 M:     Anton Altaparmakov <anton@tuxera.com>
+R:     Namjae Jeon <linkinjeon@kernel.org>
 L:     linux-ntfs-dev@lists.sourceforge.net
 S:     Supported
 W:     http://www.tuxera.com/
@@ -14984,12 +15015,6 @@ F:     drivers/nvme/target/auth.c
 F:     drivers/nvme/target/fabrics-cmd-auth.c
 F:     include/linux/nvme-auth.h
 
-NVM EXPRESS HARDWARE MONITORING SUPPORT
-M:     Guenter Roeck <linux@roeck-us.net>
-L:     linux-nvme@lists.infradead.org
-S:     Supported
-F:     drivers/nvme/host/hwmon.c
-
 NVM EXPRESS FC TRANSPORT DRIVERS
 M:     James Smart <james.smart@broadcom.com>
 L:     linux-nvme@lists.infradead.org
@@ -15000,6 +15025,12 @@ F:     drivers/nvme/target/fcloop.c
 F:     include/linux/nvme-fc-driver.h
 F:     include/linux/nvme-fc.h
 
+NVM EXPRESS HARDWARE MONITORING SUPPORT
+M:     Guenter Roeck <linux@roeck-us.net>
+L:     linux-nvme@lists.infradead.org
+S:     Supported
+F:     drivers/nvme/host/hwmon.c
+
 NVM EXPRESS TARGET DRIVER
 M:     Christoph Hellwig <hch@lst.de>
 M:     Sagi Grimberg <sagi@grimberg.me>
@@ -15020,6 +15051,13 @@ F:     drivers/nvmem/
 F:     include/linux/nvmem-consumer.h
 F:     include/linux/nvmem-provider.h
 
+NXP BLUETOOTH WIRELESS DRIVERS
+M:     Amitkumar Karwar <amitkumar.karwar@nxp.com>
+M:     Neeraj Kale <neeraj.sanjaykale@nxp.com>
+S:     Maintained
+F:     Documentation/devicetree/bindings/net/bluetooth/nxp,88w8987-bt.yaml
+F:     drivers/bluetooth/btnxpuart.c
+
 NXP C45 TJA11XX PHY DRIVER
 M:     Radu Pirea <radu-nicolae.pirea@oss.nxp.com>
 L:     netdev@vger.kernel.org
@@ -15045,16 +15083,17 @@ F:    drivers/iio/gyro/fxas21002c_core.c
 F:     drivers/iio/gyro/fxas21002c_i2c.c
 F:     drivers/iio/gyro/fxas21002c_spi.c
 
-NXP i.MX CLOCK DRIVERS
-M:     Abel Vesa <abelvesa@kernel.org>
-R:     Peng Fan <peng.fan@nxp.com>
-L:     linux-clk@vger.kernel.org
+NXP i.MX 7D/6SX/6UL/93 AND VF610 ADC DRIVER
+M:     Haibo Chen <haibo.chen@nxp.com>
+L:     linux-iio@vger.kernel.org
 L:     linux-imx@nxp.com
 S:     Maintained
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/abelvesa/linux.git clk/imx
-F:     Documentation/devicetree/bindings/clock/imx*
-F:     drivers/clk/imx/
-F:     include/dt-bindings/clock/imx*
+F:     Documentation/devicetree/bindings/iio/adc/fsl,imx7d-adc.yaml
+F:     Documentation/devicetree/bindings/iio/adc/fsl,vf610-adc.yaml
+F:     Documentation/devicetree/bindings/iio/adc/nxp,imx93-adc.yaml
+F:     drivers/iio/adc/imx7d_adc.c
+F:     drivers/iio/adc/imx93_adc.c
+F:     drivers/iio/adc/vf610_adc.c
 
 NXP i.MX 8M ISI DRIVER
 M:     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
@@ -15063,6 +15102,15 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/media/nxp,imx8-isi.yaml
 F:     drivers/media/platform/nxp/imx8-isi/
 
+NXP i.MX 8MP DW100 V4L2 DRIVER
+M:     Xavier Roumegue <xavier.roumegue@oss.nxp.com>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/media/nxp,dw100.yaml
+F:     Documentation/userspace-api/media/drivers/dw100.rst
+F:     drivers/media/platform/nxp/dw100/
+F:     include/uapi/linux/dw100.h
+
 NXP i.MX 8MQ DCSS DRIVER
 M:     Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
 R:     Lucas Stach <l.stach@pengutronix.de>
@@ -15080,17 +15128,24 @@ S:    Maintained
 F:     Documentation/devicetree/bindings/iio/adc/nxp,imx8qxp-adc.yaml
 F:     drivers/iio/adc/imx8qxp-adc.c
 
-NXP i.MX 7D/6SX/6UL/93 AND VF610 ADC DRIVER
-M:     Haibo Chen <haibo.chen@nxp.com>
-L:     linux-iio@vger.kernel.org
+NXP i.MX 8QXP/8QM JPEG V4L2 DRIVER
+M:     Mirela Rabulea <mirela.rabulea@nxp.com>
+R:     NXP Linux Team <linux-imx@nxp.com>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/media/nxp,imx8-jpeg.yaml
+F:     drivers/media/platform/nxp/imx-jpeg
+
+NXP i.MX CLOCK DRIVERS
+M:     Abel Vesa <abelvesa@kernel.org>
+R:     Peng Fan <peng.fan@nxp.com>
+L:     linux-clk@vger.kernel.org
 L:     linux-imx@nxp.com
 S:     Maintained
-F:     Documentation/devicetree/bindings/iio/adc/fsl,imx7d-adc.yaml
-F:     Documentation/devicetree/bindings/iio/adc/fsl,vf610-adc.yaml
-F:     Documentation/devicetree/bindings/iio/adc/nxp,imx93-adc.yaml
-F:     drivers/iio/adc/imx7d_adc.c
-F:     drivers/iio/adc/imx93_adc.c
-F:     drivers/iio/adc/vf610_adc.c
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/abelvesa/linux.git clk/imx
+F:     Documentation/devicetree/bindings/clock/imx*
+F:     drivers/clk/imx/
+F:     include/dt-bindings/clock/imx*
 
 NXP PF8100/PF8121A/PF8200 PMIC REGULATOR DEVICE DRIVER
 M:     Jagan Teki <jagan@amarulasolutions.com>
@@ -15136,34 +15191,17 @@ S:    Maintained
 F:     Documentation/devicetree/bindings/sound/tfa9879.txt
 F:     sound/soc/codecs/tfa9879*
 
-NXP/Goodix TFA989X (TFA1) DRIVER
-M:     Stephan Gerhold <stephan@gerhold.net>
-L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
-S:     Maintained
-F:     Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml
-F:     sound/soc/codecs/tfa989x.c
-
 NXP-NCI NFC DRIVER
 S:     Orphan
 F:     Documentation/devicetree/bindings/net/nfc/nxp,nci.yaml
 F:     drivers/nfc/nxp-nci
 
-NXP i.MX 8MP DW100 V4L2 DRIVER
-M:     Xavier Roumegue <xavier.roumegue@oss.nxp.com>
-L:     linux-media@vger.kernel.org
-S:     Maintained
-F:     Documentation/devicetree/bindings/media/nxp,dw100.yaml
-F:     Documentation/userspace-api/media/drivers/dw100.rst
-F:     drivers/media/platform/nxp/dw100/
-F:     include/uapi/linux/dw100.h
-
-NXP i.MX 8QXP/8QM JPEG V4L2 DRIVER
-M:     Mirela Rabulea <mirela.rabulea@nxp.com>
-R:     NXP Linux Team <linux-imx@nxp.com>
-L:     linux-media@vger.kernel.org
+NXP/Goodix TFA989X (TFA1) DRIVER
+M:     Stephan Gerhold <stephan@gerhold.net>
+L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Maintained
-F:     Documentation/devicetree/bindings/media/nxp,imx8-jpeg.yaml
-F:     drivers/media/platform/nxp/imx-jpeg
+F:     Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml
+F:     sound/soc/codecs/tfa989x.c
 
 NZXT-KRAKEN2 HARDWARE MONITORING DRIVER
 M:     Jonas Malaco <jonas@protocubo.io>
@@ -15689,8 +15727,8 @@ M:      Rob Herring <robh+dt@kernel.org>
 M:     Frank Rowand <frowand.list@gmail.com>
 L:     devicetree@vger.kernel.org
 S:     Maintained
-C:     irc://irc.libera.chat/devicetree
 W:     http://www.devicetree.org/
+C:     irc://irc.libera.chat/devicetree
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git
 F:     Documentation/ABI/testing/sysfs-firmware-ofw
 F:     drivers/of/
@@ -15706,8 +15744,8 @@ M:      Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
 M:     Conor Dooley <conor+dt@kernel.org>
 L:     devicetree@vger.kernel.org
 S:     Maintained
-C:     irc://irc.libera.chat/devicetree
 Q:     http://patchwork.ozlabs.org/project/devicetree-bindings/list/
+C:     irc://irc.libera.chat/devicetree
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git
 F:     Documentation/devicetree/
 F:     arch/*/boot/dts/
@@ -15720,13 +15758,6 @@ L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/ptp/ptp_ocp.c
 
-INTEL PTP DFL ToD DRIVER
-M:     Tianfei Zhang <tianfei.zhang@intel.com>
-L:     linux-fpga@vger.kernel.org
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     drivers/ptp/ptp_dfl_tod.c
-
 OPENCORES I2C BUS DRIVER
 M:     Peter Korsgaard <peter@korsgaard.com>
 M:     Andrew Lunn <andrew@lunn.ch>
@@ -15745,8 +15776,8 @@ L:      linux-openrisc@vger.kernel.org
 S:     Maintained
 W:     http://openrisc.io
 T:     git https://github.com/openrisc/linux.git
-F:     Documentation/devicetree/bindings/openrisc/
 F:     Documentation/arch/openrisc/
+F:     Documentation/devicetree/bindings/openrisc/
 F:     arch/openrisc/
 F:     drivers/irqchip/irq-ompic.c
 F:     drivers/irqchip/irq-or1k-*
@@ -16062,6 +16093,14 @@ L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/pci/controller/dwc/*layerscape*
 
+PCI DRIVER FOR FU740
+M:     Paul Walmsley <paul.walmsley@sifive.com>
+M:     Greentime Hu <greentime.hu@sifive.com>
+L:     linux-pci@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml
+F:     drivers/pci/controller/dwc/pcie-fu740.c
+
 PCI DRIVER FOR GENERIC OF HOSTS
 M:     Will Deacon <will@kernel.org>
 L:     linux-pci@vger.kernel.org
@@ -16082,14 +16121,6 @@ F:     Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-ep.yaml
 F:     Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
 F:     drivers/pci/controller/dwc/*imx6*
 
-PCI DRIVER FOR FU740
-M:     Paul Walmsley <paul.walmsley@sifive.com>
-M:     Greentime Hu <greentime.hu@sifive.com>
-L:     linux-pci@vger.kernel.org
-S:     Maintained
-F:     Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml
-F:     drivers/pci/controller/dwc/pcie-fu740.c
-
 PCI DRIVER FOR INTEL IXP4XX
 M:     Linus Walleij <linus.walleij@linaro.org>
 S:     Maintained
@@ -16169,8 +16200,8 @@ M:      Jingoo Han <jingoohan1@gmail.com>
 M:     Gustavo Pimentel <gustavo.pimentel@synopsys.com>
 L:     linux-pci@vger.kernel.org
 S:     Maintained
-F:     Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
 F:     Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml
+F:     Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
 F:     drivers/pci/controller/dwc/*designware*
 
 PCI DRIVER FOR TI DRA7XX/J721E
@@ -16190,6 +16221,14 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/pci/v3-v360epc-pci.txt
 F:     drivers/pci/controller/pci-v3-semi.c
 
+PCI DRIVER FOR XILINX VERSAL CPM
+M:     Bharat Kumar Gogada <bharat.kumar.gogada@amd.com>
+M:     Michal Simek <michal.simek@amd.com>
+L:     linux-pci@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml
+F:     drivers/pci/controller/pcie-xilinx-cpm.c
+
 PCI ENDPOINT SUBSYSTEM
 M:     Lorenzo Pieralisi <lpieralisi@kernel.org>
 M:     Krzysztof WilczyÅ„ski <kw@linux.com>
@@ -16227,19 +16266,6 @@ L:     linux-pci@vger.kernel.org
 S:     Supported
 F:     Documentation/PCI/pci-error-recovery.rst
 
-PCI PEER-TO-PEER DMA (P2PDMA)
-M:     Bjorn Helgaas <bhelgaas@google.com>
-M:     Logan Gunthorpe <logang@deltatee.com>
-L:     linux-pci@vger.kernel.org
-S:     Supported
-Q:     https://patchwork.kernel.org/project/linux-pci/list/
-B:     https://bugzilla.kernel.org
-C:     irc://irc.oftc.net/linux-pci
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git
-F:     Documentation/driver-api/pci/p2pdma.rst
-F:     drivers/pci/p2pdma.c
-F:     include/linux/pci-p2pdma.h
-
 PCI MSI DRIVER FOR ALTERA MSI IP
 M:     Joyce Ooi <joyce.ooi@intel.com>
 L:     linux-pci@vger.kernel.org
@@ -16270,6 +16296,19 @@ F:     drivers/pci/controller/
 F:     drivers/pci/pci-bridge-emul.c
 F:     drivers/pci/pci-bridge-emul.h
 
+PCI PEER-TO-PEER DMA (P2PDMA)
+M:     Bjorn Helgaas <bhelgaas@google.com>
+M:     Logan Gunthorpe <logang@deltatee.com>
+L:     linux-pci@vger.kernel.org
+S:     Supported
+Q:     https://patchwork.kernel.org/project/linux-pci/list/
+B:     https://bugzilla.kernel.org
+C:     irc://irc.oftc.net/linux-pci
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git
+F:     Documentation/driver-api/pci/p2pdma.rst
+F:     drivers/pci/p2pdma.c
+F:     include/linux/pci-p2pdma.h
+
 PCI SUBSYSTEM
 M:     Bjorn Helgaas <bhelgaas@google.com>
 L:     linux-pci@vger.kernel.org
@@ -16378,14 +16417,6 @@ L:     linux-arm-msm@vger.kernel.org
 S:     Maintained
 F:     drivers/pci/controller/dwc/pcie-qcom.c
 
-PCIE ENDPOINT DRIVER FOR QUALCOMM
-M:     Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
-L:     linux-pci@vger.kernel.org
-L:     linux-arm-msm@vger.kernel.org
-S:     Maintained
-F:     Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml
-F:     drivers/pci/controller/dwc/pcie-qcom-ep.c
-
 PCIE DRIVER FOR ROCKCHIP
 M:     Shawn Lin <shawn.lin@rock-chips.com>
 L:     linux-pci@vger.kernel.org
@@ -16407,13 +16438,13 @@ L:    linux-pci@vger.kernel.org
 S:     Maintained
 F:     drivers/pci/controller/dwc/*spear*
 
-PCI DRIVER FOR XILINX VERSAL CPM
-M:     Bharat Kumar Gogada <bharat.kumar.gogada@amd.com>
-M:     Michal Simek <michal.simek@amd.com>
+PCIE ENDPOINT DRIVER FOR QUALCOMM
+M:     Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
 L:     linux-pci@vger.kernel.org
+L:     linux-arm-msm@vger.kernel.org
 S:     Maintained
-F:     Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml
-F:     drivers/pci/controller/pcie-xilinx-cpm.c
+F:     Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml
+F:     drivers/pci/controller/dwc/pcie-qcom-ep.c
 
 PCMCIA SUBSYSTEM
 M:     Dominik Brodowski <linux@dominikbrodowski.net>
@@ -16683,9 +16714,9 @@ R:      Alim Akhtar <alim.akhtar@samsung.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-samsung-soc@vger.kernel.org
 S:     Maintained
-C:     irc://irc.libera.chat/linux-exynos
 Q:     https://patchwork.kernel.org/project/linux-samsung-soc/list/
 B:     mailto:linux-samsung-soc@vger.kernel.org
+C:     irc://irc.libera.chat/linux-exynos
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/samsung.git
 F:     Documentation/devicetree/bindings/pinctrl/samsung,pinctrl*yaml
 F:     drivers/pinctrl/samsung/
@@ -16747,13 +16778,6 @@ M:     Logan Gunthorpe <logang@deltatee.com>
 S:     Maintained
 F:     drivers/dma/plx_dma.c
 
-PM6764TR DRIVER
-M:     Charles Hsu     <hsu.yungteng@gmail.com>
-L:     linux-hwmon@vger.kernel.org
-S:     Maintained
-F:     Documentation/hwmon/pm6764tr.rst
-F:     drivers/hwmon/pmbus/pm6764tr.c
-
 PM-GRAPH UTILITY
 M:     "Todd E Brandt" <todd.e.brandt@linux.intel.com>
 L:     linux-pm@vger.kernel.org
@@ -16763,6 +16787,13 @@ B:     https://bugzilla.kernel.org/buglist.cgi?component=pm-graph&product=Tools
 T:     git git://github.com/intel/pm-graph
 F:     tools/power/pm-graph
 
+PM6764TR DRIVER
+M:     Charles Hsu     <hsu.yungteng@gmail.com>
+L:     linux-hwmon@vger.kernel.org
+S:     Maintained
+F:     Documentation/hwmon/pm6764tr.rst
+F:     drivers/hwmon/pmbus/pm6764tr.c
+
 PMBUS HARDWARE MONITORING DRIVERS
 M:     Guenter Roeck <linux@roeck-us.net>
 L:     linux-hwmon@vger.kernel.org
@@ -16843,15 +16874,6 @@ F:     include/linux/pm_*
 F:     include/linux/powercap.h
 F:     kernel/configs/nopm.config
 
-DYNAMIC THERMAL POWER MANAGEMENT (DTPM)
-M:     Daniel Lezcano <daniel.lezcano@kernel.org>
-L:     linux-pm@vger.kernel.org
-S:     Supported
-B:     https://bugzilla.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
-F:     drivers/powercap/dtpm*
-F:     include/linux/dtpm.h
-
 POWER STATE COORDINATION INTERFACE (PSCI)
 M:     Mark Rutland <mark.rutland@arm.com>
 M:     Lorenzo Pieralisi <lpieralisi@kernel.org>
@@ -17010,8 +17032,8 @@ R:      Guilherme G. Piccoli <gpiccoli@igalia.com>
 L:     linux-hardening@vger.kernel.org
 S:     Supported
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/pstore
-F:     Documentation/admin-guide/ramoops.rst
 F:     Documentation/admin-guide/pstore-blk.rst
+F:     Documentation/admin-guide/ramoops.rst
 F:     Documentation/devicetree/bindings/reserved-memory/ramoops.yaml
 F:     drivers/acpi/apei/erst.c
 F:     drivers/firmware/efi/efi-pstore.c
@@ -17160,10 +17182,10 @@ F:    sound/soc/codecs/lpass-va-macro.c
 F:     sound/soc/codecs/lpass-wsa-macro.*
 F:     sound/soc/codecs/msm8916-wcd-analog.c
 F:     sound/soc/codecs/msm8916-wcd-digital.c
-F:     sound/soc/codecs/wcd9335.*
-F:     sound/soc/codecs/wcd934x.c
 F:     sound/soc/codecs/wcd-clsh-v2.*
 F:     sound/soc/codecs/wcd-mbhc-v2.*
+F:     sound/soc/codecs/wcd9335.*
+F:     sound/soc/codecs/wcd934x.c
 F:     sound/soc/codecs/wsa881x.c
 F:     sound/soc/codecs/wsa883x.c
 F:     sound/soc/qcom/
@@ -17320,14 +17342,21 @@ Q:    http://patchwork.linuxtv.org/project/linux-media/list/
 T:     git git://linuxtv.org/anttip/media_tree.git
 F:     drivers/media/tuners/qt1010*
 
+QUALCOMM ATH12K WIRELESS DRIVER
+M:     Kalle Valo <kvalo@kernel.org>
+L:     ath12k@lists.infradead.org
+S:     Supported
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
+F:     drivers/net/wireless/ath/ath12k/
+
 QUALCOMM ATHEROS ATH10K WIRELESS DRIVER
 M:     Kalle Valo <kvalo@kernel.org>
 L:     ath10k@lists.infradead.org
 S:     Supported
 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/
 F:     Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
+F:     drivers/net/wireless/ath/ath10k/
 
 QUALCOMM ATHEROS ATH11K WIRELESS DRIVER
 M:     Kalle Valo <kvalo@kernel.org>
@@ -17337,13 +17366,6 @@ T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
 F:     Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml
 F:     drivers/net/wireless/ath/ath11k/
 
-QUALCOMM ATH12K WIRELESS DRIVER
-M:     Kalle Valo <kvalo@kernel.org>
-L:     ath12k@lists.infradead.org
-S:     Supported
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
-F:     drivers/net/wireless/ath/ath12k/
-
 QUALCOMM ATHEROS ATH9K WIRELESS DRIVER
 M:     Toke Høiland-Jørgensen <toke@toke.dk>
 L:     linux-wireless@vger.kernel.org
@@ -17440,8 +17462,8 @@ F:      include/uapi/misc/fastrpc.h
 QUALCOMM HEXAGON ARCHITECTURE
 M:     Brian Cain <bcain@quicinc.com>
 L:     linux-hexagon@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bcain/linux.git
 S:     Supported
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bcain/linux.git
 F:     arch/hexagon/
 
 QUALCOMM HIDMA DRIVER
@@ -17563,9 +17585,9 @@ M:      Christian König <christian.koenig@amd.com>
 M:     Pan, Xinhui <Xinhui.Pan@amd.com>
 L:     amd-gfx@lists.freedesktop.org
 S:     Supported
-T:     git https://gitlab.freedesktop.org/agd5f/linux.git
 B:     https://gitlab.freedesktop.org/drm/amd/-/issues
 C:     irc://irc.oftc.net/radeon
+T:     git https://gitlab.freedesktop.org/agd5f/linux.git
 F:     Documentation/gpu/amdgpu/
 F:     drivers/gpu/drm/amd/
 F:     drivers/gpu/drm/radeon/
@@ -17653,8 +17675,8 @@ F:      arch/mips/generic/board-ranchu.c
 RANDOM NUMBER DRIVER
 M:     "Theodore Ts'o" <tytso@mit.edu>
 M:     Jason A. Donenfeld <Jason@zx2c4.com>
-T:     git https://git.kernel.org/pub/scm/linux/kernel/git/crng/random.git
 S:     Maintained
+T:     git https://git.kernel.org/pub/scm/linux/kernel/git/crng/random.git
 F:     drivers/char/random.c
 F:     drivers/virt/vmgenid.c
 
@@ -17688,8 +17710,8 @@ T:      git git://linuxtv.org/media_tree.git
 F:     Documentation/driver-api/media/rc-core.rst
 F:     Documentation/userspace-api/media/rc/
 F:     drivers/media/rc/
-F:     include/media/rc-map.h
 F:     include/media/rc-core.h
+F:     include/media/rc-map.h
 F:     include/uapi/linux/lirc.h
 
 RCMM REMOTE CONTROLS DECODER
@@ -17806,6 +17828,14 @@ F:     include/linux/rtc/
 F:     include/uapi/linux/rtc.h
 F:     tools/testing/selftests/rtc/
 
+Real-time Linux Analysis (RTLA) tools
+M:     Daniel Bristot de Oliveira <bristot@kernel.org>
+M:     Steven Rostedt <rostedt@goodmis.org>
+L:     linux-trace-devel@vger.kernel.org
+S:     Maintained
+F:     Documentation/tools/rtla/
+F:     tools/tracing/rtla/
+
 REALTEK AUDIO CODECS
 M:     Oder Chiou <oder_chiou@realtek.com>
 S:     Maintained
@@ -17929,6 +17959,14 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/sound/renesas,idt821034.yaml
 F:     sound/soc/codecs/idt821034.c
 
+RENESAS R-CAR GEN3 & RZ/N1 NAND CONTROLLER DRIVER
+M:     Miquel Raynal <miquel.raynal@bootlin.com>
+L:     linux-mtd@lists.infradead.org
+L:     linux-renesas-soc@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/mtd/renesas-nandc.yaml
+F:     drivers/mtd/nand/raw/renesas-nand-controller.c
+
 RENESAS R-CAR GYROADC DRIVER
 M:     Marek Vasut <marek.vasut@gmail.com>
 L:     linux-iio@vger.kernel.org
@@ -17947,9 +17985,9 @@ F:      drivers/i2c/busses/i2c-sh_mobile.c
 
 RENESAS R-CAR SATA DRIVER
 R:     Sergey Shtylyov <s.shtylyov@omp.ru>
-S:     Supported
 L:     linux-ide@vger.kernel.org
 L:     linux-renesas-soc@vger.kernel.org
+S:     Supported
 F:     Documentation/devicetree/bindings/ata/renesas,rcar-sata.yaml
 F:     drivers/ata/sata_rcar.c
 
@@ -17969,12 +18007,6 @@ S:     Supported
 F:     Documentation/devicetree/bindings/i2c/renesas,riic.yaml
 F:     drivers/i2c/busses/i2c-riic.c
 
-RENESAS USB PHY DRIVER
-M:     Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-L:     linux-renesas-soc@vger.kernel.org
-S:     Maintained
-F:     drivers/phy/renesas/phy-rcar-gen3-usb*.c
-
 RENESAS RZ/G2L A/D DRIVER
 M:     Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
 L:     linux-iio@vger.kernel.org
@@ -18020,13 +18052,11 @@ S:    Maintained
 F:     Documentation/devicetree/bindings/usb/renesas,rzn1-usbf.yaml
 F:     drivers/usb/gadget/udc/renesas_usbf.c
 
-RENESAS R-CAR GEN3 & RZ/N1 NAND CONTROLLER DRIVER
-M:     Miquel Raynal <miquel.raynal@bootlin.com>
-L:     linux-mtd@lists.infradead.org
+RENESAS USB PHY DRIVER
+M:     Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
 L:     linux-renesas-soc@vger.kernel.org
 S:     Maintained
-F:     Documentation/devicetree/bindings/mtd/renesas-nandc.yaml
-F:     drivers/mtd/nand/raw/renesas-nand-controller.c
+F:     drivers/phy/renesas/phy-rcar-gen3-usb*.c
 
 RENESAS VERSACLOCK 7 CLOCK DRIVER
 M:     Alex Helms <alexander.helms.jy@renesas.com>
@@ -18034,6 +18064,13 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/clock/renesas,versaclock7.yaml
 F:     drivers/clk/clk-versaclock7.c
 
+RENESAS X9250 DIGITAL POTENTIOMETERS DRIVER
+M:     Herve Codina <herve.codina@bootlin.com>
+L:     linux-iio@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/iio/potentiometer/renesas,x9250.yaml
+F:     drivers/iio/potentiometer/x9250.c
+
 RESET CONTROLLER FRAMEWORK
 M:     Philipp Zabel <p.zabel@pengutronix.de>
 S:     Maintained
@@ -18094,15 +18131,6 @@ S:     Maintained
 F:     drivers/mtd/nand/raw/r852.c
 F:     drivers/mtd/nand/raw/r852.h
 
-RISC-V PMU DRIVERS
-M:     Atish Patra <atishp@atishpatra.org>
-R:     Anup Patel <anup@brainfault.org>
-L:     linux-riscv@lists.infradead.org
-S:     Supported
-F:     drivers/perf/riscv_pmu.c
-F:     drivers/perf/riscv_pmu_legacy.c
-F:     drivers/perf/riscv_pmu_sbi.c
-
 RISC-V ARCHITECTURE
 M:     Paul Walmsley <paul.walmsley@sifive.com>
 M:     Palmer Dabbelt <palmer@dabbelt.com>
@@ -18155,6 +18183,15 @@ T:     git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
 F:     Documentation/devicetree/bindings/riscv/
 F:     arch/riscv/boot/dts/
 
+RISC-V PMU DRIVERS
+M:     Atish Patra <atishp@atishpatra.org>
+R:     Anup Patel <anup@brainfault.org>
+L:     linux-riscv@lists.infradead.org
+S:     Supported
+F:     drivers/perf/riscv_pmu.c
+F:     drivers/perf/riscv_pmu_legacy.c
+F:     drivers/perf/riscv_pmu_sbi.c
+
 RNBD BLOCK DRIVERS
 M:     Md. Haris Iqbal <haris.iqbal@ionos.com>
 M:     Jack Wang <jinpu.wang@ionos.com>
@@ -18236,10 +18273,11 @@ S:    Maintained
 F:     Documentation/devicetree/bindings/iio/light/bh1750.yaml
 F:     drivers/iio/light/bh1750.c
 
-ROHM BU27034 AMBIENT LIGHT SENSOR DRIVER
+ROHM BU270xx LIGHT SENSOR DRIVERs
 M:     Matti Vaittinen <mazziesaccount@gmail.com>
 L:     linux-iio@vger.kernel.org
 S:     Supported
+F:     drivers/iio/light/rohm-bu27008.c
 F:     drivers/iio/light/rohm-bu27034.c
 
 ROHM MULTIFUNCTION BD9571MWV-M PMIC DEVICE DRIVERS
@@ -18459,14 +18497,6 @@ F:     drivers/s390/net/*iucv*
 F:     include/net/iucv/
 F:     net/iucv/
 
-S390 NETWORK DRIVERS
-M:     Alexandra Winter <wintera@linux.ibm.com>
-M:     Wenjia Zhang <wenjia@linux.ibm.com>
-L:     linux-s390@vger.kernel.org
-L:     netdev@vger.kernel.org
-S:     Supported
-F:     drivers/s390/net/
-
 S390 MM
 M:     Alexander Gordeev <agordeev@linux.ibm.com>
 M:     Gerald Schaefer <gerald.schaefer@linux.ibm.com>
@@ -18476,14 +18506,22 @@ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git
 F:     arch/s390/include/asm/pgtable.h
 F:     arch/s390/mm
 
+S390 NETWORK DRIVERS
+M:     Alexandra Winter <wintera@linux.ibm.com>
+M:     Wenjia Zhang <wenjia@linux.ibm.com>
+L:     linux-s390@vger.kernel.org
+L:     netdev@vger.kernel.org
+S:     Supported
+F:     drivers/s390/net/
+
 S390 PCI SUBSYSTEM
 M:     Niklas Schnelle <schnelle@linux.ibm.com>
 M:     Gerald Schaefer <gerald.schaefer@linux.ibm.com>
 L:     linux-s390@vger.kernel.org
 S:     Supported
+F:     Documentation/s390/pci.rst
 F:     arch/s390/pci/
 F:     drivers/pci/hotplug/s390_pci_hpc.c
-F:     Documentation/s390/pci.rst
 
 S390 SCM DRIVER
 M:     Vineeth Vijayan <vneethv@linux.ibm.com>
@@ -18568,10 +18606,9 @@ F:     Documentation/admin-guide/LSM/SafeSetID.rst
 F:     security/safesetid/
 
 SAMSUNG AUDIO (ASoC) DRIVERS
-M:     Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
 M:     Sylwester Nawrocki <s.nawrocki@samsung.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
-S:     Supported
+S:     Maintained
 B:     mailto:linux-samsung-soc@vger.kernel.org
 F:     Documentation/devicetree/bindings/sound/samsung*
 F:     sound/soc/samsung/
@@ -18699,7 +18736,6 @@ F:      include/dt-bindings/clock/samsung,*.h
 F:     include/linux/clk/samsung.h
 
 SAMSUNG SPI DRIVERS
-M:     Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
 M:     Andi Shyti <andi.shyti@kernel.org>
 L:     linux-spi@vger.kernel.org
 L:     linux-samsung-soc@vger.kernel.org
@@ -18835,12 +18871,11 @@ F:    drivers/target/
 F:     include/target/
 
 SCTP PROTOCOL
-M:     Neil Horman <nhorman@tuxdriver.com>
 M:     Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
 M:     Xin Long <lucien.xin@gmail.com>
 L:     linux-sctp@vger.kernel.org
 S:     Maintained
-W:     http://lksctp.sourceforge.net
+W:     https://github.com/sctp/lksctp-tools/wiki
 F:     Documentation/networking/sctp.rst
 F:     include/linux/sctp.h
 F:     include/net/sctp/
@@ -18916,6 +18951,13 @@ L:     linux-mmc@vger.kernel.org
 S:     Supported
 F:     drivers/mmc/host/sdhci-of-at91.c
 
+SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) NXP i.MX DRIVER
+M:     Haibo Chen <haibo.chen@nxp.com>
+L:     linux-imx@nxp.com
+L:     linux-mmc@vger.kernel.org
+S:     Maintained
+F:     drivers/mmc/host/sdhci-esdhc-imx.c
+
 SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER
 M:     Ben Dooks <ben-linux@fluff.org>
 M:     Jaehoon Chung <jh80.chung@samsung.com>
@@ -18935,13 +18977,6 @@ L:     linux-mmc@vger.kernel.org
 S:     Maintained
 F:     drivers/mmc/host/sdhci-omap.c
 
-SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) NXP i.MX DRIVER
-M:     Haibo Chen <haibo.chen@nxp.com>
-L:     linux-imx@nxp.com
-L:     linux-mmc@vger.kernel.org
-S:     Maintained
-F:     drivers/mmc/host/sdhci-esdhc-imx.c
-
 SECURE ENCRYPTING DEVICE (SED) OPAL DRIVER
 M:     Jonathan Derrick <jonathan.derrick@linux.dev>
 L:     linux-block@vger.kernel.org
@@ -18951,6 +18986,15 @@ F:     block/sed*
 F:     include/linux/sed*
 F:     include/uapi/linux/sed*
 
+SECURE MONITOR CALL(SMC) CALLING CONVENTION (SMCCC)
+M:     Mark Rutland <mark.rutland@arm.com>
+M:     Lorenzo Pieralisi <lpieralisi@kernel.org>
+M:     Sudeep Holla <sudeep.holla@arm.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     drivers/firmware/smccc/
+F:     include/linux/arm-smccc.h
+
 SECURITY CONTACT
 M:     Security Officers <security@kernel.org>
 S:     Supported
@@ -19400,15 +19444,6 @@ M:     Nicolas Pitre <nico@fluxnic.net>
 S:     Odd Fixes
 F:     drivers/net/ethernet/smsc/smc91x.*
 
-SECURE MONITOR CALL(SMC) CALLING CONVENTION (SMCCC)
-M:     Mark Rutland <mark.rutland@arm.com>
-M:     Lorenzo Pieralisi <lpieralisi@kernel.org>
-M:     Sudeep Holla <sudeep.holla@arm.com>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     Maintained
-F:     drivers/firmware/smccc/
-F:     include/linux/arm-smccc.h
-
 SMM665 HARDWARE MONITOR DRIVER
 M:     Guenter Roeck <linux@roeck-us.net>
 L:     linux-hwmon@vger.kernel.org
@@ -19456,6 +19491,10 @@ L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/smsc/smsc9420.*
 
+SNET DPU VIRTIO DATA PATH ACCELERATOR
+R:     Alvaro Karsz <alvaro.karsz@solid-run.com>
+F:     drivers/vdpa/solidrun/
+
 SOCIONEXT (SNI) AVE NETWORK DRIVER
 M:     Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
 L:     netdev@vger.kernel.org
@@ -19725,6 +19764,13 @@ F:     include/uapi/sound/
 F:     sound/
 F:     tools/testing/selftests/alsa
 
+SOUND - ALSA SELFTESTS
+M:     Mark Brown <broonie@kernel.org>
+L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
+L:     linux-kselftest@vger.kernel.org
+S:     Supported
+F:     tools/testing/selftests/alsa
+
 SOUND - COMPRESSED AUDIO
 M:     Vinod Koul <vkoul@kernel.org>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
@@ -19743,13 +19789,6 @@ F:     include/sound/dmaengine_pcm.h
 F:     sound/core/pcm_dmaengine.c
 F:     sound/soc/soc-generic-dmaengine-pcm.c
 
-SOUND - ALSA SELFTESTS
-M:     Mark Brown <broonie@kernel.org>
-L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
-L:     linux-kselftest@vger.kernel.org
-S:     Supported
-F:     tools/testing/selftests/alsa
-
 SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
 M:     Liam Girdwood <lgirdwood@gmail.com>
 M:     Mark Brown <broonie@kernel.org>
@@ -19769,8 +19808,8 @@ M:      Liam Girdwood <lgirdwood@gmail.com>
 M:     Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
 M:     Bard Liao <yung-chuan.liao@linux.intel.com>
 M:     Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
-R:     Kai Vehmanen <kai.vehmanen@linux.intel.com>
 M:     Daniel Baluta <daniel.baluta@nxp.com>
+R:     Kai Vehmanen <kai.vehmanen@linux.intel.com>
 L:     sound-open-firmware@alsa-project.org (moderated for non-subscribers)
 S:     Supported
 W:     https://github.com/thesofproject/linux/
@@ -19832,9 +19871,9 @@ M:      "Luc Van Oostenryck" <luc.vanoostenryck@gmail.com>
 L:     linux-sparse@vger.kernel.org
 S:     Maintained
 W:     https://sparse.docs.kernel.org/
-T:     git git://git.kernel.org/pub/scm/devel/sparse/sparse.git
 Q:     https://patchwork.kernel.org/project/linux-sparse/list/
 B:     https://bugzilla.kernel.org/enter_bug.cgi?component=Sparse&product=Tools
+T:     git git://git.kernel.org/pub/scm/devel/sparse/sparse.git
 F:     include/linux/compiler.h
 
 SPEAKUP CONSOLE SPEECH DRIVER
@@ -20203,6 +20242,11 @@ W:     http://www.stlinux.com
 F:     Documentation/networking/device_drivers/ethernet/stmicro/
 F:     drivers/net/ethernet/stmicro/stmmac/
 
+SUN HAPPY MEAL ETHERNET DRIVER
+M:     Sean Anderson <seanga2@gmail.com>
+S:     Maintained
+F:     drivers/net/ethernet/sun/sunhme.*
+
 SUN3/3X
 M:     Sam Creasey <sammy@sammy.net>
 S:     Maintained
@@ -20225,11 +20269,6 @@ L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/dlink/sundance.c
 
-SUN HAPPY MEAL ETHERNET DRIVER
-M:     Sean Anderson <seanga2@gmail.com>
-S:     Maintained
-F:     drivers/net/ethernet/sun/sunhme.*
-
 SUNPLUS ETHERNET DRIVER
 M:     Wells Lu <wellslutw@gmail.com>
 L:     netdev@vger.kernel.org
@@ -20251,15 +20290,6 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml
 F:     drivers/nvmem/sunplus-ocotp.c
 
-SUNPLUS USB2 PHY DRIVER
-M:     Vincent Shih <vincent.sunplus@gmail.com>
-L:     linux-usb@vger.kernel.org
-S:     Maintained
-F:     Documentation/devicetree/bindings/phy/sunplus,sp7021-usb2-phy.yaml
-F:     drivers/phy/sunplus/Kconfig
-F:     drivers/phy/sunplus/Makefile
-F:     drivers/phy/sunplus/phy-sunplus-usb2.c
-
 SUNPLUS PWM DRIVER
 M:     Hammer Hsieh <hammerh0314@gmail.com>
 S:     Maintained
@@ -20286,6 +20316,15 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/serial/sunplus,sp7021-uart.yaml
 F:     drivers/tty/serial/sunplus-uart.c
 
+SUNPLUS USB2 PHY DRIVER
+M:     Vincent Shih <vincent.sunplus@gmail.com>
+L:     linux-usb@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/phy/sunplus,sp7021-usb2-phy.yaml
+F:     drivers/phy/sunplus/Kconfig
+F:     drivers/phy/sunplus/Makefile
+F:     drivers/phy/sunplus/phy-sunplus-usb2.c
+
 SUNPLUS WATCHDOG DRIVER
 M:     Xiantao Hu <xt.hu@cqplus1.com>
 L:     linux-watchdog@vger.kernel.org
@@ -20697,6 +20736,14 @@ F:     include/linux/if_team.h
 F:     include/uapi/linux/if_team.h
 F:     tools/testing/selftests/drivers/net/team/
 
+TECHNICAL ADVISORY BOARD PROCESS DOCS
+M:     "Theodore Ts'o" <tytso@mit.edu>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+L:     tech-board-discuss@lists.linux-foundation.org
+S:     Maintained
+F:     Documentation/process/contribution-maturity-model.rst
+F:     Documentation/process/researcher-guidelines.rst
+
 TECHNOLOGIC SYSTEMS TS-5500 PLATFORM SUPPORT
 M:     "Savoir-faire Linux Inc." <kernel@savoirfairelinux.com>
 S:     Maintained
@@ -20776,6 +20823,14 @@ M:     Thierry Reding <thierry.reding@gmail.com>
 S:     Supported
 F:     drivers/pwm/pwm-tegra.c
 
+TEGRA QUAD SPI DRIVER
+M:     Thierry Reding <thierry.reding@gmail.com>
+M:     Jonathan Hunter <jonathanh@nvidia.com>
+M:     Sowjanya Komatineni <skomatineni@nvidia.com>
+L:     linux-tegra@vger.kernel.org
+S:     Maintained
+F:     drivers/spi/spi-tegra210-quad.c
+
 TEGRA SERIAL DRIVER
 M:     Laxman Dewangan <ldewangan@nvidia.com>
 S:     Supported
@@ -20786,14 +20841,6 @@ M:     Laxman Dewangan <ldewangan@nvidia.com>
 S:     Supported
 F:     drivers/spi/spi-tegra*
 
-TEGRA QUAD SPI DRIVER
-M:     Thierry Reding <thierry.reding@gmail.com>
-M:     Jonathan Hunter <jonathanh@nvidia.com>
-M:     Sowjanya Komatineni <skomatineni@nvidia.com>
-L:     linux-tegra@vger.kernel.org
-S:     Maintained
-F:     drivers/spi/spi-tegra210-quad.c
-
 TEGRA VIDEO DRIVER
 M:     Thierry Reding <thierry.reding@gmail.com>
 M:     Jonathan Hunter <jonathanh@nvidia.com>
@@ -20842,13 +20889,6 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/sound/davinci-mcasp-audio.yaml
 F:     sound/soc/ti/
 
-TEXAS INSTRUMENTS' DAC7612 DAC DRIVER
-M:     Ricardo Ribalda <ribalda@kernel.org>
-L:     linux-iio@vger.kernel.org
-S:     Supported
-F:     Documentation/devicetree/bindings/iio/dac/ti,dac7612.yaml
-F:     drivers/iio/dac/ti-dac7612.c
-
 TEXAS INSTRUMENTS DMA DRIVERS
 M:     Peter Ujfalusi <peter.ujfalusi@gmail.com>
 L:     dmaengine@vger.kernel.org
@@ -20857,10 +20897,26 @@ F:    Documentation/devicetree/bindings/dma/ti-dma-crossbar.txt
 F:     Documentation/devicetree/bindings/dma/ti-edma.txt
 F:     Documentation/devicetree/bindings/dma/ti/
 F:     drivers/dma/ti/
-X:     drivers/dma/ti/cppi41.c
+F:     include/linux/dma/k3-psil.h
 F:     include/linux/dma/k3-udma-glue.h
 F:     include/linux/dma/ti-cppi5.h
-F:     include/linux/dma/k3-psil.h
+X:     drivers/dma/ti/cppi41.c
+
+TEXAS INSTRUMENTS TPS23861 PoE PSE DRIVER
+M:     Robert Marko <robert.marko@sartura.hr>
+M:     Luka Perkov <luka.perkov@sartura.hr>
+L:     linux-hwmon@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/hwmon/ti,tps23861.yaml
+F:     Documentation/hwmon/tps23861.rst
+F:     drivers/hwmon/tps23861.c
+
+TEXAS INSTRUMENTS' DAC7612 DAC DRIVER
+M:     Ricardo Ribalda <ribalda@kernel.org>
+L:     linux-iio@vger.kernel.org
+S:     Supported
+F:     Documentation/devicetree/bindings/iio/dac/ti,dac7612.yaml
+F:     drivers/iio/dac/ti-dac7612.c
 
 TEXAS INSTRUMENTS' SYSTEM CONTROL INTERFACE (TISCI) PROTOCOL DRIVER
 M:     Nishanth Menon <nm@ti.com>
@@ -20886,15 +20942,6 @@ F:     include/dt-bindings/soc/ti,sci_pm_domain.h
 F:     include/linux/soc/ti/ti_sci_inta_msi.h
 F:     include/linux/soc/ti/ti_sci_protocol.h
 
-TEXAS INSTRUMENTS TPS23861 PoE PSE DRIVER
-M:     Robert Marko <robert.marko@sartura.hr>
-M:     Luka Perkov <luka.perkov@sartura.hr>
-L:     linux-hwmon@vger.kernel.org
-S:     Maintained
-F:     Documentation/devicetree/bindings/hwmon/ti,tps23861.yaml
-F:     Documentation/hwmon/tps23861.rst
-F:     drivers/hwmon/tps23861.c
-
 TEXAS INSTRUMENTS' TMP117 TEMPERATURE SENSOR DRIVER
 M:     Puranjay Mohan <puranjay12@gmail.com>
 L:     linux-iio@vger.kernel.org
@@ -21371,8 +21418,8 @@ M:      Steven Rostedt <rostedt@goodmis.org>
 M:     Masami Hiramatsu <mhiramat@kernel.org>
 L:     linux-kernel@vger.kernel.org
 L:     linux-trace-kernel@vger.kernel.org
-Q:     https://patchwork.kernel.org/project/linux-trace-kernel/list/
 S:     Maintained
+Q:     https://patchwork.kernel.org/project/linux-trace-kernel/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git
 F:     Documentation/trace/*
 F:     fs/tracefs/
@@ -21400,31 +21447,15 @@ TRACING OS NOISE / LATENCY TRACERS
 M:     Steven Rostedt <rostedt@goodmis.org>
 M:     Daniel Bristot de Oliveira <bristot@kernel.org>
 S:     Maintained
-F:     kernel/trace/trace_osnoise.c
+F:     Documentation/trace/hwlat_detector.rst
+F:     Documentation/trace/osnoise-tracer.rst
+F:     Documentation/trace/timerlat-tracer.rst
+F:     arch/*/kernel/trace.c
 F:     include/trace/events/osnoise.h
 F:     kernel/trace/trace_hwlat.c
 F:     kernel/trace/trace_irqsoff.c
+F:     kernel/trace/trace_osnoise.c
 F:     kernel/trace/trace_sched_wakeup.c
-F:     Documentation/trace/osnoise-tracer.rst
-F:     Documentation/trace/timerlat-tracer.rst
-F:     Documentation/trace/hwlat_detector.rst
-F:     arch/*/kernel/trace.c
-
-Real-time Linux Analysis (RTLA) tools
-M:     Daniel Bristot de Oliveira <bristot@kernel.org>
-M:     Steven Rostedt <rostedt@goodmis.org>
-L:     linux-trace-devel@vger.kernel.org
-S:     Maintained
-F:     Documentation/tools/rtla/
-F:     tools/tracing/rtla/
-
-TECHNICAL ADVISORY BOARD PROCESS DOCS
-M:     "Theodore Ts'o" <tytso@mit.edu>
-M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-L:     tech-board-discuss@lists.linux-foundation.org
-S:     Maintained
-F:     Documentation/process/researcher-guidelines.rst
-F:     Documentation/process/contribution-maturity-model.rst
 
 TRADITIONAL CHINESE DOCUMENTATION
 M:     Hu Haowen <src.res@email.cn>
@@ -21782,8 +21813,8 @@ USB ISP1760 DRIVER
 M:     Rui Miguel Silva <rui.silva@linaro.org>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
-F:     drivers/usb/isp1760/*
 F:     Documentation/devicetree/bindings/usb/nxp,isp1760.yaml
+F:     drivers/usb/isp1760/*
 
 USB LAN78XX ETHERNET DRIVER
 M:     Woojung Huh <woojung.huh@microchip.com>
@@ -21854,6 +21885,13 @@ L:     linux-usb@vger.kernel.org
 S:     Supported
 F:     drivers/usb/class/usblp.c
 
+USB QMI WWAN NETWORK DRIVER
+M:     Bjørn Mork <bjorn@mork.no>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     Documentation/ABI/testing/sysfs-class-net-qmi
+F:     drivers/net/usb/qmi_wwan.c
+
 USB RAW GADGET DRIVER
 R:     Andrey Konovalov <andreyknvl@gmail.com>
 L:     linux-usb@vger.kernel.org
@@ -21862,13 +21900,6 @@ F:     Documentation/usb/raw-gadget.rst
 F:     drivers/usb/gadget/legacy/raw_gadget.c
 F:     include/uapi/linux/usb/raw_gadget.h
 
-USB QMI WWAN NETWORK DRIVER
-M:     Bjørn Mork <bjorn@mork.no>
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     Documentation/ABI/testing/sysfs-class-net-qmi
-F:     drivers/net/usb/qmi_wwan.c
-
 USB RTL8150 DRIVER
 M:     Petko Manolov <petkan@nucleusys.com>
 L:     linux-usb@vger.kernel.org
@@ -22120,6 +22151,12 @@ F:     drivers/vfio/mdev/
 F:     include/linux/mdev.h
 F:     samples/vfio-mdev/
 
+VFIO MLX5 PCI DRIVER
+M:     Yishai Hadas <yishaih@nvidia.com>
+L:     kvm@vger.kernel.org
+S:     Maintained
+F:     drivers/vfio/pci/mlx5/
+
 VFIO PCI DEVICE SPECIFIC DRIVERS
 R:     Jason Gunthorpe <jgg@nvidia.com>
 R:     Yishai Hadas <yishaih@nvidia.com>
@@ -22136,12 +22173,6 @@ L:     kvm@vger.kernel.org
 S:     Maintained
 F:     drivers/vfio/platform/
 
-VFIO MLX5 PCI DRIVER
-M:     Yishai Hadas <yishaih@nvidia.com>
-L:     kvm@vger.kernel.org
-S:     Maintained
-F:     drivers/vfio/pci/mlx5/
-
 VGA_SWITCHEROO
 R:     Lukas Wunner <lukas@wunner.de>
 S:     Maintained
@@ -22151,8 +22182,8 @@ F:      drivers/gpu/vga/vga_switcheroo.c
 F:     include/linux/vga_switcheroo.h
 
 VIA RHINE NETWORK DRIVER
-S:     Maintained
 M:     Kevin Brace <kevinbrace@bracecomputerlab.com>
+S:     Maintained
 F:     drivers/net/ethernet/via/via-rhine.c
 
 VIA SD/MMC CARD CONTROLLER DRIVER
@@ -22204,6 +22235,14 @@ S:     Maintained
 F:     drivers/media/common/videobuf2/*
 F:     include/media/videobuf2-*
 
+VIDTV VIRTUAL DIGITAL TV DRIVER
+M:     Daniel W. S. Almeida <dwlsalmeida@gmail.com>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+W:     https://linuxtv.org
+T:     git git://linuxtv.org/media_tree.git
+F:     drivers/media/test-drivers/vidtv/*
+
 VIMC VIRTUAL MEDIA CONTROLLER DRIVER
 M:     Shuah Khan <skhan@linuxfoundation.org>
 R:     Kieran Bingham <kieran.bingham@ideasonboard.com>
@@ -22233,6 +22272,16 @@ F:     include/uapi/linux/virtio_vsock.h
 F:     net/vmw_vsock/virtio_transport.c
 F:     net/vmw_vsock/virtio_transport_common.c
 
+VIRTIO BALLOON
+M:     "Michael S. Tsirkin" <mst@redhat.com>
+M:     David Hildenbrand <david@redhat.com>
+L:     virtualization@lists.linux-foundation.org
+S:     Maintained
+F:     drivers/virtio/virtio_balloon.c
+F:     include/linux/balloon_compaction.h
+F:     include/uapi/linux/virtio_balloon.h
+F:     mm/balloon_compaction.c
+
 VIRTIO BLOCK AND SCSI DRIVERS
 M:     "Michael S. Tsirkin" <mst@redhat.com>
 M:     Jason Wang <jasowang@redhat.com>
@@ -22275,30 +22324,6 @@ F:     include/linux/vringh.h
 F:     include/uapi/linux/virtio_*.h
 F:     tools/virtio/
 
-VISL VIRTUAL STATELESS DECODER DRIVER
-M:     Daniel Almeida <daniel.almeida@collabora.com>
-L:     linux-media@vger.kernel.org
-S:     Supported
-F:     drivers/media/test-drivers/visl
-
-IFCVF VIRTIO DATA PATH ACCELERATOR
-R:     Zhu Lingshan <lingshan.zhu@intel.com>
-F:     drivers/vdpa/ifcvf/
-
-SNET DPU VIRTIO DATA PATH ACCELERATOR
-R:     Alvaro Karsz <alvaro.karsz@solid-run.com>
-F:     drivers/vdpa/solidrun/
-
-VIRTIO BALLOON
-M:     "Michael S. Tsirkin" <mst@redhat.com>
-M:     David Hildenbrand <david@redhat.com>
-L:     virtualization@lists.linux-foundation.org
-S:     Maintained
-F:     drivers/virtio/virtio_balloon.c
-F:     include/uapi/linux/virtio_balloon.h
-F:     include/linux/balloon_compaction.h
-F:     mm/balloon_compaction.c
-
 VIRTIO CRYPTO DRIVER
 M:     Gonglei <arei.gonglei@huawei.com>
 L:     virtualization@lists.linux-foundation.org
@@ -22359,11 +22384,20 @@ L:    virtualization@lists.linux-foundation.org
 L:     netdev@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git
-F:     kernel/vhost_task.c
 F:     drivers/vhost/
 F:     include/linux/sched/vhost_task.h
 F:     include/linux/vhost_iotlb.h
 F:     include/uapi/linux/vhost.h
+F:     kernel/vhost_task.c
+
+VIRTIO I2C DRIVER
+M:     Conghui Chen <conghui.chen@intel.com>
+M:     Viresh Kumar <viresh.kumar@linaro.org>
+L:     linux-i2c@vger.kernel.org
+L:     virtualization@lists.linux-foundation.org
+S:     Maintained
+F:     drivers/i2c/busses/i2c-virtio.c
+F:     include/uapi/linux/virtio_i2c.h
 
 VIRTIO INPUT DRIVER
 M:     Gerd Hoffmann <kraxel@redhat.com>
@@ -22386,6 +22420,13 @@ W:     https://virtio-mem.gitlab.io/
 F:     drivers/virtio/virtio_mem.c
 F:     include/uapi/linux/virtio_mem.h
 
+VIRTIO PMEM DRIVER
+M:     Pankaj Gupta <pankaj.gupta.linux@gmail.com>
+L:     virtualization@lists.linux-foundation.org
+S:     Maintained
+F:     drivers/nvdimm/nd_virtio.c
+F:     drivers/nvdimm/virtio_pmem.c
+
 VIRTIO SOUND DRIVER
 M:     Anton Yakovlev <anton.yakovlev@opensynergy.com>
 M:     "Michael S. Tsirkin" <mst@redhat.com>
@@ -22395,22 +22436,6 @@ S:     Maintained
 F:     include/uapi/linux/virtio_snd.h
 F:     sound/virtio/*
 
-VIRTIO I2C DRIVER
-M:     Conghui Chen <conghui.chen@intel.com>
-M:     Viresh Kumar <viresh.kumar@linaro.org>
-L:     linux-i2c@vger.kernel.org
-L:     virtualization@lists.linux-foundation.org
-S:     Maintained
-F:     drivers/i2c/busses/i2c-virtio.c
-F:     include/uapi/linux/virtio_i2c.h
-
-VIRTIO PMEM DRIVER
-M:     Pankaj Gupta <pankaj.gupta.linux@gmail.com>
-L:     virtualization@lists.linux-foundation.org
-S:     Maintained
-F:     drivers/nvdimm/virtio_pmem.c
-F:     drivers/nvdimm/nd_virtio.c
-
 VIRTUAL BOX GUEST DEVICE DRIVER
 M:     Hans de Goede <hdegoede@redhat.com>
 M:     Arnd Bergmann <arnd@arndb.de>
@@ -22432,6 +22457,12 @@ S:     Maintained
 F:     drivers/input/serio/userio.c
 F:     include/uapi/linux/userio.h
 
+VISL VIRTUAL STATELESS DECODER DRIVER
+M:     Daniel Almeida <daniel.almeida@collabora.com>
+L:     linux-media@vger.kernel.org
+S:     Supported
+F:     drivers/media/test-drivers/visl
+
 VIVID VIRTUAL VIDEO DRIVER
 M:     Hans Verkuil <hverkuil@xs4all.nl>
 L:     linux-media@vger.kernel.org
@@ -22440,14 +22471,6 @@ W:     https://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
 F:     drivers/media/test-drivers/vivid/*
 
-VIDTV VIRTUAL DIGITAL TV DRIVER
-M:     Daniel W. S. Almeida <dwlsalmeida@gmail.com>
-L:     linux-media@vger.kernel.org
-S:     Maintained
-W:     https://linuxtv.org
-T:     git git://linuxtv.org/media_tree.git
-F:     drivers/media/test-drivers/vidtv/*
-
 VLYNQ BUS
 M:     Florian Fainelli <f.fainelli@gmail.com>
 L:     openwrt-devel@lists.openwrt.org (subscribers-only)
@@ -22455,16 +22478,6 @@ S:     Maintained
 F:     drivers/vlynq/vlynq.c
 F:     include/linux/vlynq.h
 
-VME SUBSYSTEM
-M:     Martyn Welch <martyn@welchs.me.uk>
-M:     Manohar Vanga <manohar.vanga@gmail.com>
-M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-L:     linux-kernel@vger.kernel.org
-S:     Odd fixes
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
-F:     Documentation/driver-api/vme.rst
-F:     drivers/staging/vme_user/
-
 VM SOCKETS (AF_VSOCK)
 M:     Stefano Garzarella <sgarzare@redhat.com>
 L:     virtualization@lists.linux-foundation.org
@@ -22478,6 +22491,28 @@ F:     include/uapi/linux/vsockmon.h
 F:     net/vmw_vsock/
 F:     tools/testing/vsock/
 
+VMALLOC
+M:     Andrew Morton <akpm@linux-foundation.org>
+R:     Uladzislau Rezki <urezki@gmail.com>
+R:     Christoph Hellwig <hch@infradead.org>
+R:     Lorenzo Stoakes <lstoakes@gmail.com>
+L:     linux-mm@kvack.org
+S:     Maintained
+W:     http://www.linux-mm.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
+F:     include/linux/vmalloc.h
+F:     mm/vmalloc.c
+
+VME SUBSYSTEM
+M:     Martyn Welch <martyn@welchs.me.uk>
+M:     Manohar Vanga <manohar.vanga@gmail.com>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+L:     linux-kernel@vger.kernel.org
+S:     Odd fixes
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
+F:     Documentation/driver-api/vme.rst
+F:     drivers/staging/vme_user/
+
 VMWARE BALLOON DRIVER
 M:     Nadav Amit <namit@vmware.com>
 R:     VMware PV-Drivers Reviewers <pv-drivers@vmware.com>
@@ -22659,9 +22694,9 @@ F:      drivers/input/tablet/wacom_serial4.c
 WANGXUN ETHERNET DRIVER
 M:     Jiawen Wu <jiawenwu@trustnetic.com>
 M:     Mengyuan Lou <mengyuanlou@net-swift.com>
-W:     https://www.net-swift.com
 L:     netdev@vger.kernel.org
 S:     Maintained
+W:     https://www.net-swift.com
 F:     Documentation/networking/device_drivers/ethernet/wangxun/*
 F:     drivers/net/ethernet/wangxun/
 
@@ -22676,8 +22711,8 @@ F:      Documentation/devicetree/bindings/watchdog/
 F:     Documentation/watchdog/
 F:     drivers/watchdog/
 F:     include/linux/watchdog.h
-F:     include/uapi/linux/watchdog.h
 F:     include/trace/events/watchdog.h
+F:     include/uapi/linux/watchdog.h
 
 WHISKEYCOVE PMIC GPIO DRIVER
 M:     Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
@@ -22834,8 +22869,8 @@ R:      "H. Peter Anvin" <hpa@zytor.com>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/core
-F:     Documentation/devicetree/bindings/x86/
 F:     Documentation/arch/x86/
+F:     Documentation/devicetree/bindings/x86/
 F:     arch/x86/
 
 X86 ENTRY CODE
@@ -22966,6 +23001,8 @@ M:      John Fastabend <john.fastabend@gmail.com>
 L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Supported
+F:     drivers/net/ethernet/*/*/*/*/*xdp*
+F:     drivers/net/ethernet/*/*/*xdp*
 F:     include/net/xdp.h
 F:     include/net/xdp_priv.h
 F:     include/trace/events/xdp.h
@@ -22973,10 +23010,8 @@ F:     kernel/bpf/cpumap.c
 F:     kernel/bpf/devmap.c
 F:     net/core/xdp.c
 F:     samples/bpf/xdp*
-F:     tools/testing/selftests/bpf/*xdp*
 F:     tools/testing/selftests/bpf/*/*xdp*
-F:     drivers/net/ethernet/*/*/*/*/*xdp*
-F:     drivers/net/ethernet/*/*/*xdp*
+F:     tools/testing/selftests/bpf/*xdp*
 K:     (?:\b|_)xdp(?:\b|_)
 
 XDP SOCKETS (AF_XDP)
@@ -22988,11 +23023,11 @@ L:    netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Maintained
 F:     Documentation/networking/af_xdp.rst
+F:     include/net/netns/xdp.h
 F:     include/net/xdp_sock*
 F:     include/net/xsk_buff_pool.h
 F:     include/uapi/linux/if_xdp.h
 F:     include/uapi/linux/xdp_diag.h
-F:     include/net/netns/xdp.h
 F:     net/xdp/
 F:     tools/testing/selftests/bpf/*xsk*
 
@@ -23094,11 +23129,11 @@ F:    include/xen/arm/swiotlb-xen.h
 F:     include/xen/swiotlb-xen.h
 
 XFS FILESYSTEM
-C:     irc://irc.oftc.net/xfs
 M:     Darrick J. Wong <djwong@kernel.org>
 L:     linux-xfs@vger.kernel.org
 S:     Supported
 W:     http://xfs.org/
+C:     irc://irc.oftc.net/xfs
 T:     git git://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git
 F:     Documentation/ABI/testing/sysfs-fs-xfs
 F:     Documentation/admin-guide/xfs.rst
@@ -23128,16 +23163,28 @@ S:    Maintained
 F:     Documentation/devicetree/bindings/net/can/xilinx,can.yaml
 F:     drivers/net/can/xilinx_can.c
 
+XILINX EVENT MANAGEMENT DRIVER
+M:     Abhyuday Godhasara <abhyuday.godhasara@xilinx.com>
+S:     Maintained
+F:     drivers/soc/xilinx/xlnx_event_manager.c
+F:     include/linux/firmware/xlnx-event-manager.h
+
 XILINX GPIO DRIVER
 M:     Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
 R:     Srinivas Neeli <srinivas.neeli@xilinx.com>
 R:     Michal Simek <michal.simek@amd.com>
 S:     Maintained
-F:     Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml
 F:     Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
+F:     Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml
 F:     drivers/gpio/gpio-xilinx.c
 F:     drivers/gpio/gpio-zynq.c
 
+XILINX PWM DRIVER
+M:     Sean Anderson <sean.anderson@seco.com>
+S:     Maintained
+F:     drivers/pwm/pwm-xilinx.c
+F:     include/clocksource/timer-xilinx.h
+
 XILINX SD-FEC IP CORES
 M:     Derek Kiernan <derek.kiernan@xilinx.com>
 M:     Dragan Cvetic <dragan.cvetic@xilinx.com>
@@ -23149,12 +23196,6 @@ F:     drivers/misc/Makefile
 F:     drivers/misc/xilinx_sdfec.c
 F:     include/uapi/misc/xilinx_sdfec.h
 
-XILINX PWM DRIVER
-M:     Sean Anderson <sean.anderson@seco.com>
-S:     Maintained
-F:     drivers/pwm/pwm-xilinx.c
-F:     include/clocksource/timer-xilinx.h
-
 XILINX UARTLITE SERIAL DRIVER
 M:     Peter Korsgaard <jacmet@sunsite.dk>
 L:     linux-serial@vger.kernel.org
@@ -23220,12 +23261,6 @@ M:     Harsha <harsha.harsha@xilinx.com>
 S:     Maintained
 F:     drivers/crypto/xilinx/zynqmp-sha.c
 
-XILINX EVENT MANAGEMENT DRIVER
-M:     Abhyuday Godhasara <abhyuday.godhasara@xilinx.com>
-S:     Maintained
-F:     drivers/soc/xilinx/xlnx_event_manager.c
-F:     include/linux/firmware/xlnx-event-manager.h
-
 XILLYBUS DRIVER
 M:     Eli Billauer <eli.billauer@gmail.com>
 L:     linux-kernel@vger.kernel.org
@@ -23273,6 +23308,13 @@ S:     Maintained
 F:     Documentation/input/devices/yealink.rst
 F:     drivers/input/misc/yealink.*
 
+Z3FOLD COMPRESSED PAGE ALLOCATOR
+M:     Vitaly Wool <vitaly.wool@konsulko.com>
+R:     Miaohe Lin <linmiaohe@huawei.com>
+L:     linux-mm@kvack.org
+S:     Maintained
+F:     mm/z3fold.c
+
 Z8530 DRIVER FOR AX.25
 M:     Joerg Reuter <jreuter@yaina.de>
 L:     linux-hams@vger.kernel.org
@@ -23290,13 +23332,6 @@ L:     linux-mm@kvack.org
 S:     Maintained
 F:     mm/zbud.c
 
-Z3FOLD COMPRESSED PAGE ALLOCATOR
-M:     Vitaly Wool <vitaly.wool@konsulko.com>
-R:     Miaohe Lin <linmiaohe@huawei.com>
-L:     linux-mm@kvack.org
-S:     Maintained
-F:     mm/z3fold.c
-
 ZD1211RW WIRELESS DRIVER
 M:     Ulrich Kunitz <kune@deine-taler.de>
 L:     linux-wireless@vger.kernel.org
@@ -23383,10 +23418,10 @@ M:    Nick Terrell <terrelln@fb.com>
 S:     Maintained
 B:     https://github.com/facebook/zstd/issues
 T:     git https://github.com/terrelln/linux.git
+F:     crypto/zstd.c
 F:     include/linux/zstd*
-F:     lib/zstd/
 F:     lib/decompress_unzstd.c
-F:     crypto/zstd.c
+F:     lib/zstd/
 N:     zstd
 K:     zstd
 
@@ -23398,13 +23433,6 @@ L:     linux-mm@kvack.org
 S:     Maintained
 F:     mm/zswap.c
 
-NXP BLUETOOTH WIRELESS DRIVERS
-M:     Amitkumar Karwar <amitkumar.karwar@nxp.com>
-M:     Neeraj Kale <neeraj.sanjaykale@nxp.com>
-S:     Maintained
-F:     Documentation/devicetree/bindings/net/bluetooth/nxp,88w8987-bt.yaml
-F:     drivers/bluetooth/btnxpuart.c
-
 THE REST
 M:     Linus Torvalds <torvalds@linux-foundation.org>
 L:     linux-kernel@vger.kernel.org
index 9d765ebcccf1e2a9e8bf65f2b2201a754aa7b129..09866a85bc2a21b7553b1d9602165ba2d522dc6c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 4
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc5
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
index 78555a6188510f63da0bf1a2659423cbc56205de..7b7e6c2ad190c838b38c8e9a74ceea01992fdc1b 100644 (file)
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_pcie>;
        reset-gpio = <&gpio6 7 GPIO_ACTIVE_LOW>;
+       vpcie-supply = <&reg_pcie>;
        status = "okay";
 };
 
index 5882c7565f6495b31c0d2c5f88431658e3ecf758..32a6022625d979041eb038c70213e696eb81b3ed 100644 (file)
@@ -8,6 +8,7 @@
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/leds/common.h>
 #include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/regulator/dlg,da9063-regulator.h>
 #include "imx6ull.dtsi"
 
 / {
 
                regulators {
                        vdd_soc_in_1v4: buck1 {
+                               regulator-allowed-modes = <DA9063_BUCK_MODE_SLEEP>; /* PFM */
                                regulator-always-on;
                                regulator-boot-on;
+                               regulator-initial-mode = <DA9063_BUCK_MODE_SLEEP>;
                                regulator-max-microvolt = <1400000>;
                                regulator-min-microvolt = <1400000>;
                                regulator-name = "vdd_soc_in_1v4";
                        };
 
                        vcc_3v3: buck2 {
+                               regulator-allowed-modes = <DA9063_BUCK_MODE_SYNC>; /* PWM */
                                regulator-always-on;
                                regulator-boot-on;
+                               regulator-initial-mode = <DA9063_BUCK_MODE_SYNC>;
                                regulator-max-microvolt = <3300000>;
                                regulator-min-microvolt = <3300000>;
                                regulator-name = "vcc_3v3";
                         * the voltage is set to 1.5V.
                         */
                        vcc_ddr_1v35: buck3 {
+                               regulator-allowed-modes = <DA9063_BUCK_MODE_SYNC>; /* PWM */
                                regulator-always-on;
                                regulator-boot-on;
+                               regulator-initial-mode = <DA9063_BUCK_MODE_SYNC>;
                                regulator-max-microvolt = <1500000>;
                                regulator-min-microvolt = <1500000>;
                                regulator-name = "vcc_ddr_1v35";
index c9e05e3540d6408791be69435b23bb3b131d554b..00bf53f99c294c6c183366798bbd3bca7569456b 100644 (file)
                        interrupt-names = "tx", "rx0", "rx1", "sce";
                        resets = <&rcc STM32F4_APB1_RESET(CAN2)>;
                        clocks = <&rcc 0 STM32F4_APB1_CLOCK(CAN2)>;
+                       st,can-secondary;
                        st,gcan = <&gcan>;
                        status = "disabled";
                };
index c8e6c52fb248e0bb405472ceefa11828fa7e07a9..9f65403295ca059fc917e1c575a32b77cab96a56 100644 (file)
                                        slew-rate = <2>;
                                };
                        };
+
+                       can1_pins_a: can1-0 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('A', 12, AF9)>; /* CAN1_TX */
+                               };
+                               pins2 {
+                                       pinmux = <STM32_PINMUX('A', 11, AF9)>; /* CAN1_RX */
+                                       bias-pull-up;
+                               };
+                       };
+
+                       can1_pins_b: can1-1 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('B', 9, AF9)>; /* CAN1_TX */
+                               };
+                               pins2 {
+                                       pinmux = <STM32_PINMUX('B', 8, AF9)>; /* CAN1_RX */
+                                       bias-pull-up;
+                               };
+                       };
+
+                       can1_pins_c: can1-2 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('D', 1, AF9)>; /* CAN1_TX */
+                               };
+                               pins2 {
+                                       pinmux = <STM32_PINMUX('D', 0, AF9)>; /* CAN1_RX */
+                                       bias-pull-up;
+
+                               };
+                       };
+
+                       can1_pins_d: can1-3 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('H', 13, AF9)>; /* CAN1_TX */
+                               };
+                               pins2 {
+                                       pinmux = <STM32_PINMUX('H', 14, AF9)>; /* CAN1_RX */
+                                       bias-pull-up;
+
+                               };
+                       };
+
+                       can2_pins_a: can2-0 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('B', 6, AF9)>; /* CAN2_TX */
+                               };
+                               pins2 {
+                                       pinmux = <STM32_PINMUX('B', 5, AF9)>; /* CAN2_RX */
+                                       bias-pull-up;
+                               };
+                       };
+
+                       can2_pins_b: can2-1 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('B', 13, AF9)>; /* CAN2_TX */
+                               };
+                               pins2 {
+                                       pinmux = <STM32_PINMUX('B', 12, AF9)>; /* CAN2_RX */
+                                       bias-pull-up;
+                               };
+                       };
+
+                       can3_pins_a: can3-0 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('A', 15, AF11)>; /* CAN3_TX */
+                               };
+                               pins2 {
+                                       pinmux = <STM32_PINMUX('A', 8, AF11)>; /* CAN3_RX */
+                                       bias-pull-up;
+                               };
+                       };
+
+                       can3_pins_b: can3-1 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('B', 4, AF11)>;  /* CAN3_TX */
+                               };
+                               pins2 {
+                                       pinmux = <STM32_PINMUX('B', 3, AF11)>; /* CAN3_RX */
+                                       bias-pull-up;
+                               };
+                       };
                };
        };
 };
index 3b88209bacea2f8664dcc4653f6bbca2397de4cb..ff1f9a1bcfcfc3bdffe1234ae103d876dfb891e9 100644 (file)
                reg = <0x2c0f0000 0x1000>;
                interrupts = <0 84 4>;
                cache-level = <2>;
+               cache-unified;
        };
 
        pmu {
index 78d3d4b82c6c2598d63d4c691ba0e5ae59b67e5c..f4db3e75d75f024ef41943729e4558d6eb3bf604 100644 (file)
@@ -92,7 +92,7 @@
 
 #define RETURN_READ_PMEVCNTRN(n) \
        return read_sysreg(PMEVCNTR##n)
-static unsigned long read_pmevcntrn(int n)
+static inline unsigned long read_pmevcntrn(int n)
 {
        PMEVN_SWITCH(n, RETURN_READ_PMEVCNTRN);
        return 0;
@@ -100,14 +100,14 @@ static unsigned long read_pmevcntrn(int n)
 
 #define WRITE_PMEVCNTRN(n) \
        write_sysreg(val, PMEVCNTR##n)
-static void write_pmevcntrn(int n, unsigned long val)
+static inline void write_pmevcntrn(int n, unsigned long val)
 {
        PMEVN_SWITCH(n, WRITE_PMEVCNTRN);
 }
 
 #define WRITE_PMEVTYPERN(n) \
        write_sysreg(val, PMEVTYPER##n)
-static void write_pmevtypern(int n, unsigned long val)
+static inline void write_pmevtypern(int n, unsigned long val)
 {
        PMEVN_SWITCH(n, WRITE_PMEVTYPERN);
 }
index 53be7ea6181b356604201f821f84086fca304341..9d2192156087be4727d909a5190e682c99efa02a 100644 (file)
@@ -308,6 +308,29 @@ static int unwind_exec_pop_subset_r0_to_r3(struct unwind_ctrl_block *ctrl,
        return URC_OK;
 }
 
+static unsigned long unwind_decode_uleb128(struct unwind_ctrl_block *ctrl)
+{
+       unsigned long bytes = 0;
+       unsigned long insn;
+       unsigned long result = 0;
+
+       /*
+        * unwind_get_byte() will advance `ctrl` one instruction at a time, so
+        * loop until we get an instruction byte where bit 7 is not set.
+        *
+        * Note: This decodes a maximum of 4 bytes to output 28 bits data where
+        * max is 0xfffffff: that will cover a vsp increment of 1073742336, hence
+        * it is sufficient for unwinding the stack.
+        */
+       do {
+               insn = unwind_get_byte(ctrl);
+               result |= (insn & 0x7f) << (bytes * 7);
+               bytes++;
+       } while (!!(insn & 0x80) && (bytes != sizeof(result)));
+
+       return result;
+}
+
 /*
  * Execute the current unwind instruction.
  */
@@ -361,7 +384,7 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
                if (ret)
                        goto error;
        } else if (insn == 0xb2) {
-               unsigned long uleb128 = unwind_get_byte(ctrl);
+               unsigned long uleb128 = unwind_decode_uleb128(ctrl);
 
                ctrl->vrs[SP] += 0x204 + (uleb128 << 2);
        } else {
index 67f72ca984b2f5ffc9c79ad5fb8bb8d33a08eec2..1956b095e699d137ed398f795a00b10b5d65e8c7 100644 (file)
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/**
+/*
  *  arch/arm/mac-sa1100/jornada720_ssp.c
  *
  *  Copyright (C) 2006/2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com>
@@ -26,6 +26,7 @@ static unsigned long jornada_ssp_flags;
 
 /**
  * jornada_ssp_reverse - reverses input byte
+ * @byte: input byte to reverse
  *
  * we need to reverse all data we receive from the mcu due to its physical location
  * returns : 01110111 -> 11101110
@@ -46,6 +47,7 @@ EXPORT_SYMBOL(jornada_ssp_reverse);
 
 /**
  * jornada_ssp_byte - waits for ready ssp bus and sends byte
+ * @byte: input byte to transmit
  *
  * waits for fifo buffer to clear and then transmits, if it doesn't then we will
  * timeout after <timeout> rounds. Needs mcu running before its called.
@@ -77,6 +79,7 @@ EXPORT_SYMBOL(jornada_ssp_byte);
 
 /**
  * jornada_ssp_inout - decide if input is command or trading byte
+ * @byte: input byte to send (may be %TXDUMMY)
  *
  * returns : (jornada_ssp_byte(byte)) on success
  *         : %-ETIMEDOUT on timeout failure
index 7483ef8bccda394c0d21847e98b37597d8ec574a..62206ef250371cd35404b74ba3dd8c8ac51411fd 100644 (file)
@@ -23,6 +23,9 @@
 @
 ENTRY(do_vfp)
        mov     r1, r10
-       mov     r3, r9
-       b       vfp_entry
+       str     lr, [sp, #-8]!
+       add     r3, sp, #4
+       str     r9, [r3]
+       bl      vfp_entry
+       ldr     pc, [sp], #8
 ENDPROC(do_vfp)
index 4d8478264d82b3d2790b69b323118f8009c53787..a4610d0f321527cc86eee150254c6faeb5649dee 100644 (file)
@@ -172,13 +172,14 @@ vfp_hw_state_valid:
                                        @ out before setting an FPEXC that
                                        @ stops us reading stuff
        VFPFMXR FPEXC, r1               @ Restore FPEXC last
+       mov     sp, r3                  @ we think we have handled things
+       pop     {lr}
        sub     r2, r2, #4              @ Retry current instruction - if Thumb
        str     r2, [sp, #S_PC]         @ mode it's two 16-bit instructions,
                                        @ else it's one 32-bit instruction, so
                                        @ always subtract 4 from the following
                                        @ instruction address.
 
-       mov     lr, r3                  @ we think we have handled things
 local_bh_enable_and_ret:
        adr     r0, .
        mov     r1, #SOFTIRQ_DISABLE_OFFSET
@@ -209,8 +210,9 @@ skip:
 
 process_exception:
        DBGSTR  "bounce"
+       mov     sp, r3                  @ setup for a return to the user code.
+       pop     {lr}
        mov     r2, sp                  @ nothing stacked - regdump is at TOS
-       mov     lr, r3                  @ setup for a return to the user code.
 
        @ Now call the C code to package up the bounce to the support code
        @   r0 holds the trigger instruction
index 029578072d8fb495ce64cc86ee59e0dc3c36ab08..7b41537731a6aec17fee92655a52ab132aaefd36 100644 (file)
@@ -59,6 +59,7 @@
                L2_0: l2-cache0 {
                        compatible = "cache";
                        cache-level = <2>;
+                       cache-unified;
                };
        };
 
index ef68f5aae7ddf7b7ac1d886ca30de613d08aebd7..afdf954206f1d1a895b6c0106b0b7afd7d9053b8 100644 (file)
@@ -72,6 +72,7 @@
                L2_0: l2-cache0 {
                        compatible = "cache";
                        cache-level = <2>;
+                       cache-unified;
                };
        };
 
index 796cd7d02eb55ac954a7d828000c706651250130..7bdeb965f0a964f3dd77d9c6d39717b4b9b00201 100644 (file)
@@ -58,6 +58,7 @@
                L2_0: l2-cache0 {
                        compatible = "cache";
                        cache-level = <2>;
+                       cache-unified;
                };
        };
 
index 2209c1ac6e9b011726b31b4269deac85b6445a92..e62a43591361b360a64f11998bda741708bbc1f0 100644 (file)
@@ -171,6 +171,7 @@ conn_subsys: bus@5b000000 {
                        interrupt-names = "host", "peripheral", "otg", "wakeup";
                        phys = <&usb3_phy>;
                        phy-names = "cdns3,usb3-phy";
+                       cdns,on-chip-buff-size = /bits/ 16 <18>;
                        status = "disabled";
                };
        };
index 67072e6c77d5fb7834b41a938881216d87939496..cbd9d124c80d09adcdc630a8cf4710e89201aa50 100644 (file)
                #address-cells = <1>;
                #size-cells = <0>;
 
-               ethphy: ethernet-phy@4 {
+               ethphy: ethernet-phy@4 { /* AR8033 or ADIN1300 */
                        compatible = "ethernet-phy-ieee802.3-c22";
                        reg = <4>;
                        reset-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
                        reset-assert-us = <10000>;
+                       /*
+                        * Deassert delay:
+                        * ADIN1300 requires 5ms.
+                        * AR8033   requires 1ms.
+                        */
+                       reset-deassert-us = <20000>;
                };
        };
 };
index bd84db55005313ac4e6c96b2929cf3b684e95c67..8be8f090e8b8e9e7c89a998463b23b067e40ff30 100644 (file)
                                         <&clk IMX8MN_CLK_DISP_APB_ROOT>,
                                         <&clk IMX8MN_CLK_DISP_AXI_ROOT>;
                                clock-names = "pix", "axi", "disp_axi";
-                               assigned-clocks = <&clk IMX8MN_CLK_DISP_PIXEL_ROOT>,
-                                                 <&clk IMX8MN_CLK_DISP_AXI>,
-                                                 <&clk IMX8MN_CLK_DISP_APB>;
-                               assigned-clock-parents = <&clk IMX8MN_CLK_DISP_PIXEL>,
-                                                        <&clk IMX8MN_SYS_PLL2_1000M>,
-                                                        <&clk IMX8MN_SYS_PLL1_800M>;
-                               assigned-clock-rates = <594000000>, <500000000>, <200000000>;
                                interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
                                power-domains = <&disp_blk_ctrl IMX8MN_DISPBLK_PD_LCDIF>;
                                status = "disabled";
                                clocks = <&clk IMX8MN_CLK_DSI_CORE>,
                                         <&clk IMX8MN_CLK_DSI_PHY_REF>;
                                clock-names = "bus_clk", "sclk_mipi";
-                               assigned-clocks = <&clk IMX8MN_CLK_DSI_CORE>,
-                                                 <&clk IMX8MN_CLK_DSI_PHY_REF>;
-                               assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_266M>,
-                                                        <&clk IMX8MN_CLK_24M>;
-                               assigned-clock-rates = <266000000>, <24000000>;
-                               samsung,pll-clock-frequency = <24000000>;
                                interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
                                power-domains = <&disp_blk_ctrl IMX8MN_DISPBLK_PD_MIPI_DSI>;
                                status = "disabled";
                                              "lcdif-axi", "lcdif-apb", "lcdif-pix",
                                              "dsi-pclk", "dsi-ref",
                                              "csi-aclk", "csi-pclk";
+                               assigned-clocks = <&clk IMX8MN_CLK_DSI_CORE>,
+                                                 <&clk IMX8MN_CLK_DSI_PHY_REF>,
+                                                 <&clk IMX8MN_CLK_DISP_PIXEL>,
+                                                 <&clk IMX8MN_CLK_DISP_AXI>,
+                                                 <&clk IMX8MN_CLK_DISP_APB>;
+                               assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_266M>,
+                                                        <&clk IMX8MN_CLK_24M>,
+                                                        <&clk IMX8MN_VIDEO_PLL1_OUT>,
+                                                        <&clk IMX8MN_SYS_PLL2_1000M>,
+                                                        <&clk IMX8MN_SYS_PLL1_800M>;
+                               assigned-clock-rates = <266000000>,
+                                                      <24000000>,
+                                                      <594000000>,
+                                                      <500000000>,
+                                                      <200000000>;
                                #power-domain-cells = <1>;
                        };
 
index f81391993354f484aa60380a4b23545b3cfb724e..428c60462e3d6be7c09f62ea51f48be069af802f 100644 (file)
                                         <&clk IMX8MP_CLK_MEDIA_APB_ROOT>,
                                         <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>;
                                clock-names = "pix", "axi", "disp_axi";
-                               assigned-clocks = <&clk IMX8MP_CLK_MEDIA_DISP1_PIX_ROOT>,
-                                                 <&clk IMX8MP_CLK_MEDIA_AXI>,
-                                                 <&clk IMX8MP_CLK_MEDIA_APB>;
-                               assigned-clock-parents = <&clk IMX8MP_CLK_MEDIA_DISP1_PIX>,
-                                                        <&clk IMX8MP_SYS_PLL2_1000M>,
-                                                        <&clk IMX8MP_SYS_PLL1_800M>;
-                               assigned-clock-rates = <594000000>, <500000000>, <200000000>;
                                interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
                                power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_LCDIF_1>;
                                status = "disabled";
                                         <&clk IMX8MP_CLK_MEDIA_APB_ROOT>,
                                         <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>;
                                clock-names = "pix", "axi", "disp_axi";
-                               assigned-clocks = <&clk IMX8MP_CLK_MEDIA_DISP2_PIX>,
-                                                 <&clk IMX8MP_VIDEO_PLL1>;
-                               assigned-clock-parents = <&clk IMX8MP_VIDEO_PLL1_OUT>,
-                                                        <&clk IMX8MP_VIDEO_PLL1_REF_SEL>;
-                               assigned-clock-rates = <0>, <1039500000>;
                                power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_LCDIF_2>;
                                status = "disabled";
 
                                              "disp1", "disp2", "isp", "phy";
 
                                assigned-clocks = <&clk IMX8MP_CLK_MEDIA_AXI>,
-                                                 <&clk IMX8MP_CLK_MEDIA_APB>;
+                                                 <&clk IMX8MP_CLK_MEDIA_APB>,
+                                                 <&clk IMX8MP_CLK_MEDIA_DISP1_PIX>,
+                                                 <&clk IMX8MP_CLK_MEDIA_DISP2_PIX>,
+                                                 <&clk IMX8MP_VIDEO_PLL1>;
                                assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>,
-                                                        <&clk IMX8MP_SYS_PLL1_800M>;
-                               assigned-clock-rates = <500000000>, <200000000>;
-
+                                                        <&clk IMX8MP_SYS_PLL1_800M>,
+                                                        <&clk IMX8MP_VIDEO_PLL1_OUT>,
+                                                        <&clk IMX8MP_VIDEO_PLL1_OUT>;
+                               assigned-clock-rates = <500000000>, <200000000>,
+                                                      <0>, <0>, <1039500000>;
                                #power-domain-cells = <1>;
 
                                lvds_bridge: bridge@5c {
index 7264d784ae723cfa977b0953b4fed03c7d679b35..9af769ab8cebbdab47accd034fdc331d36e694f9 100644 (file)
        };
 };
 
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ext_io0>, <&pinctrl_hog0>, <&pinctrl_hog1>,
+                   <&pinctrl_lpspi2_cs2>;
+};
+
 /* Colibri SPI */
 &lpspi2 {
        status = "okay";
index 5f30c88855e70769ebded3a2716eafa37f232cf0..f8953067bc3bb86096c83365f3f3a58327aa365d 100644 (file)
@@ -48,8 +48,7 @@
                           <IMX8QXP_SAI0_TXFS_LSIO_GPIO0_IO28           0x20>,          /* SODIMM 101 */
                           <IMX8QXP_SAI0_RXD_LSIO_GPIO0_IO27            0x20>,          /* SODIMM  97 */
                           <IMX8QXP_ENET0_RGMII_RXC_LSIO_GPIO5_IO03     0x06000020>,    /* SODIMM  85 */
-                          <IMX8QXP_SAI0_TXC_LSIO_GPIO0_IO26            0x20>,          /* SODIMM  79 */
-                          <IMX8QXP_QSPI0A_DATA1_LSIO_GPIO3_IO10        0x06700041>;    /* SODIMM  45 */
+                          <IMX8QXP_SAI0_TXC_LSIO_GPIO0_IO26            0x20>;          /* SODIMM  79 */
        };
 
        pinctrl_uart1_forceoff: uart1forceoffgrp {
index 7cad79102e1afec6b06bd91fae24408832e180fd..49d105eb4769197af85317886bbb4acd13ef3248 100644 (file)
 /* TODO VPU Encoder/Decoder */
 
 &iomuxc {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_ext_io0>, <&pinctrl_hog0>, <&pinctrl_hog1>,
-                   <&pinctrl_hog2>, <&pinctrl_lpspi2_cs2>;
-
        /* On-module touch pen-down interrupt */
        pinctrl_ad7879_int: ad7879intgrp {
                fsl,pins = <IMX8QXP_MIPI_CSI0_I2C0_SCL_LSIO_GPIO3_IO05  0x21>;
        };
 
        pinctrl_hog1: hog1grp {
-               fsl,pins = <IMX8QXP_CSI_MCLK_LSIO_GPIO3_IO01                    0x20>,          /* SODIMM  75 */
-                          <IMX8QXP_QSPI0A_SCLK_LSIO_GPIO3_IO16                 0x20>;          /* SODIMM  93 */
+               fsl,pins = <IMX8QXP_QSPI0A_SCLK_LSIO_GPIO3_IO16                 0x20>;          /* SODIMM  93 */
        };
 
        pinctrl_hog2: hog2grp {
                fsl,pins = <IMX8QXP_SCU_BOOT_MODE3_SCU_DSC_RTC_CLOCK_OUTPUT_32K 0x20>;
        };
 };
+
+/* Delete peripherals which are not present on SOC, but are defined in imx8-ss-*.dtsi */
+
+/delete-node/ &adc1;
+/delete-node/ &adc1_lpcg;
+/delete-node/ &dsp;
+/delete-node/ &dsp_lpcg;
index d6b51deb7bf0ff2f28810cada684097be2666962..18dc2fb3d7b7b2d0633bbe2f4ef18ec2e8ce4f67 100644 (file)
@@ -13,7 +13,7 @@
 
 #define RETURN_READ_PMEVCNTRN(n) \
        return read_sysreg(pmevcntr##n##_el0)
-static unsigned long read_pmevcntrn(int n)
+static inline unsigned long read_pmevcntrn(int n)
 {
        PMEVN_SWITCH(n, RETURN_READ_PMEVCNTRN);
        return 0;
@@ -21,14 +21,14 @@ static unsigned long read_pmevcntrn(int n)
 
 #define WRITE_PMEVCNTRN(n) \
        write_sysreg(val, pmevcntr##n##_el0)
-static void write_pmevcntrn(int n, unsigned long val)
+static inline void write_pmevcntrn(int n, unsigned long val)
 {
        PMEVN_SWITCH(n, WRITE_PMEVCNTRN);
 }
 
 #define WRITE_PMEVTYPERN(n) \
        write_sysreg(val, pmevtyper##n##_el0)
-static void write_pmevtypern(int n, unsigned long val)
+static inline void write_pmevtypern(int n, unsigned long val)
 {
        PMEVN_SWITCH(n, WRITE_PMEVTYPERN);
 }
index 683ca3af408485aa6cdf4aa44b5988d91cd6a0f3..5f6f84837a490375c8175626e3fec40057bb56d9 100644 (file)
 #define APPLE_CPU_PART_M1_FIRESTORM_MAX        0x029
 #define APPLE_CPU_PART_M2_BLIZZARD     0x032
 #define APPLE_CPU_PART_M2_AVALANCHE    0x033
+#define APPLE_CPU_PART_M2_BLIZZARD_PRO 0x034
+#define APPLE_CPU_PART_M2_AVALANCHE_PRO        0x035
+#define APPLE_CPU_PART_M2_BLIZZARD_MAX 0x038
+#define APPLE_CPU_PART_M2_AVALANCHE_MAX        0x039
 
 #define AMPERE_CPU_PART_AMPERE1                0xAC3
 
 #define MIDR_APPLE_M1_FIRESTORM_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_MAX)
 #define MIDR_APPLE_M2_BLIZZARD MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD)
 #define MIDR_APPLE_M2_AVALANCHE MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE)
+#define MIDR_APPLE_M2_BLIZZARD_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_PRO)
+#define MIDR_APPLE_M2_AVALANCHE_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_PRO)
+#define MIDR_APPLE_M2_BLIZZARD_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX)
+#define MIDR_APPLE_M2_AVALANCHE_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_MAX)
 #define MIDR_AMPERE1 MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1)
 
 /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */
index 4cd6762bda805d16fe798a1db258155ced0d1a28..93bd0975b15f5545d5a408fd177ce35e780204ad 100644 (file)
@@ -209,6 +209,7 @@ struct kvm_pgtable_visit_ctx {
        kvm_pte_t                               old;
        void                                    *arg;
        struct kvm_pgtable_mm_ops               *mm_ops;
+       u64                                     start;
        u64                                     addr;
        u64                                     end;
        u32                                     level;
@@ -631,9 +632,9 @@ int kvm_pgtable_stage2_flush(struct kvm_pgtable *pgt, u64 addr, u64 size);
  *
  * The walker will walk the page-table entries corresponding to the input
  * address range specified, visiting entries according to the walker flags.
- * Invalid entries are treated as leaf entries. Leaf entries are reloaded
- * after invoking the walker callback, allowing the walker to descend into
- * a newly installed table.
+ * Invalid entries are treated as leaf entries. The visited page table entry is
+ * reloaded after invoking the walker callback, allowing the walker to descend
+ * into a newly installed table.
  *
  * Returning a negative error code from the walker callback function will
  * terminate the walk immediately with the same error code.
index e72d9aaab6b1b63461b6b061536486528c041514..eefd712f2430353f5800df0b06333dd0460f22c0 100644 (file)
 #define SB_BARRIER_INSN                        __SYS_BARRIER_INSN(0, 7, 31)
 
 #define SYS_DC_ISW                     sys_insn(1, 0, 7, 6, 2)
+#define SYS_DC_IGSW                    sys_insn(1, 0, 7, 6, 4)
+#define SYS_DC_IGDSW                   sys_insn(1, 0, 7, 6, 6)
 #define SYS_DC_CSW                     sys_insn(1, 0, 7, 10, 2)
+#define SYS_DC_CGSW                    sys_insn(1, 0, 7, 10, 4)
+#define SYS_DC_CGDSW                   sys_insn(1, 0, 7, 10, 6)
 #define SYS_DC_CISW                    sys_insn(1, 0, 7, 14, 2)
+#define SYS_DC_CIGSW                   sys_insn(1, 0, 7, 14, 4)
+#define SYS_DC_CIGDSW                  sys_insn(1, 0, 7, 14, 6)
 
 /*
  * Automatically generated definitions for system registers, the
index f5bcb0dc6267385e3401ed2735429b45af56e8e7..7e89968bd28244ced303586a35bb2e81dc1ffad6 100644 (file)
@@ -66,13 +66,10 @@ void mte_sync_tags(pte_t old_pte, pte_t pte)
                return;
 
        /* if PG_mte_tagged is set, tags have already been initialised */
-       for (i = 0; i < nr_pages; i++, page++) {
-               if (!page_mte_tagged(page)) {
+       for (i = 0; i < nr_pages; i++, page++)
+               if (!page_mte_tagged(page))
                        mte_sync_page_tags(page, old_pte, check_swap,
                                           pte_is_tagged);
-                       set_page_mte_tagged(page);
-               }
-       }
 
        /* ensure the tags are visible before the PTE is set */
        smp_wmb();
index 0119dc91abb5dbc7567344aff13760454fbb24c3..d9e1355730ef5811163d173590970d79207a8c5b 100644 (file)
@@ -288,7 +288,7 @@ static int aarch32_alloc_kuser_vdso_page(void)
 
        memcpy((void *)(vdso_page + 0x1000 - kuser_sz), __kuser_helper_start,
               kuser_sz);
-       aarch32_vectors_page = virt_to_page(vdso_page);
+       aarch32_vectors_page = virt_to_page((void *)vdso_page);
        return 0;
 }
 
index 1279949599b5fc84948f4061d6571537883c54e9..4c9dcd8fc93950d2927725ef23e21275267dd0c0 100644 (file)
@@ -81,26 +81,34 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 
        fpsimd_kvm_prepare();
 
+       /*
+        * We will check TIF_FOREIGN_FPSTATE just before entering the
+        * guest in kvm_arch_vcpu_ctxflush_fp() and override this to
+        * FP_STATE_FREE if the flag set.
+        */
        vcpu->arch.fp_state = FP_STATE_HOST_OWNED;
 
        vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
        if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
                vcpu_set_flag(vcpu, HOST_SVE_ENABLED);
 
-       /*
-        * We don't currently support SME guests but if we leave
-        * things in streaming mode then when the guest starts running
-        * FPSIMD or SVE code it may generate SME traps so as a
-        * special case if we are in streaming mode we force the host
-        * state to be saved now and exit streaming mode so that we
-        * don't have to handle any SME traps for valid guest
-        * operations. Do this for ZA as well for now for simplicity.
-        */
        if (system_supports_sme()) {
                vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
                if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
                        vcpu_set_flag(vcpu, HOST_SME_ENABLED);
 
+               /*
+                * If PSTATE.SM is enabled then save any pending FP
+                * state and disable PSTATE.SM. If we leave PSTATE.SM
+                * enabled and the guest does not enable SME via
+                * CPACR_EL1.SMEN then operations that should be valid
+                * may generate SME traps from EL1 to EL1 which we
+                * can't intercept and which would confuse the guest.
+                *
+                * Do the same for PSTATE.ZA in the case where there
+                * is state in the registers which has not already
+                * been saved, this is very unlikely to happen.
+                */
                if (read_sysreg_s(SYS_SVCR) & (SVCR_SM_MASK | SVCR_ZA_MASK)) {
                        vcpu->arch.fp_state = FP_STATE_FREE;
                        fpsimd_save_and_flush_cpu_state();
index c41166f1a1dd7dd6c228dd7e0477424dd19be9ba..5c15c58f90ccebb1afe2c364a5fec23559dfad03 100644 (file)
@@ -177,9 +177,17 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
        sve_guest = vcpu_has_sve(vcpu);
        esr_ec = kvm_vcpu_trap_get_class(vcpu);
 
-       /* Don't handle SVE traps for non-SVE vcpus here: */
-       if (!sve_guest && esr_ec != ESR_ELx_EC_FP_ASIMD)
+       /* Only handle traps the vCPU can support here: */
+       switch (esr_ec) {
+       case ESR_ELx_EC_FP_ASIMD:
+               break;
+       case ESR_ELx_EC_SVE:
+               if (!sve_guest)
+                       return false;
+               break;
+       default:
                return false;
+       }
 
        /* Valid trap.  Switch the context: */
 
@@ -404,17 +412,21 @@ static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
        return false;
 }
 
-static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
+static bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
        if (!__populate_fault_info(vcpu))
                return true;
 
        return false;
 }
+static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
+       __alias(kvm_hyp_handle_memory_fault);
+static bool kvm_hyp_handle_watchpt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
+       __alias(kvm_hyp_handle_memory_fault);
 
 static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
-       if (!__populate_fault_info(vcpu))
+       if (kvm_hyp_handle_memory_fault(vcpu, exit_code))
                return true;
 
        if (static_branch_unlikely(&vgic_v2_cpuif_trap)) {
index 2e9ec4a2a4a323d238e29f8ac199da8ea5301768..a8813b2129966d094e54154dec71c92781c032bb 100644 (file)
@@ -575,7 +575,7 @@ struct pkvm_mem_donation {
 
 struct check_walk_data {
        enum pkvm_page_state    desired;
-       enum pkvm_page_state    (*get_page_state)(kvm_pte_t pte);
+       enum pkvm_page_state    (*get_page_state)(kvm_pte_t pte, u64 addr);
 };
 
 static int __check_page_state_visitor(const struct kvm_pgtable_visit_ctx *ctx,
@@ -583,10 +583,7 @@ static int __check_page_state_visitor(const struct kvm_pgtable_visit_ctx *ctx,
 {
        struct check_walk_data *d = ctx->arg;
 
-       if (kvm_pte_valid(ctx->old) && !addr_is_allowed_memory(kvm_pte_to_phys(ctx->old)))
-               return -EINVAL;
-
-       return d->get_page_state(ctx->old) == d->desired ? 0 : -EPERM;
+       return d->get_page_state(ctx->old, ctx->addr) == d->desired ? 0 : -EPERM;
 }
 
 static int check_page_state_range(struct kvm_pgtable *pgt, u64 addr, u64 size,
@@ -601,8 +598,11 @@ static int check_page_state_range(struct kvm_pgtable *pgt, u64 addr, u64 size,
        return kvm_pgtable_walk(pgt, addr, size, &walker);
 }
 
-static enum pkvm_page_state host_get_page_state(kvm_pte_t pte)
+static enum pkvm_page_state host_get_page_state(kvm_pte_t pte, u64 addr)
 {
+       if (!addr_is_allowed_memory(addr))
+               return PKVM_NOPAGE;
+
        if (!kvm_pte_valid(pte) && pte)
                return PKVM_NOPAGE;
 
@@ -709,7 +709,7 @@ static int host_complete_donation(u64 addr, const struct pkvm_mem_transition *tx
        return host_stage2_set_owner_locked(addr, size, host_id);
 }
 
-static enum pkvm_page_state hyp_get_page_state(kvm_pte_t pte)
+static enum pkvm_page_state hyp_get_page_state(kvm_pte_t pte, u64 addr)
 {
        if (!kvm_pte_valid(pte))
                return PKVM_NOPAGE;
index 71fa16a0dc775890adbcebe3a2ade963734ef445..77791495c9951d60e18fa8f80fd5c22385d65840 100644 (file)
@@ -186,6 +186,7 @@ static const exit_handler_fn hyp_exit_handlers[] = {
        [ESR_ELx_EC_FP_ASIMD]           = kvm_hyp_handle_fpsimd,
        [ESR_ELx_EC_IABT_LOW]           = kvm_hyp_handle_iabt_low,
        [ESR_ELx_EC_DABT_LOW]           = kvm_hyp_handle_dabt_low,
+       [ESR_ELx_EC_WATCHPT_LOW]        = kvm_hyp_handle_watchpt_low,
        [ESR_ELx_EC_PAC]                = kvm_hyp_handle_ptrauth,
 };
 
@@ -196,6 +197,7 @@ static const exit_handler_fn pvm_exit_handlers[] = {
        [ESR_ELx_EC_FP_ASIMD]           = kvm_hyp_handle_fpsimd,
        [ESR_ELx_EC_IABT_LOW]           = kvm_hyp_handle_iabt_low,
        [ESR_ELx_EC_DABT_LOW]           = kvm_hyp_handle_dabt_low,
+       [ESR_ELx_EC_WATCHPT_LOW]        = kvm_hyp_handle_watchpt_low,
        [ESR_ELx_EC_PAC]                = kvm_hyp_handle_ptrauth,
 };
 
index 3d61bd3e591d27e9858b028220a9eb81a7498f6d..95dae02ccc2e60c2a830061a23b2e9d8c16e6246 100644 (file)
@@ -58,8 +58,9 @@
 struct kvm_pgtable_walk_data {
        struct kvm_pgtable_walker       *walker;
 
+       const u64                       start;
        u64                             addr;
-       u64                             end;
+       const u64                       end;
 };
 
 static bool kvm_phys_is_valid(u64 phys)
@@ -201,20 +202,33 @@ static inline int __kvm_pgtable_visit(struct kvm_pgtable_walk_data *data,
                .old    = READ_ONCE(*ptep),
                .arg    = data->walker->arg,
                .mm_ops = mm_ops,
+               .start  = data->start,
                .addr   = data->addr,
                .end    = data->end,
                .level  = level,
                .flags  = flags,
        };
        int ret = 0;
+       bool reload = false;
        kvm_pteref_t childp;
        bool table = kvm_pte_table(ctx.old, level);
 
-       if (table && (ctx.flags & KVM_PGTABLE_WALK_TABLE_PRE))
+       if (table && (ctx.flags & KVM_PGTABLE_WALK_TABLE_PRE)) {
                ret = kvm_pgtable_visitor_cb(data, &ctx, KVM_PGTABLE_WALK_TABLE_PRE);
+               reload = true;
+       }
 
        if (!table && (ctx.flags & KVM_PGTABLE_WALK_LEAF)) {
                ret = kvm_pgtable_visitor_cb(data, &ctx, KVM_PGTABLE_WALK_LEAF);
+               reload = true;
+       }
+
+       /*
+        * Reload the page table after invoking the walker callback for leaf
+        * entries or after pre-order traversal, to allow the walker to descend
+        * into a newly installed or replaced table.
+        */
+       if (reload) {
                ctx.old = READ_ONCE(*ptep);
                table = kvm_pte_table(ctx.old, level);
        }
@@ -293,6 +307,7 @@ int kvm_pgtable_walk(struct kvm_pgtable *pgt, u64 addr, u64 size,
                     struct kvm_pgtable_walker *walker)
 {
        struct kvm_pgtable_walk_data walk_data = {
+               .start  = ALIGN_DOWN(addr, PAGE_SIZE),
                .addr   = ALIGN_DOWN(addr, PAGE_SIZE),
                .end    = PAGE_ALIGN(walk_data.addr + size),
                .walker = walker,
@@ -349,7 +364,7 @@ int kvm_pgtable_get_leaf(struct kvm_pgtable *pgt, u64 addr,
 }
 
 struct hyp_map_data {
-       u64                             phys;
+       const u64                       phys;
        kvm_pte_t                       attr;
 };
 
@@ -407,13 +422,12 @@ enum kvm_pgtable_prot kvm_pgtable_hyp_pte_prot(kvm_pte_t pte)
 static bool hyp_map_walker_try_leaf(const struct kvm_pgtable_visit_ctx *ctx,
                                    struct hyp_map_data *data)
 {
+       u64 phys = data->phys + (ctx->addr - ctx->start);
        kvm_pte_t new;
-       u64 granule = kvm_granule_size(ctx->level), phys = data->phys;
 
        if (!kvm_block_mapping_supported(ctx, phys))
                return false;
 
-       data->phys += granule;
        new = kvm_init_valid_leaf_pte(phys, data->attr, ctx->level);
        if (ctx->old == new)
                return true;
@@ -576,7 +590,7 @@ void kvm_pgtable_hyp_destroy(struct kvm_pgtable *pgt)
 }
 
 struct stage2_map_data {
-       u64                             phys;
+       const u64                       phys;
        kvm_pte_t                       attr;
        u8                              owner_id;
 
@@ -794,20 +808,43 @@ static bool stage2_pte_executable(kvm_pte_t pte)
        return !(pte & KVM_PTE_LEAF_ATTR_HI_S2_XN);
 }
 
+static u64 stage2_map_walker_phys_addr(const struct kvm_pgtable_visit_ctx *ctx,
+                                      const struct stage2_map_data *data)
+{
+       u64 phys = data->phys;
+
+       /*
+        * Stage-2 walks to update ownership data are communicated to the map
+        * walker using an invalid PA. Avoid offsetting an already invalid PA,
+        * which could overflow and make the address valid again.
+        */
+       if (!kvm_phys_is_valid(phys))
+               return phys;
+
+       /*
+        * Otherwise, work out the correct PA based on how far the walk has
+        * gotten.
+        */
+       return phys + (ctx->addr - ctx->start);
+}
+
 static bool stage2_leaf_mapping_allowed(const struct kvm_pgtable_visit_ctx *ctx,
                                        struct stage2_map_data *data)
 {
+       u64 phys = stage2_map_walker_phys_addr(ctx, data);
+
        if (data->force_pte && (ctx->level < (KVM_PGTABLE_MAX_LEVELS - 1)))
                return false;
 
-       return kvm_block_mapping_supported(ctx, data->phys);
+       return kvm_block_mapping_supported(ctx, phys);
 }
 
 static int stage2_map_walker_try_leaf(const struct kvm_pgtable_visit_ctx *ctx,
                                      struct stage2_map_data *data)
 {
        kvm_pte_t new;
-       u64 granule = kvm_granule_size(ctx->level), phys = data->phys;
+       u64 phys = stage2_map_walker_phys_addr(ctx, data);
+       u64 granule = kvm_granule_size(ctx->level);
        struct kvm_pgtable *pgt = data->mmu->pgt;
        struct kvm_pgtable_mm_ops *mm_ops = ctx->mm_ops;
 
@@ -841,8 +878,6 @@ static int stage2_map_walker_try_leaf(const struct kvm_pgtable_visit_ctx *ctx,
 
        stage2_make_pte(ctx, new);
 
-       if (kvm_phys_is_valid(phys))
-               data->phys += granule;
        return 0;
 }
 
@@ -1297,4 +1332,7 @@ void kvm_pgtable_stage2_free_removed(struct kvm_pgtable_mm_ops *mm_ops, void *pg
        };
 
        WARN_ON(__kvm_pgtable_walk(&data, mm_ops, ptep, level + 1));
+
+       WARN_ON(mm_ops->page_count(pgtable) != 1);
+       mm_ops->put_page(pgtable);
 }
index 3d868e84c7a0a33246f86b4ccadaed8b5abec548..7a1aa511e7da6f68fc88eb4a6b39dcb7927ded09 100644 (file)
@@ -110,6 +110,7 @@ static const exit_handler_fn hyp_exit_handlers[] = {
        [ESR_ELx_EC_FP_ASIMD]           = kvm_hyp_handle_fpsimd,
        [ESR_ELx_EC_IABT_LOW]           = kvm_hyp_handle_iabt_low,
        [ESR_ELx_EC_DABT_LOW]           = kvm_hyp_handle_dabt_low,
+       [ESR_ELx_EC_WATCHPT_LOW]        = kvm_hyp_handle_watchpt_low,
        [ESR_ELx_EC_PAC]                = kvm_hyp_handle_ptrauth,
 };
 
index 64c3aec0d937c36b84d49b7ca403933429b993c8..0bd93a5f21ce382506803d018ba7df7072ac0aa1 100644 (file)
@@ -204,7 +204,7 @@ void kvm_inject_size_fault(struct kvm_vcpu *vcpu)
         * Size Fault at level 0, as if exceeding PARange.
         *
         * Non-LPAE guests will only get the external abort, as there
-        * is no way to to describe the ASF.
+        * is no way to describe the ASF.
         */
        if (vcpu_el1_is_32bit(vcpu) &&
            !(vcpu_read_sys_reg(vcpu, TCR_EL1) & TTBCR_EAE))
index 45727d50d18dd90c842285a2d621628c77c9b0e6..491ca7eb2a4c6e186abbbae9112942e0420f0116 100644 (file)
@@ -694,45 +694,23 @@ out_unlock:
 
 static struct arm_pmu *kvm_pmu_probe_armpmu(void)
 {
-       struct perf_event_attr attr = { };
-       struct perf_event *event;
-       struct arm_pmu *pmu = NULL;
-
-       /*
-        * Create a dummy event that only counts user cycles. As we'll never
-        * leave this function with the event being live, it will never
-        * count anything. But it allows us to probe some of the PMU
-        * details. Yes, this is terrible.
-        */
-       attr.type = PERF_TYPE_RAW;
-       attr.size = sizeof(attr);
-       attr.pinned = 1;
-       attr.disabled = 0;
-       attr.exclude_user = 0;
-       attr.exclude_kernel = 1;
-       attr.exclude_hv = 1;
-       attr.exclude_host = 1;
-       attr.config = ARMV8_PMUV3_PERFCTR_CPU_CYCLES;
-       attr.sample_period = GENMASK(63, 0);
+       struct arm_pmu *tmp, *pmu = NULL;
+       struct arm_pmu_entry *entry;
+       int cpu;
 
-       event = perf_event_create_kernel_counter(&attr, -1, current,
-                                                kvm_pmu_perf_overflow, &attr);
+       mutex_lock(&arm_pmus_lock);
 
-       if (IS_ERR(event)) {
-               pr_err_once("kvm: pmu event creation failed %ld\n",
-                           PTR_ERR(event));
-               return NULL;
-       }
+       cpu = smp_processor_id();
+       list_for_each_entry(entry, &arm_pmus, entry) {
+               tmp = entry->arm_pmu;
 
-       if (event->pmu) {
-               pmu = to_arm_pmu(event->pmu);
-               if (pmu->pmuver == ID_AA64DFR0_EL1_PMUVer_NI ||
-                   pmu->pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
-                       pmu = NULL;
+               if (cpumask_test_cpu(cpu, &tmp->supported_cpus)) {
+                       pmu = tmp;
+                       break;
+               }
        }
 
-       perf_event_disable(event);
-       perf_event_release_kernel(event);
+       mutex_unlock(&arm_pmus_lock);
 
        return pmu;
 }
@@ -912,7 +890,17 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
                return -EBUSY;
 
        if (!kvm->arch.arm_pmu) {
-               /* No PMU set, get the default one */
+               /*
+                * No PMU set, get the default one.
+                *
+                * The observant among you will notice that the supported_cpus
+                * mask does not get updated for the default PMU even though it
+                * is quite possible the selected instance supports only a
+                * subset of cores in the system. This is intentional, and
+                * upholds the preexisting behavior on heterogeneous systems
+                * where vCPUs can be scheduled on any core but the guest
+                * counters could stop working.
+                */
                kvm->arch.arm_pmu = kvm_pmu_probe_armpmu();
                if (!kvm->arch.arm_pmu)
                        return -ENODEV;
index 71b12094d6137008f65bf6e6297747e815bc4bd3..753aa741814977728778648fc7e3c7e05644ab51 100644 (file)
@@ -211,6 +211,19 @@ static bool access_dcsw(struct kvm_vcpu *vcpu,
        return true;
 }
 
+static bool access_dcgsw(struct kvm_vcpu *vcpu,
+                        struct sys_reg_params *p,
+                        const struct sys_reg_desc *r)
+{
+       if (!kvm_has_mte(vcpu->kvm)) {
+               kvm_inject_undefined(vcpu);
+               return false;
+       }
+
+       /* Treat MTE S/W ops as we treat the classic ones: with contempt */
+       return access_dcsw(vcpu, p, r);
+}
+
 static void get_access_mask(const struct sys_reg_desc *r, u64 *mask, u64 *shift)
 {
        switch (r->aarch32_map) {
@@ -1756,8 +1769,14 @@ static bool access_spsr(struct kvm_vcpu *vcpu,
  */
 static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_DC_ISW), access_dcsw },
+       { SYS_DESC(SYS_DC_IGSW), access_dcgsw },
+       { SYS_DESC(SYS_DC_IGDSW), access_dcgsw },
        { SYS_DESC(SYS_DC_CSW), access_dcsw },
+       { SYS_DESC(SYS_DC_CGSW), access_dcgsw },
+       { SYS_DESC(SYS_DC_CGDSW), access_dcgsw },
        { SYS_DESC(SYS_DC_CISW), access_dcsw },
+       { SYS_DESC(SYS_DC_CIGSW), access_dcgsw },
+       { SYS_DESC(SYS_DC_CIGDSW), access_dcgsw },
 
        DBG_BCR_BVR_WCR_WVR_EL1(0),
        DBG_BCR_BVR_WCR_WVR_EL1(1),
index 9d42c7cb2b588235abf9b314cf92bc52f61429b0..6eafc2c45cfcf73e1bb5d817545ec4f290a388e9 100644 (file)
@@ -235,9 +235,9 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
         * KVM io device for the redistributor that belongs to this VCPU.
         */
        if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
-               mutex_lock(&vcpu->kvm->arch.config_lock);
+               mutex_lock(&vcpu->kvm->slots_lock);
                ret = vgic_register_redist_iodev(vcpu);
-               mutex_unlock(&vcpu->kvm->arch.config_lock);
+               mutex_unlock(&vcpu->kvm->slots_lock);
        }
        return ret;
 }
@@ -406,7 +406,7 @@ void kvm_vgic_destroy(struct kvm *kvm)
 
 /**
  * vgic_lazy_init: Lazy init is only allowed if the GIC exposed to the guest
- * is a GICv2. A GICv3 must be explicitly initialized by the guest using the
+ * is a GICv2. A GICv3 must be explicitly initialized by userspace using the
  * KVM_DEV_ARM_VGIC_GRP_CTRL KVM_DEVICE group.
  * @kvm: kvm struct pointer
  */
@@ -446,11 +446,13 @@ int vgic_lazy_init(struct kvm *kvm)
 int kvm_vgic_map_resources(struct kvm *kvm)
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
+       gpa_t dist_base;
        int ret = 0;
 
        if (likely(vgic_ready(kvm)))
                return 0;
 
+       mutex_lock(&kvm->slots_lock);
        mutex_lock(&kvm->arch.config_lock);
        if (vgic_ready(kvm))
                goto out;
@@ -463,13 +465,26 @@ int kvm_vgic_map_resources(struct kvm *kvm)
        else
                ret = vgic_v3_map_resources(kvm);
 
-       if (ret)
+       if (ret) {
                __kvm_vgic_destroy(kvm);
-       else
-               dist->ready = true;
+               goto out;
+       }
+       dist->ready = true;
+       dist_base = dist->vgic_dist_base;
+       mutex_unlock(&kvm->arch.config_lock);
+
+       ret = vgic_register_dist_iodev(kvm, dist_base,
+                                      kvm_vgic_global_state.type);
+       if (ret) {
+               kvm_err("Unable to register VGIC dist MMIO regions\n");
+               kvm_vgic_destroy(kvm);
+       }
+       mutex_unlock(&kvm->slots_lock);
+       return ret;
 
 out:
        mutex_unlock(&kvm->arch.config_lock);
+       mutex_unlock(&kvm->slots_lock);
        return ret;
 }
 
index 750e51e3779a31a0eda2f8223be233fb10355664..5fe2365a629f25013fd9039ab8279fe76a31349c 100644 (file)
@@ -1936,6 +1936,7 @@ void vgic_lpi_translation_cache_destroy(struct kvm *kvm)
 
 static int vgic_its_create(struct kvm_device *dev, u32 type)
 {
+       int ret;
        struct vgic_its *its;
 
        if (type != KVM_DEV_TYPE_ARM_VGIC_ITS)
@@ -1945,9 +1946,12 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
        if (!its)
                return -ENOMEM;
 
+       mutex_lock(&dev->kvm->arch.config_lock);
+
        if (vgic_initialized(dev->kvm)) {
-               int ret = vgic_v4_init(dev->kvm);
+               ret = vgic_v4_init(dev->kvm);
                if (ret < 0) {
+                       mutex_unlock(&dev->kvm->arch.config_lock);
                        kfree(its);
                        return ret;
                }
@@ -1960,12 +1964,10 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
 
        /* Yep, even more trickery for lock ordering... */
 #ifdef CONFIG_LOCKDEP
-       mutex_lock(&dev->kvm->arch.config_lock);
        mutex_lock(&its->cmd_lock);
        mutex_lock(&its->its_lock);
        mutex_unlock(&its->its_lock);
        mutex_unlock(&its->cmd_lock);
-       mutex_unlock(&dev->kvm->arch.config_lock);
 #endif
 
        its->vgic_its_base = VGIC_ADDR_UNDEF;
@@ -1986,7 +1988,11 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
 
        dev->private = its;
 
-       return vgic_its_set_abi(its, NR_ITS_ABIS - 1);
+       ret = vgic_its_set_abi(its, NR_ITS_ABIS - 1);
+
+       mutex_unlock(&dev->kvm->arch.config_lock);
+
+       return ret;
 }
 
 static void vgic_its_destroy(struct kvm_device *kvm_dev)
index 35cfa268fd5de7a0e3d1e1fa7eaa864715f77103..212b73a715c1c245540e12636085bb0d4ac1d741 100644 (file)
@@ -102,7 +102,11 @@ static int kvm_vgic_addr(struct kvm *kvm, struct kvm_device_attr *attr, bool wri
                if (get_user(addr, uaddr))
                        return -EFAULT;
 
-       mutex_lock(&kvm->arch.config_lock);
+       /*
+        * Since we can't hold config_lock while registering the redistributor
+        * iodevs, take the slots_lock immediately.
+        */
+       mutex_lock(&kvm->slots_lock);
        switch (attr->attr) {
        case KVM_VGIC_V2_ADDR_TYPE_DIST:
                r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
@@ -182,6 +186,7 @@ static int kvm_vgic_addr(struct kvm *kvm, struct kvm_device_attr *attr, bool wri
        if (r)
                goto out;
 
+       mutex_lock(&kvm->arch.config_lock);
        if (write) {
                r = vgic_check_iorange(kvm, *addr_ptr, addr, alignment, size);
                if (!r)
@@ -189,9 +194,10 @@ static int kvm_vgic_addr(struct kvm *kvm, struct kvm_device_attr *attr, bool wri
        } else {
                addr = *addr_ptr;
        }
+       mutex_unlock(&kvm->arch.config_lock);
 
 out:
-       mutex_unlock(&kvm->arch.config_lock);
+       mutex_unlock(&kvm->slots_lock);
 
        if (!r && !write)
                r =  put_user(addr, uaddr);
index 472b18ac92a242bd922cc1a3f58a56326de2c40b..188d2187eede935e43b31fcf4985205a1872d92f 100644 (file)
@@ -769,10 +769,13 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
        struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev;
        struct vgic_redist_region *rdreg;
        gpa_t rd_base;
-       int ret;
+       int ret = 0;
+
+       lockdep_assert_held(&kvm->slots_lock);
+       mutex_lock(&kvm->arch.config_lock);
 
        if (!IS_VGIC_ADDR_UNDEF(vgic_cpu->rd_iodev.base_addr))
-               return 0;
+               goto out_unlock;
 
        /*
         * We may be creating VCPUs before having set the base address for the
@@ -782,10 +785,12 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
         */
        rdreg = vgic_v3_rdist_free_slot(&vgic->rd_regions);
        if (!rdreg)
-               return 0;
+               goto out_unlock;
 
-       if (!vgic_v3_check_base(kvm))
-               return -EINVAL;
+       if (!vgic_v3_check_base(kvm)) {
+               ret = -EINVAL;
+               goto out_unlock;
+       }
 
        vgic_cpu->rdreg = rdreg;
        vgic_cpu->rdreg_index = rdreg->free_index;
@@ -799,16 +804,20 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
        rd_dev->nr_regions = ARRAY_SIZE(vgic_v3_rd_registers);
        rd_dev->redist_vcpu = vcpu;
 
-       mutex_lock(&kvm->slots_lock);
+       mutex_unlock(&kvm->arch.config_lock);
+
        ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, rd_base,
                                      2 * SZ_64K, &rd_dev->dev);
-       mutex_unlock(&kvm->slots_lock);
-
        if (ret)
                return ret;
 
+       /* Protected by slots_lock */
        rdreg->free_index++;
        return 0;
+
+out_unlock:
+       mutex_unlock(&kvm->arch.config_lock);
+       return ret;
 }
 
 static void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu)
@@ -834,12 +843,10 @@ static int vgic_register_all_redist_iodevs(struct kvm *kvm)
                /* The current c failed, so iterate over the previous ones. */
                int i;
 
-               mutex_lock(&kvm->slots_lock);
                for (i = 0; i < c; i++) {
                        vcpu = kvm_get_vcpu(kvm, i);
                        vgic_unregister_redist_iodev(vcpu);
                }
-               mutex_unlock(&kvm->slots_lock);
        }
 
        return ret;
@@ -938,7 +945,9 @@ int vgic_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count)
 {
        int ret;
 
+       mutex_lock(&kvm->arch.config_lock);
        ret = vgic_v3_alloc_redist_region(kvm, index, addr, count);
+       mutex_unlock(&kvm->arch.config_lock);
        if (ret)
                return ret;
 
@@ -950,8 +959,10 @@ int vgic_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count)
        if (ret) {
                struct vgic_redist_region *rdreg;
 
+               mutex_lock(&kvm->arch.config_lock);
                rdreg = vgic_v3_rdist_region_from_index(kvm, index);
                vgic_v3_free_redist_region(rdreg);
+               mutex_unlock(&kvm->arch.config_lock);
                return ret;
        }
 
index 1939c94e0b248801800ea00c62f081f2b0c9f62d..ff558c05e990c728abd5361054cb04ef44083818 100644 (file)
@@ -1096,7 +1096,6 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
                             enum vgic_type type)
 {
        struct vgic_io_device *io_device = &kvm->arch.vgic.dist_iodev;
-       int ret = 0;
        unsigned int len;
 
        switch (type) {
@@ -1114,10 +1113,6 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
        io_device->iodev_type = IODEV_DIST;
        io_device->redist_vcpu = NULL;
 
-       mutex_lock(&kvm->slots_lock);
-       ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, dist_base_address,
-                                     len, &io_device->dev);
-       mutex_unlock(&kvm->slots_lock);
-
-       return ret;
+       return kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, dist_base_address,
+                                      len, &io_device->dev);
 }
index 645648349c99b122359535c36f221d78432e25c0..7e9cdb78f7ce885f9917d380d99fa18547af47e6 100644 (file)
@@ -312,12 +312,6 @@ int vgic_v2_map_resources(struct kvm *kvm)
                return ret;
        }
 
-       ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V2);
-       if (ret) {
-               kvm_err("Unable to register VGIC MMIO regions\n");
-               return ret;
-       }
-
        if (!static_branch_unlikely(&vgic_v2_cpuif_trap)) {
                ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base,
                                            kvm_vgic_global_state.vcpu_base,
index 469d816f356f3fe94b021f5e2fd14ea91310f114..c3b8e132d5992616ca1f308456ababce125c6c01 100644 (file)
@@ -539,7 +539,6 @@ int vgic_v3_map_resources(struct kvm *kvm)
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
        struct kvm_vcpu *vcpu;
-       int ret = 0;
        unsigned long c;
 
        kvm_for_each_vcpu(c, vcpu, kvm) {
@@ -569,12 +568,6 @@ int vgic_v3_map_resources(struct kvm *kvm)
                return -EBUSY;
        }
 
-       ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V3);
-       if (ret) {
-               kvm_err("Unable to register VGICv3 dist MMIO regions\n");
-               return ret;
-       }
-
        if (kvm_vgic_global_state.has_gicv4_1)
                vgic_v4_configure_vsgis(kvm);
 
@@ -616,6 +609,10 @@ static const struct midr_range broken_seis[] = {
        MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_MAX),
        MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD),
        MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE),
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_PRO),
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_PRO),
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_MAX),
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_MAX),
        {},
 };
 
index 3bb0034780605772859f329620765d742e3fdf59..c1c28fe680ba317e9b8712de9a04b264991cdd0a 100644 (file)
@@ -184,13 +184,14 @@ static void vgic_v4_disable_vsgis(struct kvm_vcpu *vcpu)
        }
 }
 
-/* Must be called with the kvm lock held */
 void vgic_v4_configure_vsgis(struct kvm *kvm)
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
        struct kvm_vcpu *vcpu;
        unsigned long i;
 
+       lockdep_assert_held(&kvm->arch.config_lock);
+
        kvm_arm_halt_guest(kvm);
 
        kvm_for_each_vcpu(i, vcpu, kvm) {
index 08978d0672e7e947b0afbca0eb7d5ae0d9be440a..7fe8ba1a2851c5b71acbf17075987b96436f1a4a 100644 (file)
@@ -47,7 +47,7 @@ static void flush_context(void)
        int cpu;
        u64 vmid;
 
-       bitmap_clear(vmid_map, 0, NUM_USER_VMIDS);
+       bitmap_zero(vmid_map, NUM_USER_VMIDS);
 
        for_each_possible_cpu(cpu) {
                vmid = atomic64_xchg_relaxed(&per_cpu(active_vmids, cpu), 0);
@@ -182,8 +182,7 @@ int __init kvm_arm_vmid_alloc_init(void)
         */
        WARN_ON(NUM_USER_VMIDS - 1 <= num_possible_cpus());
        atomic64_set(&vmid_generation, VMID_FIRST_VERSION);
-       vmid_map = kcalloc(BITS_TO_LONGS(NUM_USER_VMIDS),
-                          sizeof(*vmid_map), GFP_KERNEL);
+       vmid_map = bitmap_zalloc(NUM_USER_VMIDS, GFP_KERNEL);
        if (!vmid_map)
                return -ENOMEM;
 
@@ -192,5 +191,5 @@ int __init kvm_arm_vmid_alloc_init(void)
 
 void __init kvm_arm_vmid_alloc_free(void)
 {
-       kfree(vmid_map);
+       bitmap_free(vmid_map);
 }
index 4aadcfb017545dbaef8fd7fb321ab2bdd9d565bd..a7bb20055ce0948a6f586e29fd1a05bbbc1cc75f 100644 (file)
@@ -21,9 +21,10 @@ void copy_highpage(struct page *to, struct page *from)
 
        copy_page(kto, kfrom);
 
+       if (kasan_hw_tags_enabled())
+               page_kasan_tag_reset(to);
+
        if (system_supports_mte() && page_mte_tagged(from)) {
-               if (kasan_hw_tags_enabled())
-                       page_kasan_tag_reset(to);
                /* It's a new page, shouldn't have been tagged yet */
                WARN_ON_ONCE(!try_page_mte_tagging(to));
                mte_copy_page_tags(kto, kfrom);
index 9e0db5c387e3ae903ca5b6526b5ef6978eee22bf..cb21ccd7940d0e3cd9b496fa1c3110b3cfb1f75e 100644 (file)
@@ -480,8 +480,8 @@ static void do_bad_area(unsigned long far, unsigned long esr,
        }
 }
 
-#define VM_FAULT_BADMAP                0x010000
-#define VM_FAULT_BADACCESS     0x020000
+#define VM_FAULT_BADMAP                ((__force vm_fault_t)0x010000)
+#define VM_FAULT_BADACCESS     ((__force vm_fault_t)0x020000)
 
 static vm_fault_t __do_page_fault(struct mm_struct *mm, unsigned long addr,
                                  unsigned int mm_flags, unsigned long vm_flags,
index b9f6908a31bc39f94c0418a298aed87470755170..ba468b5f3f0b65bd57d74af263d19d9ba917f635 100644 (file)
@@ -858,11 +858,17 @@ static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *
 }
 
 static inline void __user *
-get_sigframe(struct ksignal *ksig, size_t frame_size)
+get_sigframe(struct ksignal *ksig, struct pt_regs *tregs, size_t frame_size)
 {
        unsigned long usp = sigsp(rdusp(), ksig);
+       unsigned long gap = 0;
 
-       return (void __user *)((usp - frame_size) & -8UL);
+       if (CPU_IS_020_OR_030 && tregs->format == 0xb) {
+               /* USP is unreliable so use worst-case value */
+               gap = 256;
+       }
+
+       return (void __user *)((usp - gap - frame_size) & -8UL);
 }
 
 static int setup_frame(struct ksignal *ksig, sigset_t *set,
@@ -880,7 +886,7 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
                return -EFAULT;
        }
 
-       frame = get_sigframe(ksig, sizeof(*frame) + fsize);
+       frame = get_sigframe(ksig, tregs, sizeof(*frame) + fsize);
 
        if (fsize)
                err |= copy_to_user (frame + 1, regs + 1, fsize);
@@ -952,7 +958,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
                return -EFAULT;
        }
 
-       frame = get_sigframe(ksig, sizeof(*frame));
+       frame = get_sigframe(ksig, tregs, sizeof(*frame));
 
        if (fsize)
                err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
index c2f5498d207fffd0f07bfff905ff75e05c504802..675a8660cb85a033792d9622040ea48a8b800cb0 100644 (file)
@@ -79,6 +79,7 @@ config MIPS
        select HAVE_LD_DEAD_CODE_DATA_ELIMINATION
        select HAVE_MOD_ARCH_SPECIFIC
        select HAVE_NMI
+       select HAVE_PATA_PLATFORM
        select HAVE_PERF_EVENTS
        select HAVE_PERF_REGS
        select HAVE_PERF_USER_STACK_DUMP
index 5ab0430004092900cb8a7de8013031ff18d862fe..6a3c890f7bbfedc43459edc3c69b6f8cae3c79dc 100644 (file)
@@ -30,6 +30,7 @@
  *
  */
 
+#include <linux/dma-map-ops.h> /* for dma_default_coherent */
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -623,17 +624,18 @@ u32 au1xxx_dbdma_put_source(u32 chanid, dma_addr_t buf, int nbytes, u32 flags)
                dp->dscr_cmd0 &= ~DSCR_CMD0_IE;
 
        /*
-        * There is an errata on the Au1200/Au1550 parts that could result
-        * in "stale" data being DMA'ed. It has to do with the snoop logic on
-        * the cache eviction buffer.  DMA_NONCOHERENT is on by default for
-        * these parts. If it is fixed in the future, these dma_cache_inv will
-        * just be nothing more than empty macros. See io.h.
+        * There is an erratum on certain Au1200/Au1550 revisions that could
+        * result in "stale" data being DMA'ed. It has to do with the snoop
+        * logic on the cache eviction buffer.  dma_default_coherent is set
+        * to false on these parts.
         */
-       dma_cache_wback_inv((unsigned long)buf, nbytes);
+       if (!dma_default_coherent)
+               dma_cache_wback_inv(KSEG0ADDR(buf), nbytes);
        dp->dscr_cmd0 |= DSCR_CMD0_V;   /* Let it rip */
        wmb(); /* drain writebuffer */
        dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
        ctp->chan_ptr->ddma_dbell = 0;
+       wmb(); /* force doorbell write out to dma engine */
 
        /* Get next descriptor pointer. */
        ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
@@ -685,17 +687,18 @@ u32 au1xxx_dbdma_put_dest(u32 chanid, dma_addr_t buf, int nbytes, u32 flags)
                          dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1);
 #endif
        /*
-        * There is an errata on the Au1200/Au1550 parts that could result in
-        * "stale" data being DMA'ed. It has to do with the snoop logic on the
-        * cache eviction buffer.  DMA_NONCOHERENT is on by default for these
-        * parts. If it is fixed in the future, these dma_cache_inv will just
-        * be nothing more than empty macros. See io.h.
+        * There is an erratum on certain Au1200/Au1550 revisions that could
+        * result in "stale" data being DMA'ed. It has to do with the snoop
+        * logic on the cache eviction buffer.  dma_default_coherent is set
+        * to false on these parts.
         */
-       dma_cache_inv((unsigned long)buf, nbytes);
+       if (!dma_default_coherent)
+               dma_cache_inv(KSEG0ADDR(buf), nbytes);
        dp->dscr_cmd0 |= DSCR_CMD0_V;   /* Let it rip */
        wmb(); /* drain writebuffer */
        dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
        ctp->chan_ptr->ddma_dbell = 0;
+       wmb(); /* force doorbell write out to dma engine */
 
        /* Get next descriptor pointer. */
        ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
index 6d15a398d389e2bd269d47794edd1b37a370b956..e79adcb128e67df5a13dfc30740e555b4697554c 100644 (file)
@@ -1502,6 +1502,10 @@ static inline void cpu_probe_alchemy(struct cpuinfo_mips *c, unsigned int cpu)
                        break;
                }
                break;
+       case PRID_IMP_NETLOGIC_AU13XX:
+               c->cputype = CPU_ALCHEMY;
+               __cpu_name[cpu] = "Au1300";
+               break;
        }
 }
 
@@ -1863,6 +1867,7 @@ void cpu_probe(void)
                cpu_probe_mips(c, cpu);
                break;
        case PRID_COMP_ALCHEMY:
+       case PRID_COMP_NETLOGIC:
                cpu_probe_alchemy(c, cpu);
                break;
        case PRID_COMP_SIBYTE:
index febdc5564638e9b9bbb959791ecb75d6068b676c..c0e65135481b74bfb102f09dd56607c634f45b55 100644 (file)
@@ -158,10 +158,6 @@ static unsigned long __init init_initrd(void)
                pr_err("initrd start must be page aligned\n");
                goto disable;
        }
-       if (initrd_start < PAGE_OFFSET) {
-               pr_err("initrd start < PAGE_OFFSET\n");
-               goto disable;
-       }
 
        /*
         * Sanitize initrd addresses. For example firmware
@@ -174,6 +170,11 @@ static unsigned long __init init_initrd(void)
        initrd_end = (unsigned long)__va(end);
        initrd_start = (unsigned long)__va(__pa(initrd_start));
 
+       if (initrd_start < PAGE_OFFSET) {
+               pr_err("initrd start < PAGE_OFFSET\n");
+               goto disable;
+       }
+
        ROOT_DEV = Root_RAM0;
        return PFN_UP(end);
 disable:
index 466a25525364d2d45e7ed5bf286856242fdc90d2..967bde65dd0ec895d78b2314a49aa8cb043e28c0 100644 (file)
@@ -130,6 +130,10 @@ config PM
 config STACKTRACE_SUPPORT
        def_bool y
 
+config LOCKDEP_SUPPORT
+       bool
+       default y
+
 config ISA_DMA_API
        bool
 
index f66554cd5c4518cf919abf321ce9137e8b2be59d..3a059cb5e112fb09fe701fe362c07c84cec247e2 100644 (file)
@@ -1 +1,12 @@
 # SPDX-License-Identifier: GPL-2.0
+#
+config LIGHTWEIGHT_SPINLOCK_CHECK
+       bool "Enable lightweight spinlock checks"
+       depends on SMP && !DEBUG_SPINLOCK
+       default y
+       help
+         Add checks with low performance impact to the spinlock functions
+         to catch memory overwrites at runtime. For more advanced
+         spinlock debugging you should choose the DEBUG_SPINLOCK option
+         which will detect unitialized spinlocks too.
+         If unsure say Y here.
index 0bdee672413206aa9db8c23c4bd3fd3be2182660..c8b6928cee1ee442f4b9c9b0c996fe1801620f75 100644 (file)
@@ -48,6 +48,10 @@ void flush_dcache_page(struct page *page);
 
 #define flush_dcache_mmap_lock(mapping)                xa_lock_irq(&mapping->i_pages)
 #define flush_dcache_mmap_unlock(mapping)      xa_unlock_irq(&mapping->i_pages)
+#define flush_dcache_mmap_lock_irqsave(mapping, flags)         \
+               xa_lock_irqsave(&mapping->i_pages, flags)
+#define flush_dcache_mmap_unlock_irqrestore(mapping, flags)    \
+               xa_unlock_irqrestore(&mapping->i_pages, flags)
 
 #define flush_icache_page(vma,page)    do {            \
        flush_kernel_dcache_page_addr(page_address(page)); \
index e2950f5db7c9cf621f1409dc532d2c86591df759..e715df5385d6e5c415decd20f89d8c47f8ee5567 100644 (file)
@@ -413,12 +413,12 @@ extern void paging_init (void);
  *   For the 64bit version, the offset is extended by 32bit.
  */
 #define __swp_type(x)                     ((x).val & 0x1f)
-#define __swp_offset(x)                   ( (((x).val >> 6) &  0x7) | \
-                                         (((x).val >> 8) & ~0x7) )
+#define __swp_offset(x)                   ( (((x).val >> 5) & 0x7) | \
+                                         (((x).val >> 10) << 3) )
 #define __swp_entry(type, offset)         ((swp_entry_t) { \
                                            ((type) & 0x1f) | \
-                                           ((offset &  0x7) << 6) | \
-                                           ((offset & ~0x7) << 8) })
+                                           ((offset & 0x7) << 5) | \
+                                           ((offset >> 3) << 10) })
 #define __pte_to_swp_entry(pte)                ((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)          ((pte_t) { (x).val })
 
index a6e5d66a76562aaa8e89bab4b55e4aa39d13ad43..edfcb9858bcb7ca0bf2fee2cfeef304836beb4a5 100644 (file)
@@ -7,10 +7,26 @@
 #include <asm/processor.h>
 #include <asm/spinlock_types.h>
 
+#define SPINLOCK_BREAK_INSN    0x0000c006      /* break 6,6 */
+
+static inline void arch_spin_val_check(int lock_val)
+{
+       if (IS_ENABLED(CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK))
+               asm volatile(   "andcm,= %0,%1,%%r0\n"
+                               ".word %2\n"
+               : : "r" (lock_val), "r" (__ARCH_SPIN_LOCK_UNLOCKED_VAL),
+                       "i" (SPINLOCK_BREAK_INSN));
+}
+
 static inline int arch_spin_is_locked(arch_spinlock_t *x)
 {
-       volatile unsigned int *a = __ldcw_align(x);
-       return READ_ONCE(*a) == 0;
+       volatile unsigned int *a;
+       int lock_val;
+
+       a = __ldcw_align(x);
+       lock_val = READ_ONCE(*a);
+       arch_spin_val_check(lock_val);
+       return (lock_val == 0);
 }
 
 static inline void arch_spin_lock(arch_spinlock_t *x)
@@ -18,9 +34,18 @@ static inline void arch_spin_lock(arch_spinlock_t *x)
        volatile unsigned int *a;
 
        a = __ldcw_align(x);
-       while (__ldcw(a) == 0)
+       do {
+               int lock_val_old;
+
+               lock_val_old = __ldcw(a);
+               arch_spin_val_check(lock_val_old);
+               if (lock_val_old)
+                       return; /* got lock */
+
+               /* wait until we should try to get lock again */
                while (*a == 0)
                        continue;
+       } while (1);
 }
 
 static inline void arch_spin_unlock(arch_spinlock_t *x)
@@ -29,15 +54,19 @@ static inline void arch_spin_unlock(arch_spinlock_t *x)
 
        a = __ldcw_align(x);
        /* Release with ordered store. */
-       __asm__ __volatile__("stw,ma %0,0(%1)" : : "r"(1), "r"(a) : "memory");
+       __asm__ __volatile__("stw,ma %0,0(%1)"
+               : : "r"(__ARCH_SPIN_LOCK_UNLOCKED_VAL), "r"(a) : "memory");
 }
 
 static inline int arch_spin_trylock(arch_spinlock_t *x)
 {
        volatile unsigned int *a;
+       int lock_val;
 
        a = __ldcw_align(x);
-       return __ldcw(a) != 0;
+       lock_val = __ldcw(a);
+       arch_spin_val_check(lock_val);
+       return lock_val != 0;
 }
 
 /*
index ca39ee350c3f422eee3ff28fa39cd5090600464e..d65934079ebdb032967f86976da3fc8963a84f80 100644 (file)
@@ -2,13 +2,17 @@
 #ifndef __ASM_SPINLOCK_TYPES_H
 #define __ASM_SPINLOCK_TYPES_H
 
+#define __ARCH_SPIN_LOCK_UNLOCKED_VAL  0x1a46
+
 typedef struct {
 #ifdef CONFIG_PA20
        volatile unsigned int slock;
-# define __ARCH_SPIN_LOCK_UNLOCKED { 1 }
+# define __ARCH_SPIN_LOCK_UNLOCKED { __ARCH_SPIN_LOCK_UNLOCKED_VAL }
 #else
        volatile unsigned int lock[4];
-# define __ARCH_SPIN_LOCK_UNLOCKED     { { 1, 1, 1, 1 } }
+# define __ARCH_SPIN_LOCK_UNLOCKED     \
+       { { __ARCH_SPIN_LOCK_UNLOCKED_VAL, __ARCH_SPIN_LOCK_UNLOCKED_VAL, \
+           __ARCH_SPIN_LOCK_UNLOCKED_VAL, __ARCH_SPIN_LOCK_UNLOCKED_VAL } }
 #endif
 } arch_spinlock_t;
 
index 66f5672c70bd469e6e1a261c4a7c080be1d808f5..25c4d6c3375db357f73c12e48826c941b92fc621 100644 (file)
@@ -25,7 +25,7 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
 {
        struct alt_instr *entry;
        int index = 0, applied = 0;
-       int num_cpus = num_online_cpus();
+       int num_cpus = num_present_cpus();
        u16 cond_check;
 
        cond_check = ALT_COND_ALWAYS |
index 1d3b8bc8a6233641c4eeea6d8b775887b0de9a4e..ca4a302d4365fe9e7472d3c748b69369233610af 100644 (file)
@@ -399,6 +399,7 @@ void flush_dcache_page(struct page *page)
        unsigned long offset;
        unsigned long addr, old_addr = 0;
        unsigned long count = 0;
+       unsigned long flags;
        pgoff_t pgoff;
 
        if (mapping && !mapping_mapped(mapping)) {
@@ -420,7 +421,7 @@ void flush_dcache_page(struct page *page)
         * to flush one address here for them all to become coherent
         * on machines that support equivalent aliasing
         */
-       flush_dcache_mmap_lock(mapping);
+       flush_dcache_mmap_lock_irqsave(mapping, flags);
        vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
                offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
                addr = mpnt->vm_start + offset;
@@ -460,7 +461,7 @@ void flush_dcache_page(struct page *page)
                }
                WARN_ON(++count == 4096);
        }
-       flush_dcache_mmap_unlock(mapping);
+       flush_dcache_mmap_unlock_irqrestore(mapping, flags);
 }
 EXPORT_SYMBOL(flush_dcache_page);
 
index 5eb7f30edc1f7da3eedd284ada33cda9ef0a9d52..db57345a9dafba360f90684964a86040580fa68e 100644 (file)
@@ -4,6 +4,8 @@
 #include <linux/console.h>
 #include <linux/kexec.h>
 #include <linux/delay.h>
+#include <linux/reboot.h>
+
 #include <asm/cacheflush.h>
 #include <asm/sections.h>
 
index ba87f791323be008d1e6abfcfbe846a55575cbf5..71ed5391f29d6f00ec85168b02cce2fe4eccb097 100644 (file)
@@ -446,11 +446,27 @@ void arch_dma_free(struct device *dev, size_t size, void *vaddr,
 void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
                enum dma_data_direction dir)
 {
+       /*
+        * fdc: The data cache line is written back to memory, if and only if
+        * it is dirty, and then invalidated from the data cache.
+        */
        flush_kernel_dcache_range((unsigned long)phys_to_virt(paddr), size);
 }
 
 void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
                enum dma_data_direction dir)
 {
-       flush_kernel_dcache_range((unsigned long)phys_to_virt(paddr), size);
+       unsigned long addr = (unsigned long) phys_to_virt(paddr);
+
+       switch (dir) {
+       case DMA_TO_DEVICE:
+       case DMA_BIDIRECTIONAL:
+               flush_kernel_dcache_range(addr, size);
+               return;
+       case DMA_FROM_DEVICE:
+               purge_kernel_dcache_range_asm(addr, addr + size);
+               return;
+       default:
+               BUG();
+       }
 }
index 97c6f875bd0e12f188215afa07815356711593f5..24411ab79c307d4ab78f33303a7b1d8afb7d1c1d 100644 (file)
@@ -122,13 +122,18 @@ void machine_power_off(void)
        /* It seems we have no way to power the system off via
         * software. The user has to press the button himself. */
 
-       printk(KERN_EMERG "System shut down completed.\n"
-              "Please power this system off now.");
+       printk("Power off or press RETURN to reboot.\n");
 
        /* prevent soft lockup/stalled CPU messages for endless loop. */
        rcu_sysrq_start();
        lockup_detector_soft_poweroff();
-       for (;;);
+       while (1) {
+               /* reboot if user presses RETURN key */
+               if (pdc_iodc_getc() == 13) {
+                       printk("Rebooting...\n");
+                       machine_restart(NULL);
+               }
+       }
 }
 
 void (*pm_power_off)(void);
index f9696fbf646c473cffbe26f316b1bcd289054431..304eebd1c83e7d802fd9b1d726d479fbaeefa175 100644 (file)
 #include <linux/kgdb.h>
 #include <linux/kprobes.h>
 
+#if defined(CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK)
+#include <asm/spinlock.h>
+#endif
+
 #include "../math-emu/math-emu.h"      /* for handle_fpe() */
 
 static void parisc_show_stack(struct task_struct *task,
@@ -291,24 +295,30 @@ static void handle_break(struct pt_regs *regs)
        }
 
 #ifdef CONFIG_KPROBES
-       if (unlikely(iir == PARISC_KPROBES_BREAK_INSN)) {
+       if (unlikely(iir == PARISC_KPROBES_BREAK_INSN && !user_mode(regs))) {
                parisc_kprobe_break_handler(regs);
                return;
        }
-       if (unlikely(iir == PARISC_KPROBES_BREAK_INSN2)) {
+       if (unlikely(iir == PARISC_KPROBES_BREAK_INSN2 && !user_mode(regs))) {
                parisc_kprobe_ss_handler(regs);
                return;
        }
 #endif
 
 #ifdef CONFIG_KGDB
-       if (unlikely(iir == PARISC_KGDB_COMPILED_BREAK_INSN ||
-               iir == PARISC_KGDB_BREAK_INSN)) {
+       if (unlikely((iir == PARISC_KGDB_COMPILED_BREAK_INSN ||
+               iir == PARISC_KGDB_BREAK_INSN)) && !user_mode(regs)) {
                kgdb_handle_exception(9, SIGTRAP, 0, regs);
                return;
        }
 #endif
 
+#ifdef CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK
+        if ((iir == SPINLOCK_BREAK_INSN) && !user_mode(regs)) {
+               die_if_kernel("Spinlock was trashed", regs, 1);
+       }
+#endif
+
        if (unlikely(iir != GDB_BREAK_INSN))
                parisc_printk_ratelimited(0, regs,
                        KERN_DEBUG "break %d,%d: pid=%d command='%s'\n",
index 539d1f03ff42a5a60527836791f3b17cead05e05..bff5820b7cda14714f6b76da3bac2de92c8f740f 100644 (file)
@@ -906,11 +906,17 @@ config DATA_SHIFT
 
 config ARCH_FORCE_MAX_ORDER
        int "Order of maximal physically contiguous allocations"
+       range 7 8 if PPC64 && PPC_64K_PAGES
        default "8" if PPC64 && PPC_64K_PAGES
+       range 12 12 if PPC64 && !PPC_64K_PAGES
        default "12" if PPC64 && !PPC_64K_PAGES
+       range 8 10 if PPC32 && PPC_16K_PAGES
        default "8" if PPC32 && PPC_16K_PAGES
+       range 6 10 if PPC32 && PPC_64K_PAGES
        default "6" if PPC32 && PPC_64K_PAGES
+       range 4 10 if PPC32 && PPC_256K_PAGES
        default "4" if PPC32 && PPC_256K_PAGES
+       range 10 10
        default "10"
        help
          The kernel page allocator limits the size of maximal physically
index 85cde5bf04b7ae7c3cfdb2394cbf67d4c7c96e0e..771b79423bbc2b4ea4ee4d5a5fa3c07b0a14d53c 100644 (file)
@@ -34,8 +34,6 @@ endif
 
 BOOTCFLAGS    := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
                 -fno-strict-aliasing -O2 -msoft-float -mno-altivec -mno-vsx \
-                $(call cc-option,-mno-prefixed) $(call cc-option,-mno-pcrel) \
-                $(call cc-option,-mno-mma) \
                 $(call cc-option,-mno-spe) $(call cc-option,-mspe=no) \
                 -pipe -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \
                 $(LINUXINCLUDE)
@@ -71,6 +69,10 @@ BOOTAFLAGS   := -D__ASSEMBLY__ $(BOOTCFLAGS) -nostdinc
 
 BOOTARFLAGS    := -crD
 
+BOOTCFLAGS     += $(call cc-option,-mno-prefixed) \
+                  $(call cc-option,-mno-pcrel) \
+                  $(call cc-option,-mno-mma)
+
 ifdef CONFIG_CC_IS_CLANG
 BOOTCFLAGS += $(CLANG_FLAGS)
 BOOTAFLAGS += $(CLANG_FLAGS)
index 7113f9355165a663732964cdf1890541936a36a8..ad1872518992e0a074a250ff46997eb3d02740f4 100644 (file)
@@ -96,7 +96,7 @@ config CRYPTO_AES_PPC_SPE
 
 config CRYPTO_AES_GCM_P10
        tristate "Stitched AES/GCM acceleration support on P10 or later CPU (PPC)"
-       depends on PPC64 && CPU_LITTLE_ENDIAN
+       depends on PPC64 && CPU_LITTLE_ENDIAN && VSX
        select CRYPTO_LIB_AES
        select CRYPTO_ALGAPI
        select CRYPTO_AEAD
index 05c7486f42c587b1bf1c59b3ad756c4a6f474609..7b4f516abec1d35b221b29ac6fec238f0eb55d99 100644 (file)
@@ -22,15 +22,15 @@ sha1-ppc-spe-y := sha1-spe-asm.o sha1-spe-glue.o
 sha256-ppc-spe-y := sha256-spe-asm.o sha256-spe-glue.o
 crc32c-vpmsum-y := crc32c-vpmsum_asm.o crc32c-vpmsum_glue.o
 crct10dif-vpmsum-y := crct10dif-vpmsum_asm.o crct10dif-vpmsum_glue.o
-aes-gcm-p10-crypto-y := aes-gcm-p10-glue.o aes-gcm-p10.o ghashp8-ppc.o aesp8-ppc.o
+aes-gcm-p10-crypto-y := aes-gcm-p10-glue.o aes-gcm-p10.o ghashp10-ppc.o aesp10-ppc.o
 
 quiet_cmd_perl = PERL    $@
       cmd_perl = $(PERL) $< $(if $(CONFIG_CPU_LITTLE_ENDIAN), linux-ppc64le, linux-ppc64) > $@
 
-targets += aesp8-ppc.S ghashp8-ppc.S
+targets += aesp10-ppc.S ghashp10-ppc.S
 
-$(obj)/aesp8-ppc.S $(obj)/ghashp8-ppc.S: $(obj)/%.S: $(src)/%.pl FORCE
+$(obj)/aesp10-ppc.S $(obj)/ghashp10-ppc.S: $(obj)/%.S: $(src)/%.pl FORCE
        $(call if_changed,perl)
 
-OBJECT_FILES_NON_STANDARD_aesp8-ppc.o := y
-OBJECT_FILES_NON_STANDARD_ghashp8-ppc.o := y
+OBJECT_FILES_NON_STANDARD_aesp10-ppc.o := y
+OBJECT_FILES_NON_STANDARD_ghashp10-ppc.o := y
index bd3475f5348d99ec0620c968fd95bcffed2388cc..4b6e899895e7be8214d021559e9d0d7fbc8d65d2 100644 (file)
@@ -30,15 +30,15 @@ MODULE_AUTHOR("Danny Tsen <dtsen@linux.ibm.com");
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS_CRYPTO("aes");
 
-asmlinkage int aes_p8_set_encrypt_key(const u8 *userKey, const int bits,
+asmlinkage int aes_p10_set_encrypt_key(const u8 *userKey, const int bits,
                                      void *key);
-asmlinkage void aes_p8_encrypt(const u8 *in, u8 *out, const void *key);
+asmlinkage void aes_p10_encrypt(const u8 *in, u8 *out, const void *key);
 asmlinkage void aes_p10_gcm_encrypt(u8 *in, u8 *out, size_t len,
                                    void *rkey, u8 *iv, void *Xi);
 asmlinkage void aes_p10_gcm_decrypt(u8 *in, u8 *out, size_t len,
                                    void *rkey, u8 *iv, void *Xi);
 asmlinkage void gcm_init_htable(unsigned char htable[256], unsigned char Xi[16]);
-asmlinkage void gcm_ghash_p8(unsigned char *Xi, unsigned char *Htable,
+asmlinkage void gcm_ghash_p10(unsigned char *Xi, unsigned char *Htable,
                unsigned char *aad, unsigned int alen);
 
 struct aes_key {
@@ -93,7 +93,7 @@ static void set_aad(struct gcm_ctx *gctx, struct Hash_ctx *hash,
        gctx->aadLen = alen;
        i = alen & ~0xf;
        if (i) {
-               gcm_ghash_p8(nXi, hash->Htable+32, aad, i);
+               gcm_ghash_p10(nXi, hash->Htable+32, aad, i);
                aad += i;
                alen -= i;
        }
@@ -102,7 +102,7 @@ static void set_aad(struct gcm_ctx *gctx, struct Hash_ctx *hash,
                        nXi[i] ^= aad[i];
 
                memset(gctx->aad_hash, 0, 16);
-               gcm_ghash_p8(gctx->aad_hash, hash->Htable+32, nXi, 16);
+               gcm_ghash_p10(gctx->aad_hash, hash->Htable+32, nXi, 16);
        } else {
                memcpy(gctx->aad_hash, nXi, 16);
        }
@@ -115,7 +115,7 @@ static void gcmp10_init(struct gcm_ctx *gctx, u8 *iv, unsigned char *rdkey,
 {
        __be32 counter = cpu_to_be32(1);
 
-       aes_p8_encrypt(hash->H, hash->H, rdkey);
+       aes_p10_encrypt(hash->H, hash->H, rdkey);
        set_subkey(hash->H);
        gcm_init_htable(hash->Htable+32, hash->H);
 
@@ -126,7 +126,7 @@ static void gcmp10_init(struct gcm_ctx *gctx, u8 *iv, unsigned char *rdkey,
        /*
         * Encrypt counter vector as iv tag and increment counter.
         */
-       aes_p8_encrypt(iv, gctx->ivtag, rdkey);
+       aes_p10_encrypt(iv, gctx->ivtag, rdkey);
 
        counter = cpu_to_be32(2);
        *((__be32 *)(iv+12)) = counter;
@@ -160,7 +160,7 @@ static void finish_tag(struct gcm_ctx *gctx, struct Hash_ctx *hash, int len)
        /*
         * hash (AAD len and len)
         */
-       gcm_ghash_p8(hash->Htable, hash->Htable+32, aclen, 16);
+       gcm_ghash_p10(hash->Htable, hash->Htable+32, aclen, 16);
 
        for (i = 0; i < 16; i++)
                hash->Htable[i] ^= gctx->ivtag[i];
@@ -192,7 +192,7 @@ static int p10_aes_gcm_setkey(struct crypto_aead *aead, const u8 *key,
        int ret;
 
        vsx_begin();
-       ret = aes_p8_set_encrypt_key(key, keylen * 8, &ctx->enc_key);
+       ret = aes_p10_set_encrypt_key(key, keylen * 8, &ctx->enc_key);
        vsx_end();
 
        return ret ? -EINVAL : 0;
similarity index 99%
rename from arch/powerpc/crypto/aesp8-ppc.pl
rename to arch/powerpc/crypto/aesp10-ppc.pl
index 1f22aec27d79970c5d1d7a4694cd6cb5416bc3d6..2c06ce2a2c7c02b159ac0108f8b380c3781f3403 100644 (file)
@@ -110,7 +110,7 @@ die "can't locate ppc-xlate.pl";
 open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
 
 $FRAME=8*$SIZE_T;
-$prefix="aes_p8";
+$prefix="aes_p10";
 
 $sp="r1";
 $vrsave="r12";
similarity index 97%
rename from arch/powerpc/crypto/ghashp8-ppc.pl
rename to arch/powerpc/crypto/ghashp10-ppc.pl
index b56603b4a893c756217255a51fe90fdadae77d24..27a6b0bec645f9ae4e457fcbdbe0bccda07dc71e 100644 (file)
@@ -64,7 +64,7 @@ $code=<<___;
 
 .text
 
-.globl .gcm_init_p8
+.globl .gcm_init_p10
        lis             r0,0xfff0
        li              r8,0x10
        mfspr           $vrsave,256
@@ -110,7 +110,7 @@ $code=<<___;
        .long           0
        .byte           0,12,0x14,0,0,0,2,0
        .long           0
-.size  .gcm_init_p8,.-.gcm_init_p8
+.size  .gcm_init_p10,.-.gcm_init_p10
 
 .globl .gcm_init_htable
        lis             r0,0xfff0
@@ -237,7 +237,7 @@ $code=<<___;
        .long           0
 .size  .gcm_init_htable,.-.gcm_init_htable
 
-.globl .gcm_gmult_p8
+.globl .gcm_gmult_p10
        lis             r0,0xfff8
        li              r8,0x10
        mfspr           $vrsave,256
@@ -283,9 +283,9 @@ $code=<<___;
        .long           0
        .byte           0,12,0x14,0,0,0,2,0
        .long           0
-.size  .gcm_gmult_p8,.-.gcm_gmult_p8
+.size  .gcm_gmult_p10,.-.gcm_gmult_p10
 
-.globl .gcm_ghash_p8
+.globl .gcm_ghash_p10
        lis             r0,0xfff8
        li              r8,0x10
        mfspr           $vrsave,256
@@ -350,7 +350,7 @@ Loop:
        .long           0
        .byte           0,12,0x14,0,0,0,4,0
        .long           0
-.size  .gcm_ghash_p8,.-.gcm_ghash_p8
+.size  .gcm_ghash_p10,.-.gcm_ghash_p10
 
 .asciz  "GHASH for PowerISA 2.07, CRYPTOGAMS by <appro\@openssl.org>"
 .align  2
index 678b5bdc79b1f5df91372ce5c95fbde92a676918..34e14dfd8e042a679df1dd50cf6d6586aae0f099 100644 (file)
@@ -205,7 +205,6 @@ extern void iommu_register_group(struct iommu_table_group *table_group,
                                 int pci_domain_number, unsigned long pe_num);
 extern int iommu_add_device(struct iommu_table_group *table_group,
                struct device *dev);
-extern void iommu_del_device(struct device *dev);
 extern long iommu_tce_xchg(struct mm_struct *mm, struct iommu_table *tbl,
                unsigned long entry, unsigned long *hpa,
                enum dma_data_direction *direction);
@@ -229,10 +228,6 @@ static inline int iommu_add_device(struct iommu_table_group *table_group,
 {
        return 0;
 }
-
-static inline void iommu_del_device(struct device *dev)
-{
-}
 #endif /* !CONFIG_IOMMU_API */
 
 u64 dma_iommu_get_required_mask(struct device *dev);
index 038ce8d9061d166b8c85663adc2fa4dab08c23f1..8920862ffd7916ef3afcde6714a1676ae6a1f647 100644 (file)
@@ -144,7 +144,7 @@ static bool dma_iommu_bypass_supported(struct device *dev, u64 mask)
 /* We support DMA to/from any memory page via the iommu */
 int dma_iommu_dma_supported(struct device *dev, u64 mask)
 {
-       struct iommu_table *tbl = get_iommu_table_base(dev);
+       struct iommu_table *tbl;
 
        if (dev_is_pci(dev) && dma_iommu_bypass_supported(dev, mask)) {
                /*
@@ -162,6 +162,8 @@ int dma_iommu_dma_supported(struct device *dev, u64 mask)
                return 1;
        }
 
+       tbl = get_iommu_table_base(dev);
+
        if (!tbl) {
                dev_err(dev, "Warning: IOMMU dma not supported: mask 0x%08llx, table unavailable\n", mask);
                return 0;
index 0089dd49b4cbf71a964aee0dd7ae5165853fbb70..67f0b01e6ff575d54d95532f04e70e735b3640ee 100644 (file)
@@ -518,7 +518,7 @@ int ppc_iommu_map_sg(struct device *dev, struct iommu_table *tbl,
                /* Convert entry to a dma_addr_t */
                entry += tbl->it_offset;
                dma_addr = entry << tbl->it_page_shift;
-               dma_addr |= (s->offset & ~IOMMU_PAGE_MASK(tbl));
+               dma_addr |= (vaddr & ~IOMMU_PAGE_MASK(tbl));
 
                DBG("  - %lu pages, entry: %lx, dma_addr: %lx\n",
                            npages, entry, dma_addr);
@@ -905,6 +905,7 @@ void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
        unsigned int order;
        unsigned int nio_pages, io_order;
        struct page *page;
+       int tcesize = (1 << tbl->it_page_shift);
 
        size = PAGE_ALIGN(size);
        order = get_order(size);
@@ -931,7 +932,8 @@ void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
        memset(ret, 0, size);
 
        /* Set up tces to cover the allocated range */
-       nio_pages = size >> tbl->it_page_shift;
+       nio_pages = IOMMU_PAGE_ALIGN(size, tbl) >> tbl->it_page_shift;
+
        io_order = get_iommu_order(size, tbl);
        mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
                              mask >> tbl->it_page_shift, io_order, 0);
@@ -939,7 +941,8 @@ void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
                free_pages((unsigned long)ret, order);
                return NULL;
        }
-       *dma_handle = mapping;
+
+       *dma_handle = mapping | ((u64)ret & (tcesize - 1));
        return ret;
 }
 
@@ -950,7 +953,7 @@ void iommu_free_coherent(struct iommu_table *tbl, size_t size,
                unsigned int nio_pages;
 
                size = PAGE_ALIGN(size);
-               nio_pages = size >> tbl->it_page_shift;
+               nio_pages = IOMMU_PAGE_ALIGN(size, tbl) >> tbl->it_page_shift;
                iommu_free(tbl, dma_handle, nio_pages);
                size = PAGE_ALIGN(size);
                free_pages((unsigned long)vaddr, get_order(size));
@@ -1168,23 +1171,6 @@ int iommu_add_device(struct iommu_table_group *table_group, struct device *dev)
 }
 EXPORT_SYMBOL_GPL(iommu_add_device);
 
-void iommu_del_device(struct device *dev)
-{
-       /*
-        * Some devices might not have IOMMU table and group
-        * and we needn't detach them from the associated
-        * IOMMU groups
-        */
-       if (!device_iommu_mapped(dev)) {
-               pr_debug("iommu_tce: skipping device %s with no tbl\n",
-                        dev_name(dev));
-               return;
-       }
-
-       iommu_group_remove_device(dev);
-}
-EXPORT_SYMBOL_GPL(iommu_del_device);
-
 /*
  * A simple iommu_table_group_ops which only allows reusing the existing
  * iommu_table. This handles VFIO for POWER7 or the nested KVM.
index 85bdd7d3652f84222f2cb6cdcc0be1d4a9664099..48e0eaf1ad61559a374fe83b33c65aee6ef35e7f 100644 (file)
@@ -93,11 +93,12 @@ static int process_ISA_OF_ranges(struct device_node *isa_node,
        }
 
 inval_range:
-       if (!phb_io_base_phys) {
+       if (phb_io_base_phys) {
                pr_err("no ISA IO ranges or unexpected isa range, mapping 64k\n");
                remap_isa_base(phb_io_base_phys, 0x10000);
+               return 0;
        }
-       return 0;
+       return -EINVAL;
 }
 
 
index 26245aaf12b8bddb8f6082ce5b2b3c093f2e00cc..2297aa764ecdbcedbaf7958df234f5d5c4408470 100644 (file)
@@ -1040,8 +1040,8 @@ void radix__ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep,
                                  pte_t entry, unsigned long address, int psize)
 {
        struct mm_struct *mm = vma->vm_mm;
-       unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED |
-                                             _PAGE_RW | _PAGE_EXEC);
+       unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_SOFT_DIRTY |
+                                             _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
 
        unsigned long change = pte_val(entry) ^ pte_val(*ptep);
        /*
index e93aefcfb83f2663008833d9a845ae3a83b22556..37043dfc1adddf67b84f881fe751216db87162ec 100644 (file)
@@ -101,6 +101,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
                bpf_hdr = jit_data->header;
                proglen = jit_data->proglen;
                extra_pass = true;
+               /* During extra pass, ensure index is reset before repopulating extable entries */
+               cgctx.exentry_idx = 0;
                goto skip_init_ctx;
        }
 
index 0d9b7609c7d5629404594eb9bec518795aae0763..3e2e252016f7a6e66de2e85a5c6bb548a36c1688 100644 (file)
@@ -265,6 +265,7 @@ config CPM2
 config FSL_ULI1575
        bool "ULI1575 PCIe south bridge support"
        depends on FSL_SOC_BOOKE || PPC_86xx
+       depends on PCI
        select FSL_PCI
        select GENERIC_ISA_DMA
        help
index 233a50e65fceddf8d641d71c40f989df7a219144..7725492097b627ff70b6026f0c9267bf94feb9be 100644 (file)
@@ -865,28 +865,3 @@ void __init pnv_pci_init(void)
        /* Configure IOMMU DMA hooks */
        set_pci_dma_ops(&dma_iommu_ops);
 }
-
-static int pnv_tce_iommu_bus_notifier(struct notifier_block *nb,
-               unsigned long action, void *data)
-{
-       struct device *dev = data;
-
-       switch (action) {
-       case BUS_NOTIFY_DEL_DEVICE:
-               iommu_del_device(dev);
-               return 0;
-       default:
-               return 0;
-       }
-}
-
-static struct notifier_block pnv_tce_iommu_bus_nb = {
-       .notifier_call = pnv_tce_iommu_bus_notifier,
-};
-
-static int __init pnv_tce_iommu_bus_notifier_init(void)
-{
-       bus_register_notifier(&pci_bus_type, &pnv_tce_iommu_bus_nb);
-       return 0;
-}
-machine_subsys_initcall_sync(powernv, pnv_tce_iommu_bus_notifier_init);
index 7464fa6e41455385b06885e5720bfcb1a5e9dc05..d59e8a98a200826c75a1602129312b8014f5f26d 100644 (file)
@@ -91,19 +91,24 @@ static struct iommu_table_group *iommu_pseries_alloc_group(int node)
 static void iommu_pseries_free_group(struct iommu_table_group *table_group,
                const char *node_name)
 {
-       struct iommu_table *tbl;
-
        if (!table_group)
                return;
 
-       tbl = table_group->tables[0];
 #ifdef CONFIG_IOMMU_API
        if (table_group->group) {
                iommu_group_put(table_group->group);
                BUG_ON(table_group->group);
        }
 #endif
-       iommu_tce_table_put(tbl);
+
+       /* Default DMA window table is at index 0, while DDW at 1. SR-IOV
+        * adapters only have table on index 1.
+        */
+       if (table_group->tables[0])
+               iommu_tce_table_put(table_group->tables[0]);
+
+       if (table_group->tables[1])
+               iommu_tce_table_put(table_group->tables[1]);
 
        kfree(table_group);
 }
@@ -312,13 +317,22 @@ static void tce_free_pSeriesLP(unsigned long liobn, long tcenum, long tceshift,
 static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
 {
        u64 rc;
+       long rpages = npages;
+       unsigned long limit;
 
        if (!firmware_has_feature(FW_FEATURE_STUFF_TCE))
                return tce_free_pSeriesLP(tbl->it_index, tcenum,
                                          tbl->it_page_shift, npages);
 
-       rc = plpar_tce_stuff((u64)tbl->it_index,
-                            (u64)tcenum << tbl->it_page_shift, 0, npages);
+       do {
+               limit = min_t(unsigned long, rpages, 512);
+
+               rc = plpar_tce_stuff((u64)tbl->it_index,
+                                    (u64)tcenum << tbl->it_page_shift, 0, limit);
+
+               rpages -= limit;
+               tcenum += limit;
+       } while (rpages > 0 && !rc);
 
        if (rc && printk_ratelimit()) {
                printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
@@ -1695,31 +1709,6 @@ static int __init disable_multitce(char *str)
 
 __setup("multitce=", disable_multitce);
 
-static int tce_iommu_bus_notifier(struct notifier_block *nb,
-               unsigned long action, void *data)
-{
-       struct device *dev = data;
-
-       switch (action) {
-       case BUS_NOTIFY_DEL_DEVICE:
-               iommu_del_device(dev);
-               return 0;
-       default:
-               return 0;
-       }
-}
-
-static struct notifier_block tce_iommu_bus_nb = {
-       .notifier_call = tce_iommu_bus_notifier,
-};
-
-static int __init tce_iommu_bus_notifier_init(void)
-{
-       bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb);
-       return 0;
-}
-machine_subsys_initcall_sync(pseries, tce_iommu_bus_notifier_init);
-
 #ifdef CONFIG_SPAPR_TCE_IOMMU
 struct iommu_group *pSeries_pci_device_group(struct pci_controller *hose,
                                             struct pci_dev *pdev)
index 728d3c257e4a33323bdca9716dd2658548fc693a..70c4c59a1a8f47f103ba180935974b6e71f6db31 100644 (file)
@@ -88,7 +88,7 @@ static unsigned long ndump = 64;
 static unsigned long nidump = 16;
 static unsigned long ncsum = 4096;
 static int termch;
-static char tmpstr[128];
+static char tmpstr[KSYM_NAME_LEN];
 static int tracing_enabled;
 
 static long bus_error_jmp[JMP_BUF_LEN];
index 348c0fa1fc8c7a8479c42c70bdede50a8a3c5126..2bb0c38419ff5347faff88554277e8acf7bd6d25 100644 (file)
@@ -799,8 +799,11 @@ menu "Power management options"
 
 source "kernel/power/Kconfig"
 
+# Hibernation is only possible on systems where the SBI implementation has
+# marked its reserved memory as not accessible from, or does not run
+# from the same memory as, Linux
 config ARCH_HIBERNATION_POSSIBLE
-       def_bool y
+       def_bool NONPORTABLE
 
 config ARCH_HIBERNATION_HEADER
        def_bool HIBERNATION
index a1055965fbee6a6da0b173f9e894e79f8930dfd1..7b2637c8c332653f5c5551a88c0947f732233b23 100644 (file)
@@ -1,2 +1,6 @@
+ifdef CONFIG_RELOCATABLE
+KBUILD_CFLAGS += -fno-pie
+endif
+
 obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
 obj-$(CONFIG_ERRATA_THEAD) += thead/
index fe6f2300664162c1b0e233e1323aeb96c2d33746..ce1ebda1a49a79b41c240b033c94b2c47d90c465 100644 (file)
@@ -36,6 +36,9 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
                               unsigned long addr, pte_t *ptep,
                               pte_t pte, int dirty);
 
+#define __HAVE_ARCH_HUGE_PTEP_GET
+pte_t huge_ptep_get(pte_t *ptep);
+
 pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags);
 #define arch_make_huge_pte arch_make_huge_pte
 
index d42c901f9a9770985b53da11098d69cf7934cc62..665bbc9b2f840a5272eb493d799f21dab73dfd25 100644 (file)
 
 #include <linux/perf_event.h>
 #define perf_arch_bpf_user_pt_regs(regs) (struct user_regs_struct *)regs
+
+#define perf_arch_fetch_caller_regs(regs, __ip) { \
+       (regs)->epc = (__ip); \
+       (regs)->s0 = (unsigned long) __builtin_frame_address(0); \
+       (regs)->sp = current_stack_pointer; \
+       (regs)->status = SR_PP; \
+}
 #endif /* _ASM_RISCV_PERF_EVENT_H */
index fbdccc21418a5b9bf0d53de537089b879a04a429..153864e4f3996dc3405a28fc024e0d76f0232028 100644 (file)
@@ -23,6 +23,10 @@ ifdef CONFIG_FTRACE
 CFLAGS_REMOVE_alternative.o = $(CC_FLAGS_FTRACE)
 CFLAGS_REMOVE_cpufeature.o = $(CC_FLAGS_FTRACE)
 endif
+ifdef CONFIG_RELOCATABLE
+CFLAGS_alternative.o += -fno-pie
+CFLAGS_cpufeature.o += -fno-pie
+endif
 ifdef CONFIG_KASAN
 KASAN_SANITIZE_alternative.o := n
 KASAN_SANITIZE_cpufeature.o := n
index 5d7cb991f2b86c8d7604ee21dd9f04eb1482f4ee..7b593d44c712aa7a06ddc5a66da73eb7e3184083 100644 (file)
@@ -22,7 +22,7 @@ KCOV_INSTRUMENT       := n
 
 $(obj)/%.pi.o: OBJCOPYFLAGS := --prefix-symbols=__pi_ \
                               --remove-section=.note.gnu.property \
-                              --prefix-alloc-sections=.init
+                              --prefix-alloc-sections=.init.pi
 $(obj)/%.pi.o: $(obj)/%.o FORCE
        $(call if_changed,objcopy)
 
index c40139e9ca4781e414946bd9e58648f15c89d25a..8265ff497977cffb5559f25a2bd6adcce2eb1a60 100644 (file)
@@ -4,3 +4,5 @@ obj-$(CONFIG_RETHOOK)           += rethook.o rethook_trampoline.o
 obj-$(CONFIG_KPROBES_ON_FTRACE)        += ftrace.o
 obj-$(CONFIG_UPROBES)          += uprobes.o decode-insn.o simulate-insn.o
 CFLAGS_REMOVE_simulate-insn.o = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_rethook.o = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_rethook_trampoline.o = $(CC_FLAGS_FTRACE)
index f03b5697f8e05ae8256c54683a4cebaca72681cb..e5f9f4677bbfdabd2f5af995f281267414422aad 100644 (file)
@@ -84,11 +84,8 @@ SECTIONS
        __init_data_begin = .;
        INIT_DATA_SECTION(16)
 
-       /* Those sections result from the compilation of kernel/pi/string.c */
-       .init.pidata : {
-               *(.init.srodata.cst8*)
-               *(.init__bug_table*)
-               *(.init.sdata*)
+       .init.pi : {
+               *(.init.pi*)
        }
 
        .init.bss : {
index a163a3e0f0d46b92565e85318c105b9cf0891c29..e0ef56dc57b90a31a9ef95072f4360019ac84ba1 100644 (file)
@@ -3,6 +3,30 @@
 #include <linux/err.h>
 
 #ifdef CONFIG_RISCV_ISA_SVNAPOT
+pte_t huge_ptep_get(pte_t *ptep)
+{
+       unsigned long pte_num;
+       int i;
+       pte_t orig_pte = ptep_get(ptep);
+
+       if (!pte_present(orig_pte) || !pte_napot(orig_pte))
+               return orig_pte;
+
+       pte_num = napot_pte_num(napot_cont_order(orig_pte));
+
+       for (i = 0; i < pte_num; i++, ptep++) {
+               pte_t pte = ptep_get(ptep);
+
+               if (pte_dirty(pte))
+                       orig_pte = pte_mkdirty(orig_pte);
+
+               if (pte_young(pte))
+                       orig_pte = pte_mkyoung(orig_pte);
+       }
+
+       return orig_pte;
+}
+
 pte_t *huge_pte_alloc(struct mm_struct *mm,
                      struct vm_area_struct *vma,
                      unsigned long addr,
@@ -218,6 +242,7 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
 {
        pte_t pte = ptep_get(ptep);
        unsigned long order;
+       pte_t orig_pte;
        int i, pte_num;
 
        if (!pte_napot(pte)) {
@@ -228,9 +253,12 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
        order = napot_cont_order(pte);
        pte_num = napot_pte_num(order);
        ptep = huge_pte_offset(mm, addr, napot_cont_size(order));
+       orig_pte = get_clear_contig_flush(mm, addr, ptep, pte_num);
+
+       orig_pte = pte_wrprotect(orig_pte);
 
        for (i = 0; i < pte_num; i++, addr += PAGE_SIZE, ptep++)
-               ptep_set_wrprotect(mm, addr, ptep);
+               set_pte_at(mm, addr, ptep, orig_pte);
 }
 
 pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
index 747e5b1ef02d35ebbc2fdaed3f6af793f0d2a5b5..c6bb966e4123720cec00b2e6a5b1694aeea2e1ee 100644 (file)
@@ -922,9 +922,9 @@ static void __init create_kernel_page_table(pgd_t *pgdir, bool early)
 static void __init create_fdt_early_page_table(uintptr_t fix_fdt_va,
                                               uintptr_t dtb_pa)
 {
+#ifndef CONFIG_BUILTIN_DTB
        uintptr_t pa = dtb_pa & ~(PMD_SIZE - 1);
 
-#ifndef CONFIG_BUILTIN_DTB
        /* Make sure the fdt fixmap address is always aligned on PMD size */
        BUILD_BUG_ON(FIX_FDT % (PMD_SIZE / PAGE_SIZE));
 
index db20c1589a98f3905d57f452ff19fc53380a45c6..6dab9c1be508b9138ef7dde50db6db2ef9ff5a3a 100644 (file)
@@ -469,19 +469,11 @@ config SCHED_SMT
 config SCHED_MC
        def_bool n
 
-config SCHED_BOOK
-       def_bool n
-
-config SCHED_DRAWER
-       def_bool n
-
 config SCHED_TOPOLOGY
        def_bool y
        prompt "Topology scheduler support"
        select SCHED_SMT
        select SCHED_MC
-       select SCHED_BOOK
-       select SCHED_DRAWER
        help
          Topology scheduler support improves the CPU scheduler's decision
          making when dealing with machines that have multi-threading,
@@ -716,7 +708,6 @@ config EADM_SCH
 config VFIO_CCW
        def_tristate n
        prompt "Support for VFIO-CCW subchannels"
-       depends on S390_CCW_IOMMU
        depends on VFIO
        select VFIO_MDEV
        help
@@ -728,7 +719,7 @@ config VFIO_CCW
 config VFIO_AP
        def_tristate n
        prompt "VFIO support for AP devices"
-       depends on S390_AP_IOMMU && KVM
+       depends on KVM
        depends on VFIO
        depends on ZCRYPT
        select VFIO_MDEV
index 4ccf66d29fc24b9cad9425fc0fcb9a01bfe4b3c0..be3bf03bf361850d9a0abd5cdb6644878ebec6a4 100644 (file)
@@ -591,8 +591,6 @@ CONFIG_VIRTIO_BALLOON=m
 CONFIG_VIRTIO_INPUT=y
 CONFIG_VHOST_NET=m
 CONFIG_VHOST_VSOCK=m
-CONFIG_S390_CCW_IOMMU=y
-CONFIG_S390_AP_IOMMU=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
@@ -703,6 +701,7 @@ CONFIG_IMA_DEFAULT_HASH_SHA256=y
 CONFIG_IMA_WRITE_POLICY=y
 CONFIG_IMA_APPRAISE=y
 CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"
+CONFIG_INIT_STACK_NONE=y
 CONFIG_CRYPTO_USER=m
 # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
 CONFIG_CRYPTO_PCRYPT=m
index 693297a2e89733d888c30e78e9d95f981c6db015..769c7eed8b6ac67f01ac781b6eac7721c21ce3b8 100644 (file)
@@ -580,8 +580,6 @@ CONFIG_VIRTIO_BALLOON=m
 CONFIG_VIRTIO_INPUT=y
 CONFIG_VHOST_NET=m
 CONFIG_VHOST_VSOCK=m
-CONFIG_S390_CCW_IOMMU=y
-CONFIG_S390_AP_IOMMU=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
@@ -686,6 +684,7 @@ CONFIG_IMA_DEFAULT_HASH_SHA256=y
 CONFIG_IMA_WRITE_POLICY=y
 CONFIG_IMA_APPRAISE=y
 CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"
+CONFIG_INIT_STACK_NONE=y
 CONFIG_CRYPTO_FIPS=y
 CONFIG_CRYPTO_USER=m
 # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
index 33a232bb68af95b460eb098136fbdd23e3045751..6f68b39817effcfc5f5a9612cd52ec465630be53 100644 (file)
@@ -67,6 +67,7 @@ CONFIG_ZFCP=y
 # CONFIG_MISC_FILESYSTEMS is not set
 # CONFIG_NETWORK_FILESYSTEMS is not set
 CONFIG_LSM="yama,loadpin,safesetid,integrity"
+CONFIG_INIT_STACK_NONE=y
 # CONFIG_ZLIB_DFLTCC is not set
 CONFIG_XZ_DEC_MICROLZMA=y
 CONFIG_PRINTK_TIME=y
index 7752bd314558e50ce6c0142c2472cb60297799f7..5fae187f947a08325ccb19ff792118fdcc661277 100644 (file)
@@ -82,7 +82,7 @@ void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src,
         * it cannot handle a block of data or less, but otherwise
         * it can handle data of arbitrary size
         */
-       if (bytes <= CHACHA_BLOCK_SIZE || nrounds != 20)
+       if (bytes <= CHACHA_BLOCK_SIZE || nrounds != 20 || !MACHINE_HAS_VX)
                chacha_crypt_generic(state, dst, src, bytes, nrounds);
        else
                chacha20_crypt_s390(state, dst, src, bytes,
index a386070f1d5653a97bf2aa075b21c23e83eac436..3cb9d813f022b9b8e565bca04f9ec1e805452e2f 100644 (file)
@@ -112,7 +112,7 @@ struct compat_statfs64 {
        u32             f_namelen;
        u32             f_frsize;
        u32             f_flags;
-       u32             f_spare[4];
+       u32             f_spare[5];
 };
 
 /*
index 72604f7792c33642aed1907bb0a69effd8b06991..f85b50723dd355f04a66e3ef5ac07bf89de0c6ff 100644 (file)
@@ -30,7 +30,7 @@ struct statfs {
        unsigned int    f_namelen;
        unsigned int    f_frsize;
        unsigned int    f_flags;
-       unsigned int    f_spare[4];
+       unsigned int    f_spare[5];
 };
 
 struct statfs64 {
@@ -45,7 +45,7 @@ struct statfs64 {
        unsigned int    f_namelen;
        unsigned int    f_frsize;
        unsigned int    f_flags;
-       unsigned int    f_spare[4];
+       unsigned int    f_spare[5];
 };
 
 #endif
index 8983837b3565914b19451546d7b5a1ff61511c95..6b2a051e1f8a2a7fec822ab5b287a9b25fd33a84 100644 (file)
@@ -10,6 +10,7 @@ CFLAGS_REMOVE_ftrace.o                = $(CC_FLAGS_FTRACE)
 
 # Do not trace early setup code
 CFLAGS_REMOVE_early.o          = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_rethook.o                = $(CC_FLAGS_FTRACE)
 
 endif
 
index 43de939b7af199757646a3ea82347897f6dd9980..f44f70de966115c64aa6286afb9bfe06f2543dc6 100644 (file)
@@ -1935,14 +1935,13 @@ static struct shutdown_action __refdata dump_action = {
 
 static void dump_reipl_run(struct shutdown_trigger *trigger)
 {
-       unsigned long ipib = (unsigned long) reipl_block_actual;
        struct lowcore *abs_lc;
        unsigned int csum;
 
        csum = (__force unsigned int)
               csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0);
        abs_lc = get_abs_lowcore();
-       abs_lc->ipib = ipib;
+       abs_lc->ipib = __pa(reipl_block_actual);
        abs_lc->ipib_checksum = csum;
        put_abs_lowcore(abs_lc);
        dump_run(trigger);
index 9fd19530c9a5623d5901abb1dd9e2032238203ba..68adf1de8888b25fbfaea0a45537e8cd4fb21c2f 100644 (file)
@@ -95,7 +95,7 @@ out:
 static void cpu_thread_map(cpumask_t *dst, unsigned int cpu)
 {
        static cpumask_t mask;
-       int i;
+       unsigned int max_cpu;
 
        cpumask_clear(&mask);
        if (!cpumask_test_cpu(cpu, &cpu_setup_mask))
@@ -104,9 +104,10 @@ static void cpu_thread_map(cpumask_t *dst, unsigned int cpu)
        if (topology_mode != TOPOLOGY_MODE_HW)
                goto out;
        cpu -= cpu % (smp_cpu_mtid + 1);
-       for (i = 0; i <= smp_cpu_mtid; i++) {
-               if (cpumask_test_cpu(cpu + i, &cpu_setup_mask))
-                       cpumask_set_cpu(cpu + i, &mask);
+       max_cpu = min(cpu + smp_cpu_mtid, nr_cpu_ids - 1);
+       for (; cpu <= max_cpu; cpu++) {
+               if (cpumask_test_cpu(cpu, &cpu_setup_mask))
+                       cpumask_set_cpu(cpu, &mask);
        }
 out:
        cpumask_copy(dst, &mask);
@@ -123,25 +124,26 @@ static void add_cpus_to_mask(struct topology_core *tl_core,
        unsigned int core;
 
        for_each_set_bit(core, &tl_core->mask, TOPOLOGY_CORE_BITS) {
-               unsigned int rcore;
-               int lcpu, i;
+               unsigned int max_cpu, rcore;
+               int cpu;
 
                rcore = TOPOLOGY_CORE_BITS - 1 - core + tl_core->origin;
-               lcpu = smp_find_processor_id(rcore << smp_cpu_mt_shift);
-               if (lcpu < 0)
+               cpu = smp_find_processor_id(rcore << smp_cpu_mt_shift);
+               if (cpu < 0)
                        continue;
-               for (i = 0; i <= smp_cpu_mtid; i++) {
-                       topo = &cpu_topology[lcpu + i];
+               max_cpu = min(cpu + smp_cpu_mtid, nr_cpu_ids - 1);
+               for (; cpu <= max_cpu; cpu++) {
+                       topo = &cpu_topology[cpu];
                        topo->drawer_id = drawer->id;
                        topo->book_id = book->id;
                        topo->socket_id = socket->id;
                        topo->core_id = rcore;
-                       topo->thread_id = lcpu + i;
+                       topo->thread_id = cpu;
                        topo->dedicated = tl_core->d;
-                       cpumask_set_cpu(lcpu + i, &drawer->mask);
-                       cpumask_set_cpu(lcpu + i, &book->mask);
-                       cpumask_set_cpu(lcpu + i, &socket->mask);
-                       smp_cpu_set_polarization(lcpu + i, tl_core->pp);
+                       cpumask_set_cpu(cpu, &drawer->mask);
+                       cpumask_set_cpu(cpu, &book->mask);
+                       cpumask_set_cpu(cpu, &socket->mask);
+                       smp_cpu_set_polarization(cpu, tl_core->pp);
                }
        }
 }
index dee6f66353b334c6b55de0097409f2ce11cb7a26..a461a950f0518d55fc5ad95175520c6b45e8efe4 100644 (file)
@@ -16,7 +16,8 @@ mconsole-objs := mconsole_kern.o mconsole_user.o
 hostaudio-objs := hostaudio_kern.o
 ubd-objs := ubd_kern.o ubd_user.o
 port-objs := port_kern.o port_user.o
-harddog-objs := harddog_kern.o harddog_user.o
+harddog-objs := harddog_kern.o
+harddog-builtin-$(CONFIG_UML_WATCHDOG) := harddog_user.o harddog_user_exp.o
 rtc-objs := rtc_kern.o rtc_user.o
 
 LDFLAGS_pcap.o = $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libpcap.a)
@@ -60,6 +61,7 @@ obj-$(CONFIG_PTY_CHAN) += pty.o
 obj-$(CONFIG_TTY_CHAN) += tty.o 
 obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
 obj-$(CONFIG_UML_WATCHDOG) += harddog.o
+obj-y += $(harddog-builtin-y) $(harddog-builtin-m)
 obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
 obj-$(CONFIG_UML_RANDOM) += random.o
 obj-$(CONFIG_VIRTIO_UML) += virtio_uml.o
diff --git a/arch/um/drivers/harddog.h b/arch/um/drivers/harddog.h
new file mode 100644 (file)
index 0000000..6d9ea60
--- /dev/null
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef UM_WATCHDOG_H
+#define UM_WATCHDOG_H
+
+int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock);
+void stop_watchdog(int in_fd, int out_fd);
+int ping_watchdog(int fd);
+
+#endif /* UM_WATCHDOG_H */
index e6d4f43deba82a77e20eaf15ea81639f0ddb37d1..60d1c6cab8a95197e2c14cc789ca5a8f9fa47496 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
 #include "mconsole.h"
+#include "harddog.h"
 
 MODULE_LICENSE("GPL");
 
@@ -60,8 +61,6 @@ static int harddog_out_fd = -1;
  *     Allow only one person to hold it open
  */
 
-extern int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock);
-
 static int harddog_open(struct inode *inode, struct file *file)
 {
        int err = -EBUSY;
@@ -92,8 +91,6 @@ err:
        return err;
 }
 
-extern void stop_watchdog(int in_fd, int out_fd);
-
 static int harddog_release(struct inode *inode, struct file *file)
 {
        /*
@@ -112,8 +109,6 @@ static int harddog_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-extern int ping_watchdog(int fd);
-
 static ssize_t harddog_write(struct file *file, const char __user *data, size_t len,
                             loff_t *ppos)
 {
index 070468d22e3943f4d047aa8917776ee7f87b43db..9ed89304975ed351b264d5c068b70fd0094f44b2 100644 (file)
@@ -7,6 +7,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <os.h>
+#include "harddog.h"
 
 struct dog_data {
        int stdin_fd;
diff --git a/arch/um/drivers/harddog_user_exp.c b/arch/um/drivers/harddog_user_exp.c
new file mode 100644 (file)
index 0000000..c74d4b8
--- /dev/null
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/export.h>
+#include "harddog.h"
+
+#if IS_MODULE(CONFIG_UML_WATCHDOG)
+EXPORT_SYMBOL(start_watchdog);
+EXPORT_SYMBOL(stop_watchdog);
+EXPORT_SYMBOL(ping_watchdog);
+#endif
index 7c1abc513f34621eff4d0ee72db6a6c3dbb291f5..9556dacd984154a2b6ede8808321b8c6c692f347 100644 (file)
        .octa 0x3F893781E95FE1576CDA64D2BA0CB204
 
 #ifdef CONFIG_AS_GFNI
-.section       .rodata.cst8, "aM", @progbits, 8
-.align 8
 /* AES affine: */
 #define tf_aff_const BV8(1, 1, 0, 0, 0, 1, 1, 0)
 .Ltf_aff_bitmatrix:
index d096b04bf80e80b2c9784cd5380dbe7677f45cd9..9d248703cbddcd6fb7623d22f4a408adee8d97d5 100644 (file)
@@ -1703,10 +1703,8 @@ int x86_pmu_handle_irq(struct pt_regs *regs)
 
                perf_sample_data_init(&data, 0, event->hw.last_period);
 
-               if (has_branch_stack(event)) {
-                       data.br_stack = &cpuc->lbr_stack;
-                       data.sample_flags |= PERF_SAMPLE_BRANCH_STACK;
-               }
+               if (has_branch_stack(event))
+                       perf_sample_save_brstack(&data, event, &cpuc->lbr_stack);
 
                if (perf_event_overflow(event, &data, regs))
                        x86_pmu_stop(event, 0);
index 070cc4ef267210b4dc7a490f43cad45d5d3ab5c7..89b9c1cebb613a89865909cfe7e322f93f5abe10 100644 (file)
@@ -4074,7 +4074,7 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr, void *data)
        if (x86_pmu.intel_cap.pebs_baseline) {
                arr[(*nr)++] = (struct perf_guest_switch_msr){
                        .msr = MSR_PEBS_DATA_CFG,
-                       .host = cpuc->pebs_data_cfg,
+                       .host = cpuc->active_pebs_data_cfg,
                        .guest = kvm_pmu->pebs_data_cfg,
                };
        }
index a2e566e53076ec83daa42f4cc91609ae11705cfa..df88576d6b2a54bbf00ffc5dd5c71cdca7213981 100644 (file)
@@ -1229,12 +1229,14 @@ pebs_update_state(bool needed_cb, struct cpu_hw_events *cpuc,
                  struct perf_event *event, bool add)
 {
        struct pmu *pmu = event->pmu;
+
        /*
         * Make sure we get updated with the first PEBS
         * event. It will trigger also during removal, but
         * that does not hurt:
         */
-       bool update = cpuc->n_pebs == 1;
+       if (cpuc->n_pebs == 1)
+               cpuc->pebs_data_cfg = PEBS_UPDATE_DS_SW;
 
        if (needed_cb != pebs_needs_sched_cb(cpuc)) {
                if (!needed_cb)
@@ -1242,7 +1244,7 @@ pebs_update_state(bool needed_cb, struct cpu_hw_events *cpuc,
                else
                        perf_sched_cb_dec(pmu);
 
-               update = true;
+               cpuc->pebs_data_cfg |= PEBS_UPDATE_DS_SW;
        }
 
        /*
@@ -1252,24 +1254,13 @@ pebs_update_state(bool needed_cb, struct cpu_hw_events *cpuc,
        if (x86_pmu.intel_cap.pebs_baseline && add) {
                u64 pebs_data_cfg;
 
-               /* Clear pebs_data_cfg and pebs_record_size for first PEBS. */
-               if (cpuc->n_pebs == 1) {
-                       cpuc->pebs_data_cfg = 0;
-                       cpuc->pebs_record_size = sizeof(struct pebs_basic);
-               }
-
                pebs_data_cfg = pebs_update_adaptive_cfg(event);
-
-               /* Update pebs_record_size if new event requires more data. */
-               if (pebs_data_cfg & ~cpuc->pebs_data_cfg) {
-                       cpuc->pebs_data_cfg |= pebs_data_cfg;
-                       adaptive_pebs_record_size_update();
-                       update = true;
-               }
+               /*
+                * Be sure to update the thresholds when we change the record.
+                */
+               if (pebs_data_cfg & ~cpuc->pebs_data_cfg)
+                       cpuc->pebs_data_cfg |= pebs_data_cfg | PEBS_UPDATE_DS_SW;
        }
-
-       if (update)
-               pebs_update_threshold(cpuc);
 }
 
 void intel_pmu_pebs_add(struct perf_event *event)
@@ -1326,9 +1317,17 @@ static void intel_pmu_pebs_via_pt_enable(struct perf_event *event)
        wrmsrl(base + idx, value);
 }
 
+static inline void intel_pmu_drain_large_pebs(struct cpu_hw_events *cpuc)
+{
+       if (cpuc->n_pebs == cpuc->n_large_pebs &&
+           cpuc->n_pebs != cpuc->n_pebs_via_pt)
+               intel_pmu_drain_pebs_buffer();
+}
+
 void intel_pmu_pebs_enable(struct perf_event *event)
 {
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       u64 pebs_data_cfg = cpuc->pebs_data_cfg & ~PEBS_UPDATE_DS_SW;
        struct hw_perf_event *hwc = &event->hw;
        struct debug_store *ds = cpuc->ds;
        unsigned int idx = hwc->idx;
@@ -1344,11 +1343,22 @@ void intel_pmu_pebs_enable(struct perf_event *event)
 
        if (x86_pmu.intel_cap.pebs_baseline) {
                hwc->config |= ICL_EVENTSEL_ADAPTIVE;
-               if (cpuc->pebs_data_cfg != cpuc->active_pebs_data_cfg) {
-                       wrmsrl(MSR_PEBS_DATA_CFG, cpuc->pebs_data_cfg);
-                       cpuc->active_pebs_data_cfg = cpuc->pebs_data_cfg;
+               if (pebs_data_cfg != cpuc->active_pebs_data_cfg) {
+                       /*
+                        * drain_pebs() assumes uniform record size;
+                        * hence we need to drain when changing said
+                        * size.
+                        */
+                       intel_pmu_drain_large_pebs(cpuc);
+                       adaptive_pebs_record_size_update();
+                       wrmsrl(MSR_PEBS_DATA_CFG, pebs_data_cfg);
+                       cpuc->active_pebs_data_cfg = pebs_data_cfg;
                }
        }
+       if (cpuc->pebs_data_cfg & PEBS_UPDATE_DS_SW) {
+               cpuc->pebs_data_cfg = pebs_data_cfg;
+               pebs_update_threshold(cpuc);
+       }
 
        if (idx >= INTEL_PMC_IDX_FIXED) {
                if (x86_pmu.intel_cap.pebs_format < 5)
@@ -1391,9 +1401,7 @@ void intel_pmu_pebs_disable(struct perf_event *event)
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
 
-       if (cpuc->n_pebs == cpuc->n_large_pebs &&
-           cpuc->n_pebs != cpuc->n_pebs_via_pt)
-               intel_pmu_drain_pebs_buffer();
+       intel_pmu_drain_large_pebs(cpuc);
 
        cpuc->pebs_enabled &= ~(1ULL << hwc->idx);
 
index fa9b209a11fabce2f57d585e9e08219182d947dd..d49e90dc04a4ccac259485982384f994c728c122 100644 (file)
@@ -6150,6 +6150,7 @@ static struct intel_uncore_type spr_uncore_mdf = {
 };
 
 #define UNCORE_SPR_NUM_UNCORE_TYPES            12
+#define UNCORE_SPR_CHA                         0
 #define UNCORE_SPR_IIO                         1
 #define UNCORE_SPR_IMC                         6
 #define UNCORE_SPR_UPI                         8
@@ -6460,12 +6461,22 @@ static int uncore_type_max_boxes(struct intel_uncore_type **types,
        return max + 1;
 }
 
+#define SPR_MSR_UNC_CBO_CONFIG         0x2FFE
+
 void spr_uncore_cpu_init(void)
 {
+       struct intel_uncore_type *type;
+       u64 num_cbo;
+
        uncore_msr_uncores = uncore_get_uncores(UNCORE_ACCESS_MSR,
                                                UNCORE_SPR_MSR_EXTRA_UNCORES,
                                                spr_msr_uncores);
 
+       type = uncore_find_type_by_id(uncore_msr_uncores, UNCORE_SPR_CHA);
+       if (type) {
+               rdmsrl(SPR_MSR_UNC_CBO_CONFIG, num_cbo);
+               type->num_boxes = num_cbo;
+       }
        spr_uncore_iio_free_running.num_boxes = uncore_type_max_boxes(uncore_msr_uncores, UNCORE_SPR_IIO);
 }
 
index c2d6cd78ed0c2986181217a184e8d52f7e72c534..78fcde7b1f0700ee1e12cba4871edf7d3efed5f1 100644 (file)
@@ -39,7 +39,7 @@ extern void fpu_flush_thread(void);
 static inline void switch_fpu_prepare(struct fpu *old_fpu, int cpu)
 {
        if (cpu_feature_enabled(X86_FEATURE_FPU) &&
-           !(current->flags & (PF_KTHREAD | PF_IO_WORKER))) {
+           !(current->flags & (PF_KTHREAD | PF_USER_WORKER))) {
                save_fpregs_to_fpstate(old_fpu);
                /*
                 * The save operation preserved register state, so the
index 8fc15ed5e60bb627db5226bf6e966b9294ae44ab..abf09882f58b67c20a622a98ced522961b818931 100644 (file)
 #define PEBS_DATACFG_LBRS      BIT_ULL(3)
 #define PEBS_DATACFG_LBR_SHIFT 24
 
+/* Steal the highest bit of pebs_data_cfg for SW usage */
+#define PEBS_UPDATE_DS_SW      BIT_ULL(63)
+
 /*
  * Intel "Architectural Performance Monitoring" CPUID
  * detection/enumeration details:
index 498dc600bd5c8ef55a4de29ecb87396d4d192859..0d02c4aafa6f49b2e981ac975610095844a815d3 100644 (file)
@@ -13,7 +13,9 @@
 
 
 #include <linux/bitops.h>
+#include <linux/bug.h>
 #include <linux/types.h>
+
 #include <uapi/asm/vmx.h>
 #include <asm/vmxfeatures.h>
 
index dd61752f4c966bf0db57abb92472f8c4ae4c0c82..4070a01c11b72af04f429dee966c495275a7dfb6 100644 (file)
@@ -17,6 +17,7 @@ CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_early_printk.o = -pg
 CFLAGS_REMOVE_head64.o = -pg
 CFLAGS_REMOVE_sev.o = -pg
+CFLAGS_REMOVE_rethook.o = -pg
 endif
 
 KASAN_SANITIZE_head$(BITS).o                           := n
index 4266b64631a46af574c7592fa8e17e4d8fda0f7a..7e331e8f36929de7a4550a7b90127252f9768f86 100644 (file)
@@ -36,6 +36,7 @@
 #define PCI_DEVICE_ID_AMD_19H_M50H_DF_F4 0x166e
 #define PCI_DEVICE_ID_AMD_19H_M60H_DF_F4 0x14e4
 #define PCI_DEVICE_ID_AMD_19H_M70H_DF_F4 0x14f4
+#define PCI_DEVICE_ID_AMD_19H_M78H_DF_F4 0x12fc
 
 /* Protect the PCI config register pairs used for SMN. */
 static DEFINE_MUTEX(smn_mutex);
@@ -79,6 +80,7 @@ static const struct pci_device_id amd_nb_misc_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M50H_DF_F3) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M60H_DF_F3) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M70H_DF_F3) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M78H_DF_F3) },
        {}
 };
 
index 5e868b62a7c4e4c466fadd8f858e004a9ba76e27..0270925fe013bcf9bbe76e589c93a35a6ddbfde5 100644 (file)
@@ -79,7 +79,7 @@ int detect_extended_topology_early(struct cpuinfo_x86 *c)
         * initial apic id, which also represents 32-bit extended x2apic id.
         */
        c->initial_apicid = edx;
-       smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
+       smp_num_siblings = max_t(int, smp_num_siblings, LEVEL_MAX_SIBLINGS(ebx));
 #endif
        return 0;
 }
@@ -109,7 +109,8 @@ int detect_extended_topology(struct cpuinfo_x86 *c)
         */
        cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
        c->initial_apicid = edx;
-       core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
+       core_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
+       smp_num_siblings = max_t(int, smp_num_siblings, LEVEL_MAX_SIBLINGS(ebx));
        core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
        die_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
        pkg_mask_width = die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
index 0bf6779187dda158a8deba21e14215d2b0cbddb7..f18ca44c904b747e68a3fdf0f7926a7025da71b7 100644 (file)
@@ -195,7 +195,6 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
        printk("%sCall Trace:\n", log_lvl);
 
        unwind_start(&state, task, regs, stack);
-       stack = stack ? : get_stack_pointer(task, regs);
        regs = unwind_get_entry_regs(&state, &partial);
 
        /*
@@ -214,9 +213,13 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
         * - hardirq stack
         * - entry stack
         */
-       for ( ; stack; stack = PTR_ALIGN(stack_info.next_sp, sizeof(long))) {
+       for (stack = stack ?: get_stack_pointer(task, regs);
+            stack;
+            stack = stack_info.next_sp) {
                const char *stack_name;
 
+               stack = PTR_ALIGN(stack, sizeof(long));
+
                if (get_stack_info(stack, task, &stack_info, &visit_mask)) {
                        /*
                         * We weren't on a valid stack.  It's possible that
index 9fcfa5c4dad799c99cafff1a0b6c4b9ad958af74..af5cbdd9bd29a2b496d349a439071b75b88f8d61 100644 (file)
@@ -57,7 +57,7 @@ static inline void fpregs_restore_userregs(void)
        struct fpu *fpu = &current->thread.fpu;
        int cpu = smp_processor_id();
 
-       if (WARN_ON_ONCE(current->flags & (PF_KTHREAD | PF_IO_WORKER)))
+       if (WARN_ON_ONCE(current->flags & (PF_KTHREAD | PF_USER_WORKER)))
                return;
 
        if (!fpregs_state_valid(fpu, cpu)) {
index caf33486dc5ee5b39bc4bfb1032d233cc1f0e09d..1015af1ae562bff33925f2e3266517d8c365296c 100644 (file)
@@ -426,7 +426,7 @@ void kernel_fpu_begin_mask(unsigned int kfpu_mask)
 
        this_cpu_write(in_kernel_fpu, true);
 
-       if (!(current->flags & (PF_KTHREAD | PF_IO_WORKER)) &&
+       if (!(current->flags & (PF_KTHREAD | PF_USER_WORKER)) &&
            !test_thread_flag(TIF_NEED_FPU_LOAD)) {
                set_thread_flag(TIF_NEED_FPU_LOAD);
                save_fpregs_to_fpstate(&current->thread.fpu);
index 123bf8b97a4b21098a8271320f711cecf2eae5ec..0c9660a07b233ff404147fa6acda76668241f7ee 100644 (file)
@@ -253,7 +253,6 @@ static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_e
                                       int nent)
 {
        struct kvm_cpuid_entry2 *best;
-       u64 guest_supported_xcr0 = cpuid_get_supported_xcr0(entries, nent);
 
        best = cpuid_entry2_find(entries, nent, 1, KVM_CPUID_INDEX_NOT_SIGNIFICANT);
        if (best) {
@@ -292,21 +291,6 @@ static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_e
                                           vcpu->arch.ia32_misc_enable_msr &
                                           MSR_IA32_MISC_ENABLE_MWAIT);
        }
-
-       /*
-        * Bits 127:0 of the allowed SECS.ATTRIBUTES (CPUID.0x12.0x1) enumerate
-        * the supported XSAVE Feature Request Mask (XFRM), i.e. the enclave's
-        * requested XCR0 value.  The enclave's XFRM must be a subset of XCRO
-        * at the time of EENTER, thus adjust the allowed XFRM by the guest's
-        * supported XCR0.  Similar to XCR0 handling, FP and SSE are forced to
-        * '1' even on CPUs that don't support XSAVE.
-        */
-       best = cpuid_entry2_find(entries, nent, 0x12, 0x1);
-       if (best) {
-               best->ecx &= guest_supported_xcr0 & 0xffffffff;
-               best->edx &= guest_supported_xcr0 >> 32;
-               best->ecx |= XFEATURE_MASK_FPSSE;
-       }
 }
 
 void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu)
index e542cf285b51842099332f594f4836836bda56d4..3c300a196bdf945ea7354cc370b4cd0aad515c61 100644 (file)
@@ -228,6 +228,23 @@ static int kvm_recalculate_phys_map(struct kvm_apic_map *new,
        u32 xapic_id = kvm_xapic_id(apic);
        u32 physical_id;
 
+       /*
+        * For simplicity, KVM always allocates enough space for all possible
+        * xAPIC IDs.  Yell, but don't kill the VM, as KVM can continue on
+        * without the optimized map.
+        */
+       if (WARN_ON_ONCE(xapic_id > new->max_apic_id))
+               return -EINVAL;
+
+       /*
+        * Bail if a vCPU was added and/or enabled its APIC between allocating
+        * the map and doing the actual calculations for the map.  Note, KVM
+        * hardcodes the x2APIC ID to vcpu_id, i.e. there's no TOCTOU bug if
+        * the compiler decides to reload x2apic_id after this check.
+        */
+       if (x2apic_id > new->max_apic_id)
+               return -E2BIG;
+
        /*
         * Deliberately truncate the vCPU ID when detecting a mismatched APIC
         * ID to avoid false positives if the vCPU ID, i.e. x2APIC ID, is a
@@ -253,8 +270,7 @@ static int kvm_recalculate_phys_map(struct kvm_apic_map *new,
         */
        if (vcpu->kvm->arch.x2apic_format) {
                /* See also kvm_apic_match_physical_addr(). */
-               if ((apic_x2apic_mode(apic) || x2apic_id > 0xff) &&
-                       x2apic_id <= new->max_apic_id)
+               if (apic_x2apic_mode(apic) || x2apic_id > 0xff)
                        new->phys_map[x2apic_id] = apic;
 
                if (!apic_x2apic_mode(apic) && !new->phys_map[xapic_id])
index c8961f45e3b1c1c01108f2830da0aad9624601b2..6eaa3d6994aebea7ecc344626adce9d0d062a31b 100644 (file)
@@ -7091,7 +7091,10 @@ static void kvm_recover_nx_huge_pages(struct kvm *kvm)
                 */
                slot = NULL;
                if (atomic_read(&kvm->nr_memslots_dirty_logging)) {
-                       slot = gfn_to_memslot(kvm, sp->gfn);
+                       struct kvm_memslots *slots;
+
+                       slots = kvm_memslots_for_spte_role(kvm, sp->role);
+                       slot = __gfn_to_memslot(slots, sp->gfn);
                        WARN_ON_ONCE(!slot);
                }
 
index ca32389f3c36bae9d4c2d29c7d810fde12bb82ff..54089f990c8f83292eecede362b19269c8756900 100644 (file)
@@ -3510,7 +3510,7 @@ static bool svm_is_vnmi_pending(struct kvm_vcpu *vcpu)
        if (!is_vnmi_enabled(svm))
                return false;
 
-       return !!(svm->vmcb->control.int_ctl & V_NMI_BLOCKING_MASK);
+       return !!(svm->vmcb->control.int_ctl & V_NMI_PENDING_MASK);
 }
 
 static bool svm_set_vnmi_pending(struct kvm_vcpu *vcpu)
index 0574030b071fbfea9ed7943da13c5d32942b4b14..2261b684a7d4475ab78107114aa5cb8dd5b2179e 100644 (file)
@@ -170,12 +170,19 @@ static int __handle_encls_ecreate(struct kvm_vcpu *vcpu,
                return 1;
        }
 
-       /* Enforce CPUID restrictions on MISCSELECT, ATTRIBUTES and XFRM. */
+       /*
+        * Enforce CPUID restrictions on MISCSELECT, ATTRIBUTES and XFRM.  Note
+        * that the allowed XFRM (XFeature Request Mask) isn't strictly bound
+        * by the supported XCR0.  FP+SSE *must* be set in XFRM, even if XSAVE
+        * is unsupported, i.e. even if XCR0 itself is completely unsupported.
+        */
        if ((u32)miscselect & ~sgx_12_0->ebx ||
            (u32)attributes & ~sgx_12_1->eax ||
            (u32)(attributes >> 32) & ~sgx_12_1->ebx ||
            (u32)xfrm & ~sgx_12_1->ecx ||
-           (u32)(xfrm >> 32) & ~sgx_12_1->edx) {
+           (u32)(xfrm >> 32) & ~sgx_12_1->edx ||
+           xfrm & ~(vcpu->arch.guest_supported_xcr0 | XFEATURE_MASK_FPSSE) ||
+           (xfrm & XFEATURE_MASK_FPSSE) != XFEATURE_MASK_FPSSE) {
                kvm_inject_gp(vcpu, 0);
                return 1;
        }
index ceb7c5e9cf9e9235a63cee5f909ba2a0ae41d5b3..04b57a336b34e5fc5224c47e5e8f23f794e98729 100644 (file)
@@ -1446,7 +1446,7 @@ static const u32 msrs_to_save_base[] = {
 #endif
        MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA,
        MSR_IA32_FEAT_CTL, MSR_IA32_BNDCFGS, MSR_TSC_AUX,
-       MSR_IA32_SPEC_CTRL,
+       MSR_IA32_SPEC_CTRL, MSR_IA32_TSX_CTRL,
        MSR_IA32_RTIT_CTL, MSR_IA32_RTIT_STATUS, MSR_IA32_RTIT_CR3_MATCH,
        MSR_IA32_RTIT_OUTPUT_BASE, MSR_IA32_RTIT_OUTPUT_MASK,
        MSR_IA32_RTIT_ADDR0_A, MSR_IA32_RTIT_ADDR0_B,
@@ -7155,6 +7155,10 @@ static void kvm_probe_msr_to_save(u32 msr_index)
                if (!kvm_cpu_cap_has(X86_FEATURE_XFD))
                        return;
                break;
+       case MSR_IA32_TSX_CTRL:
+               if (!(kvm_get_arch_capabilities() & ARCH_CAP_TSX_CTRL_MSR))
+                       return;
+               break;
        default:
                break;
        }
@@ -10754,6 +10758,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
                        exit_fastpath = EXIT_FASTPATH_EXIT_HANDLED;
                        break;
                }
+
+               /* Note, VM-Exits that go down the "slow" path are accounted below. */
+               ++vcpu->stat.exits;
        }
 
        /*
index 4fc5c2de2de467c689ddf91eb1684eeb00aeb9db..01c5de4c279b8fe8cf0fcd914f4cb4ec31945bc8 100644 (file)
@@ -7,6 +7,8 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/cpufeatures.h>
+#include <asm/alternative.h>
 #include <asm/asm.h>
 #include <asm/export.h>
 
@@ -29,7 +31,7 @@
  */
 SYM_FUNC_START(rep_movs_alternative)
        cmpq $64,%rcx
-       jae .Lunrolled
+       jae .Llarge
 
        cmp $8,%ecx
        jae .Lword
@@ -65,6 +67,12 @@ SYM_FUNC_START(rep_movs_alternative)
        _ASM_EXTABLE_UA( 2b, .Lcopy_user_tail)
        _ASM_EXTABLE_UA( 3b, .Lcopy_user_tail)
 
+.Llarge:
+0:     ALTERNATIVE "jmp .Lunrolled", "rep movsb", X86_FEATURE_ERMS
+1:     RET
+
+        _ASM_EXTABLE_UA( 0b, 1b)
+
        .p2align 4
 .Lunrolled:
 10:    movq (%rsi),%r8
index 27ef53fab6bd7a501211f59ffe42f880bbd48096..b3b1e376dce86a15ea56a8445867d9ccb5db5c87 100644 (file)
@@ -144,8 +144,8 @@ SYM_CODE_END(__x86_indirect_jump_thunk_array)
  */
        .align 64
        .skip 63, 0xcc
-SYM_FUNC_START_NOALIGN(zen_untrain_ret);
-
+SYM_START(zen_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE)
+       ANNOTATE_NOENDBR
        /*
         * As executed from zen_untrain_ret, this is:
         *
index 3cdac0f0055deef186eb5a84d751f0ecb7058b9d..8192452d1d2d3569dddfb109e74e6b83d8b5570d 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/sched/task.h>
 
 #include <asm/set_memory.h>
+#include <asm/cpu_device_id.h>
 #include <asm/e820/api.h>
 #include <asm/init.h>
 #include <asm/page.h>
@@ -261,6 +262,24 @@ static void __init probe_page_size_mask(void)
        }
 }
 
+#define INTEL_MATCH(_model) { .vendor  = X86_VENDOR_INTEL,     \
+                             .family  = 6,                     \
+                             .model = _model,                  \
+                           }
+/*
+ * INVLPG may not properly flush Global entries
+ * on these CPUs when PCIDs are enabled.
+ */
+static const struct x86_cpu_id invlpg_miss_ids[] = {
+       INTEL_MATCH(INTEL_FAM6_ALDERLAKE   ),
+       INTEL_MATCH(INTEL_FAM6_ALDERLAKE_L ),
+       INTEL_MATCH(INTEL_FAM6_ALDERLAKE_N ),
+       INTEL_MATCH(INTEL_FAM6_RAPTORLAKE  ),
+       INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_P),
+       INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_S),
+       {}
+};
+
 static void setup_pcid(void)
 {
        if (!IS_ENABLED(CONFIG_X86_64))
@@ -269,6 +288,12 @@ static void setup_pcid(void)
        if (!boot_cpu_has(X86_FEATURE_PCID))
                return;
 
+       if (x86_match_cpu(invlpg_miss_ids)) {
+               pr_info("Incomplete global flushes, disabling PCID");
+               setup_clear_cpu_cap(X86_FEATURE_PCID);
+               return;
+       }
+
        if (boot_cpu_has(X86_FEATURE_PGE)) {
                /*
                 * This can't be cr4_set_bits_and_update_boot() -- the
index 8babce71915fe514aa24cfdb25f36c98ddc90369..014c508e914d9816bb062621554c65231468870a 100644 (file)
@@ -198,7 +198,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                i++;
        }
        kfree(v);
-       return 0;
+       return msi_device_populate_sysfs(&dev->dev);
 
 error:
        if (ret == -ENOSYS)
@@ -254,7 +254,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                dev_dbg(&dev->dev,
                        "xen: msi --> pirq=%d --> irq=%d\n", pirq, irq);
        }
-       return 0;
+       return msi_device_populate_sysfs(&dev->dev);
 
 error:
        dev_err(&dev->dev, "Failed to create MSI%s! ret=%d!\n",
@@ -346,7 +346,7 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                if (ret < 0)
                        goto out;
        }
-       ret = 0;
+       ret = msi_device_populate_sysfs(&dev->dev);
 out:
        return ret;
 }
@@ -394,6 +394,8 @@ static void xen_teardown_msi_irqs(struct pci_dev *dev)
                        xen_destroy_irq(msidesc->irq + i);
                msidesc->irq = 0;
        }
+
+       msi_device_destroy_sysfs(&dev->dev);
 }
 
 static void xen_pv_teardown_msi_irqs(struct pci_dev *dev)
index 876d5df157ed986ff3d919aba15fca177806d56e..5c01d7e70d90da4a0f495273180005cf235f4a7c 100644 (file)
@@ -343,7 +343,19 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
        struct rt_sigframe *frame;
        int err = 0, sig = ksig->sig;
        unsigned long sp, ra, tp, ps;
+       unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
+       unsigned long handler_fdpic_GOT = 0;
        unsigned int base;
+       bool fdpic = IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC) &&
+               (current->personality & FDPIC_FUNCPTRS);
+
+       if (fdpic) {
+               unsigned long __user *fdpic_func_desc =
+                       (unsigned long __user *)handler;
+               if (__get_user(handler, &fdpic_func_desc[0]) ||
+                   __get_user(handler_fdpic_GOT, &fdpic_func_desc[1]))
+                       return -EFAULT;
+       }
 
        sp = regs->areg[1];
 
@@ -373,20 +385,26 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
        if (ksig->ka.sa.sa_flags & SA_RESTORER) {
-               ra = (unsigned long)ksig->ka.sa.sa_restorer;
+               if (fdpic) {
+                       unsigned long __user *fdpic_func_desc =
+                               (unsigned long __user *)ksig->ka.sa.sa_restorer;
+
+                       err |= __get_user(ra, fdpic_func_desc);
+               } else {
+                       ra = (unsigned long)ksig->ka.sa.sa_restorer;
+               }
        } else {
 
                /* Create sys_rt_sigreturn syscall in stack frame */
 
                err |= gen_return_code(frame->retcode);
-
-               if (err) {
-                       return -EFAULT;
-               }
                ra = (unsigned long) frame->retcode;
        }
 
-       /* 
+       if (err)
+               return -EFAULT;
+
+       /*
         * Create signal handler execution context.
         * Return context not modified until this point.
         */
@@ -394,8 +412,7 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
        /* Set up registers for signal handler; preserve the threadptr */
        tp = regs->threadptr;
        ps = regs->ps;
-       start_thread(regs, (unsigned long) ksig->ka.sa.sa_handler,
-                    (unsigned long) frame);
+       start_thread(regs, handler, (unsigned long)frame);
 
        /* Set up a stack frame for a call4 if userspace uses windowed ABI */
        if (ps & PS_WOE_MASK) {
@@ -413,6 +430,8 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
        regs->areg[base + 4] = (unsigned long) &frame->uc;
        regs->threadptr = tp;
        regs->ps = ps;
+       if (fdpic)
+               regs->areg[base + 11] = handler_fdpic_GOT;
 
        pr_debug("SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08lx\n",
                 current->comm, current->pid, sig, frame, regs->pc);
index 2a31b1ab0c9f20ed800b3f2490afe5e33b9bd579..17a7ef86fd0dd0c67c4ef0d25576ac1ce106620f 100644 (file)
@@ -56,6 +56,8 @@ EXPORT_SYMBOL(empty_zero_page);
  */
 extern long long __ashrdi3(long long, int);
 extern long long __ashldi3(long long, int);
+extern long long __bswapdi2(long long);
+extern int __bswapsi2(int);
 extern long long __lshrdi3(long long, int);
 extern int __divsi3(int, int);
 extern int __modsi3(int, int);
@@ -66,6 +68,8 @@ extern unsigned long long __umulsidi3(unsigned int, unsigned int);
 
 EXPORT_SYMBOL(__ashldi3);
 EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__bswapdi2);
+EXPORT_SYMBOL(__bswapsi2);
 EXPORT_SYMBOL(__lshrdi3);
 EXPORT_SYMBOL(__divsi3);
 EXPORT_SYMBOL(__modsi3);
index 7ecef0519a27caac48855896aa6042959f315c56..c9c2614188f74c788a566a1c58b24f3b68721163 100644 (file)
@@ -4,7 +4,7 @@
 #
 
 lib-y  += memcopy.o memset.o checksum.o \
-          ashldi3.o ashrdi3.o lshrdi3.o \
+          ashldi3.o ashrdi3.o bswapdi2.o bswapsi2.o lshrdi3.o \
           divsi3.o udivsi3.o modsi3.o umodsi3.o mulsi3.o umulsidi3.o \
           usercopy.o strncpy_user.o strnlen_user.o
 lib-$(CONFIG_PCI) += pci-auto.o
diff --git a/arch/xtensa/lib/bswapdi2.S b/arch/xtensa/lib/bswapdi2.S
new file mode 100644 (file)
index 0000000..d8e52e0
--- /dev/null
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */
+#include <linux/linkage.h>
+#include <asm/asmmacro.h>
+#include <asm/core.h>
+
+ENTRY(__bswapdi2)
+
+       abi_entry_default
+       ssai    8
+       srli    a4, a2, 16
+       src     a4, a4, a2
+       src     a4, a4, a4
+       src     a4, a2, a4
+       srli    a2, a3, 16
+       src     a2, a2, a3
+       src     a2, a2, a2
+       src     a2, a3, a2
+       mov     a3, a4
+       abi_ret_default
+
+ENDPROC(__bswapdi2)
diff --git a/arch/xtensa/lib/bswapsi2.S b/arch/xtensa/lib/bswapsi2.S
new file mode 100644 (file)
index 0000000..9c1de13
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */
+#include <linux/linkage.h>
+#include <asm/asmmacro.h>
+#include <asm/core.h>
+
+ENTRY(__bswapsi2)
+
+       abi_entry_default
+       ssai    8
+       srli    a3, a2, 16
+       src     a3, a3, a2
+       src     a3, a3, a3
+       src     a2, a2, a3
+       abi_ret_default
+
+ENDPROC(__bswapsi2)
index 00c74330fa92c221422a629361607068a65eda99..1da77e7d62894651d3e307dbd1be1930983baad8 100644 (file)
@@ -520,7 +520,7 @@ static inline int bio_check_eod(struct bio *bio)
        sector_t maxsector = bdev_nr_sectors(bio->bi_bdev);
        unsigned int nr_sectors = bio_sectors(bio);
 
-       if (nr_sectors && maxsector &&
+       if (nr_sectors &&
            (nr_sectors > maxsector ||
             bio->bi_iter.bi_sector > maxsector - nr_sectors)) {
                pr_info_ratelimited("%s: attempt to access beyond end of device\n"
index 04c55f1c492eb144b332139478b5cc390dbbf075..46eed2e627c363a4ab6a3797b538380be6a45ef6 100644 (file)
@@ -248,7 +248,7 @@ static struct bio *blk_rq_map_bio_alloc(struct request *rq,
 {
        struct bio *bio;
 
-       if (rq->cmd_flags & REQ_ALLOC_CACHE) {
+       if (rq->cmd_flags & REQ_ALLOC_CACHE && (nr_vecs <= BIO_INLINE_VECS)) {
                bio = bio_alloc_bioset(NULL, nr_vecs, rq->cmd_flags, gfp_mask,
                                        &fs_bio_set);
                if (!bio)
index d6af9d431dc631989dce6709971d1fc042e89dc1..dfd81cab57888b33a39b7b8b8e7d8d1c3bae0506 100644 (file)
@@ -39,16 +39,20 @@ void __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx)
 {
        unsigned int users;
 
+       /*
+        * calling test_bit() prior to test_and_set_bit() is intentional,
+        * it avoids dirtying the cacheline if the queue is already active.
+        */
        if (blk_mq_is_shared_tags(hctx->flags)) {
                struct request_queue *q = hctx->queue;
 
-               if (test_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags))
+               if (test_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags) ||
+                   test_and_set_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags))
                        return;
-               set_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags);
        } else {
-               if (test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state))
+               if (test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state) ||
+                   test_and_set_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state))
                        return;
-               set_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state);
        }
 
        users = atomic_inc_return(&hctx->tags->active_queues);
index 896b4654ab00fa700146678f2a0c1c4371f2ed7b..4dd59059b788eb3b8b45cc555716eec11bfcd995 100644 (file)
@@ -915,6 +915,7 @@ static bool disk_has_partitions(struct gendisk *disk)
 void disk_set_zoned(struct gendisk *disk, enum blk_zoned_model model)
 {
        struct request_queue *q = disk->queue;
+       unsigned int old_model = q->limits.zoned;
 
        switch (model) {
        case BLK_ZONED_HM:
@@ -952,7 +953,7 @@ void disk_set_zoned(struct gendisk *disk, enum blk_zoned_model model)
                 */
                blk_queue_zone_write_granularity(q,
                                                queue_logical_block_size(q));
-       } else {
+       } else if (old_model != BLK_ZONED_NONE) {
                disk_clear_zone_settings(disk);
        }
 }
index e49a4868453276744e02561c6bfef1dfe68aa2c2..9ec2a2f1eda3882b8d174b90c2e5f14ae5d07679 100644 (file)
@@ -730,14 +730,16 @@ void wbt_enable_default(struct gendisk *disk)
 {
        struct request_queue *q = disk->queue;
        struct rq_qos *rqos;
-       bool disable_flag = q->elevator &&
-                   test_bit(ELEVATOR_FLAG_DISABLE_WBT, &q->elevator->flags);
+       bool enable = IS_ENABLED(CONFIG_BLK_WBT_MQ);
+
+       if (q->elevator &&
+           test_bit(ELEVATOR_FLAG_DISABLE_WBT, &q->elevator->flags))
+               enable = false;
 
        /* Throttling already enabled? */
        rqos = wbt_rq_qos(q);
        if (rqos) {
-               if (!disable_flag &&
-                   RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT)
+               if (enable && RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT)
                        RQWB(rqos)->enable_state = WBT_STATE_ON_DEFAULT;
                return;
        }
@@ -746,7 +748,7 @@ void wbt_enable_default(struct gendisk *disk)
        if (!blk_queue_registered(q))
                return;
 
-       if (queue_is_mq(q) && !disable_flag)
+       if (queue_is_mq(q) && enable)
                wbt_init(disk);
 }
 EXPORT_SYMBOL_GPL(wbt_enable_default);
index d2e6be4e3d1c7da029d0a38bd18cf9b069f901e2..58d0aebc7313a838d4d895fd73f7c383290d75da 100644 (file)
@@ -678,6 +678,16 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start,
        return error;
 }
 
+static int blkdev_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct inode *bd_inode = bdev_file_inode(file);
+
+       if (bdev_read_only(I_BDEV(bd_inode)))
+               return generic_file_readonly_mmap(file, vma);
+
+       return generic_file_mmap(file, vma);
+}
+
 const struct file_operations def_blk_fops = {
        .open           = blkdev_open,
        .release        = blkdev_close,
@@ -685,7 +695,7 @@ const struct file_operations def_blk_fops = {
        .read_iter      = blkdev_read_iter,
        .write_iter     = blkdev_write_iter,
        .iopoll         = iocb_bio_iopoll,
-       .mmap           = generic_file_mmap,
+       .mmap           = blkdev_mmap,
        .fsync          = blkdev_fsync,
        .unlocked_ioctl = blkdev_ioctl,
 #ifdef CONFIG_COMPAT
index 9f216eb6f76ed80eb0fa3706e83e291898374782..5c57f7b4494e482f46d920e34f265ae1cac0c1ba 100644 (file)
@@ -997,14 +997,34 @@ static void *msg_xfer(struct qaic_device *qdev, struct wrapper_list *wrappers, u
        struct xfer_queue_elem elem;
        struct wire_msg *out_buf;
        struct wrapper_msg *w;
+       long ret = -EAGAIN;
+       int xfer_count = 0;
        int retry_count;
-       long ret;
 
        if (qdev->in_reset) {
                mutex_unlock(&qdev->cntl_mutex);
                return ERR_PTR(-ENODEV);
        }
 
+       /* Attempt to avoid a partial commit of a message */
+       list_for_each_entry(w, &wrappers->list, list)
+               xfer_count++;
+
+       for (retry_count = 0; retry_count < QAIC_MHI_RETRY_MAX; retry_count++) {
+               if (xfer_count <= mhi_get_free_desc_count(qdev->cntl_ch, DMA_TO_DEVICE)) {
+                       ret = 0;
+                       break;
+               }
+               msleep_interruptible(QAIC_MHI_RETRY_WAIT_MS);
+               if (signal_pending(current))
+                       break;
+       }
+
+       if (ret) {
+               mutex_unlock(&qdev->cntl_mutex);
+               return ERR_PTR(ret);
+       }
+
        elem.seq_num = seq_num;
        elem.buf = NULL;
        init_completion(&elem.xfer_done);
@@ -1038,16 +1058,9 @@ static void *msg_xfer(struct qaic_device *qdev, struct wrapper_list *wrappers, u
        list_for_each_entry(w, &wrappers->list, list) {
                kref_get(&w->ref_count);
                retry_count = 0;
-retry:
                ret = mhi_queue_buf(qdev->cntl_ch, DMA_TO_DEVICE, &w->msg, w->len,
                                    list_is_last(&w->list, &wrappers->list) ? MHI_EOT : MHI_CHAIN);
                if (ret) {
-                       if (ret == -EAGAIN && retry_count++ < QAIC_MHI_RETRY_MAX) {
-                               msleep_interruptible(QAIC_MHI_RETRY_WAIT_MS);
-                               if (!signal_pending(current))
-                                       goto retry;
-                       }
-
                        qdev->cntl_lost_buf = true;
                        kref_put(&w->ref_count, free_wrapper);
                        mutex_unlock(&qdev->cntl_mutex);
@@ -1249,7 +1262,7 @@ dma_cont_failed:
 
 int qaic_manage_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       struct qaic_manage_msg *user_msg;
+       struct qaic_manage_msg *user_msg = data;
        struct qaic_device *qdev;
        struct manage_msg *msg;
        struct qaic_user *usr;
@@ -1258,6 +1271,9 @@ int qaic_manage_ioctl(struct drm_device *dev, void *data, struct drm_file *file_
        int usr_rcu_id;
        int ret;
 
+       if (user_msg->len > QAIC_MANAGE_MAX_MSG_LENGTH)
+               return -EINVAL;
+
        usr = file_priv->driver_priv;
 
        usr_rcu_id = srcu_read_lock(&usr->qddev_lock);
@@ -1275,13 +1291,6 @@ int qaic_manage_ioctl(struct drm_device *dev, void *data, struct drm_file *file_
                return -ENODEV;
        }
 
-       user_msg = data;
-
-       if (user_msg->len > QAIC_MANAGE_MAX_MSG_LENGTH) {
-               ret = -EINVAL;
-               goto out;
-       }
-
        msg = kzalloc(QAIC_MANAGE_MAX_MSG_LENGTH + sizeof(*msg), GFP_KERNEL);
        if (!msg) {
                ret = -ENOMEM;
index c0a574cd1b35c6b80696e0b3d46380eef5008e6f..e42c1f9ffff85eb72650b2bc75590d924d4f3d02 100644 (file)
@@ -591,7 +591,7 @@ static int qaic_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struc
        struct qaic_bo *bo = to_qaic_bo(obj);
        unsigned long offset = 0;
        struct scatterlist *sg;
-       int ret;
+       int ret = 0;
 
        if (obj->import_attach)
                return -EINVAL;
@@ -663,6 +663,10 @@ int qaic_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *fi
        if (args->pad)
                return -EINVAL;
 
+       size = PAGE_ALIGN(args->size);
+       if (size == 0)
+               return -EINVAL;
+
        usr = file_priv->driver_priv;
        usr_rcu_id = srcu_read_lock(&usr->qddev_lock);
        if (!usr->qddev) {
@@ -677,12 +681,6 @@ int qaic_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *fi
                goto unlock_dev_srcu;
        }
 
-       size = PAGE_ALIGN(args->size);
-       if (size == 0) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
        bo = qaic_alloc_init_bo();
        if (IS_ERR(bo)) {
                ret = PTR_ERR(bo);
@@ -926,8 +924,8 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
 {
        struct qaic_attach_slice_entry *slice_ent;
        struct qaic_attach_slice *args = data;
+       int rcu_id, usr_rcu_id, qdev_rcu_id;
        struct dma_bridge_chan  *dbc;
-       int usr_rcu_id, qdev_rcu_id;
        struct drm_gem_object *obj;
        struct qaic_device *qdev;
        unsigned long arg_size;
@@ -936,6 +934,22 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
        struct qaic_bo *bo;
        int ret;
 
+       if (args->hdr.count == 0)
+               return -EINVAL;
+
+       arg_size = args->hdr.count * sizeof(*slice_ent);
+       if (arg_size / args->hdr.count != sizeof(*slice_ent))
+               return -EINVAL;
+
+       if (args->hdr.size == 0)
+               return -EINVAL;
+
+       if (!(args->hdr.dir == DMA_TO_DEVICE || args->hdr.dir == DMA_FROM_DEVICE))
+               return -EINVAL;
+
+       if (args->data == 0)
+               return -EINVAL;
+
        usr = file_priv->driver_priv;
        usr_rcu_id = srcu_read_lock(&usr->qddev_lock);
        if (!usr->qddev) {
@@ -950,43 +964,11 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
                goto unlock_dev_srcu;
        }
 
-       if (args->hdr.count == 0) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
-       arg_size = args->hdr.count * sizeof(*slice_ent);
-       if (arg_size / args->hdr.count != sizeof(*slice_ent)) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
        if (args->hdr.dbc_id >= qdev->num_dbc) {
                ret = -EINVAL;
                goto unlock_dev_srcu;
        }
 
-       if (args->hdr.size == 0) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
-       if (!(args->hdr.dir == DMA_TO_DEVICE  || args->hdr.dir == DMA_FROM_DEVICE)) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
-       dbc = &qdev->dbc[args->hdr.dbc_id];
-       if (dbc->usr != usr) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
-       if (args->data == 0) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
        user_data = u64_to_user_ptr(args->data);
 
        slice_ent = kzalloc(arg_size, GFP_KERNEL);
@@ -1013,9 +995,21 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
 
        bo = to_qaic_bo(obj);
 
+       if (bo->sliced) {
+               ret = -EINVAL;
+               goto put_bo;
+       }
+
+       dbc = &qdev->dbc[args->hdr.dbc_id];
+       rcu_id = srcu_read_lock(&dbc->ch_lock);
+       if (dbc->usr != usr) {
+               ret = -EINVAL;
+               goto unlock_ch_srcu;
+       }
+
        ret = qaic_prepare_bo(qdev, bo, &args->hdr);
        if (ret)
-               goto put_bo;
+               goto unlock_ch_srcu;
 
        ret = qaic_attach_slicing_bo(qdev, bo, &args->hdr, slice_ent);
        if (ret)
@@ -1025,6 +1019,7 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
                dma_sync_sgtable_for_cpu(&qdev->pdev->dev, bo->sgt, args->hdr.dir);
 
        bo->dbc = dbc;
+       srcu_read_unlock(&dbc->ch_lock, rcu_id);
        drm_gem_object_put(obj);
        srcu_read_unlock(&qdev->dev_lock, qdev_rcu_id);
        srcu_read_unlock(&usr->qddev_lock, usr_rcu_id);
@@ -1033,6 +1028,8 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
 
 unprepare_bo:
        qaic_unprepare_bo(qdev, bo);
+unlock_ch_srcu:
+       srcu_read_unlock(&dbc->ch_lock, rcu_id);
 put_bo:
        drm_gem_object_put(obj);
 free_slice_ent:
@@ -1316,7 +1313,6 @@ static int __qaic_execute_bo_ioctl(struct drm_device *dev, void *data, struct dr
        received_ts = ktime_get_ns();
 
        size = is_partial ? sizeof(*pexec) : sizeof(*exec);
-
        n = (unsigned long)size * args->hdr.count;
        if (args->hdr.count == 0 || n / args->hdr.count != size)
                return -EINVAL;
@@ -1665,6 +1661,9 @@ int qaic_wait_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file
        int rcu_id;
        int ret;
 
+       if (args->pad != 0)
+               return -EINVAL;
+
        usr = file_priv->driver_priv;
        usr_rcu_id = srcu_read_lock(&usr->qddev_lock);
        if (!usr->qddev) {
@@ -1679,11 +1678,6 @@ int qaic_wait_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file
                goto unlock_dev_srcu;
        }
 
-       if (args->pad != 0) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
        if (args->dbc_id >= qdev->num_dbc) {
                ret = -EINVAL;
                goto unlock_dev_srcu;
@@ -1855,6 +1849,11 @@ void wakeup_dbc(struct qaic_device *qdev, u32 dbc_id)
        dbc->usr = NULL;
        empty_xfer_list(qdev, dbc);
        synchronize_srcu(&dbc->ch_lock);
+       /*
+        * Threads holding channel lock, may add more elements in the xfer_list.
+        * Flush out these elements from xfer_list.
+        */
+       empty_xfer_list(qdev, dbc);
 }
 
 void release_dbc(struct qaic_device *qdev, u32 dbc_id)
index ff80eb5717290c7d72ed3585bd0dd982dfe0f9ce..2d0828db28d8e9d87da49b62583e48ae069831e0 100644 (file)
@@ -262,8 +262,8 @@ static void qaic_destroy_drm_device(struct qaic_device *qdev, s32 partition_id)
 
 static int qaic_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id)
 {
+       u16 major = -1, minor = -1;
        struct qaic_device *qdev;
-       u16 major, minor;
        int ret;
 
        /*
index 07ecbbde0384123d22509a37c01a117273507546..e84fb617acc44b1f56352e6cf8d351b3b25c0451 100644 (file)
@@ -46,6 +46,7 @@ if SPEAKUP
 config SPEAKUP_SERIALIO
        def_bool y
        depends on ISA || COMPILE_TEST
+       depends on HAS_IOPORT
 
 config SPEAKUP_SYNTH_ACNTSA
        tristate "Accent SA synthesizer support"
index 56c073103cbb9958e79ddf54e3b6bda0345bd812..1fbc9b921c4fccbff6bb64981ce678efd1841890 100644 (file)
@@ -1287,7 +1287,7 @@ static struct var_t spk_vars[NB_ID] = {
        [PUNC_LEVEL_ID] = { PUNC_LEVEL, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
        [READING_PUNC_ID] = { READING_PUNC, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
        [CURSOR_TIME_ID] = { CURSOR_TIME, .u.n = {NULL, 120, 50, 600, 0, 0, NULL} },
-       [SAY_CONTROL_ID] { SAY_CONTROL, TOGGLE_0},
+       [SAY_CONTROL_ID] { SAY_CONTROL, TOGGLE_0},
        [SAY_WORD_CTL_ID] = {SAY_WORD_CTL, TOGGLE_0},
        [NO_INTERRUPT_ID] = { NO_INTERRUPT, TOGGLE_0},
        [KEY_ECHO_ID] = { KEY_ECHO, .u.n = {NULL, 1, 0, 2, 0, 0, NULL} },
index 1d6ef96547252d510b570858d937bc7c222586fe..67c2c3b959e1538a645d43bda3449378c0051ed8 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef APEI_INTERNAL_H
 #define APEI_INTERNAL_H
 
-#include <linux/cper.h>
 #include <linux/acpi.h>
 
 struct apei_exec_context;
@@ -130,10 +129,5 @@ static inline u32 cper_estatus_len(struct acpi_hest_generic_status *estatus)
                return sizeof(*estatus) + estatus->data_length;
 }
 
-void cper_estatus_print(const char *pfx,
-                       const struct acpi_hest_generic_status *estatus);
-int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus);
-int cper_estatus_check(const struct acpi_hest_generic_status *estatus);
-
 int apei_osc_setup(void);
 #endif
index c23eb75866d0214fa98688e1206d106effb7cca7..7514e38d5640eed18483897f9ddfd867061d9fa9 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
+#include <linux/cper.h>
 #include <linux/io.h>
 
 #include "apei-internal.h"
index e8492b3a393ab6932c1f6c791bee1c442688fb64..0800a9d77558069edc16243098183b16f5f78e39 100644 (file)
@@ -516,6 +516,17 @@ static const struct dmi_system_id maingear_laptop[] = {
        { }
 };
 
+static const struct dmi_system_id lg_laptop[] = {
+       {
+               .ident = "LG Electronics 17U70P",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
+                       DMI_MATCH(DMI_BOARD_NAME, "17U70P"),
+               },
+       },
+       { }
+};
+
 struct irq_override_cmp {
        const struct dmi_system_id *system;
        unsigned char irq;
@@ -532,6 +543,7 @@ static const struct irq_override_cmp override_table[] = {
        { lenovo_laptop, 10, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true },
        { tongfang_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
        { maingear_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
+       { lg_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
 };
 
 static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,
index fb56bfc45096d4a8a645dc30f7441b77c6c20c33..486c8271cab7ae71cf2be952935bc034e6ae3b20 100644 (file)
@@ -66,6 +66,7 @@
 #include <linux/syscalls.h>
 #include <linux/task_work.h>
 #include <linux/sizes.h>
+#include <linux/ktime.h>
 
 #include <uapi/linux/android/binder.h>
 
@@ -1934,24 +1935,23 @@ static void binder_deferred_fd_close(int fd)
 static void binder_transaction_buffer_release(struct binder_proc *proc,
                                              struct binder_thread *thread,
                                              struct binder_buffer *buffer,
-                                             binder_size_t failed_at,
+                                             binder_size_t off_end_offset,
                                              bool is_failure)
 {
        int debug_id = buffer->debug_id;
-       binder_size_t off_start_offset, buffer_offset, off_end_offset;
+       binder_size_t off_start_offset, buffer_offset;
 
        binder_debug(BINDER_DEBUG_TRANSACTION,
                     "%d buffer release %d, size %zd-%zd, failed at %llx\n",
                     proc->pid, buffer->debug_id,
                     buffer->data_size, buffer->offsets_size,
-                    (unsigned long long)failed_at);
+                    (unsigned long long)off_end_offset);
 
        if (buffer->target_node)
                binder_dec_node(buffer->target_node, 1, 0);
 
        off_start_offset = ALIGN(buffer->data_size, sizeof(void *));
-       off_end_offset = is_failure && failed_at ? failed_at :
-                               off_start_offset + buffer->offsets_size;
+
        for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
             buffer_offset += sizeof(binder_size_t)) {
                struct binder_object_header *hdr;
@@ -2111,6 +2111,21 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
        }
 }
 
+/* Clean up all the objects in the buffer */
+static inline void binder_release_entire_buffer(struct binder_proc *proc,
+                                               struct binder_thread *thread,
+                                               struct binder_buffer *buffer,
+                                               bool is_failure)
+{
+       binder_size_t off_end_offset;
+
+       off_end_offset = ALIGN(buffer->data_size, sizeof(void *));
+       off_end_offset += buffer->offsets_size;
+
+       binder_transaction_buffer_release(proc, thread, buffer,
+                                         off_end_offset, is_failure);
+}
+
 static int binder_translate_binder(struct flat_binder_object *fp,
                                   struct binder_transaction *t,
                                   struct binder_thread *thread)
@@ -2806,7 +2821,7 @@ static int binder_proc_transaction(struct binder_transaction *t,
                t_outdated->buffer = NULL;
                buffer->transaction = NULL;
                trace_binder_transaction_update_buffer_release(buffer);
-               binder_transaction_buffer_release(proc, NULL, buffer, 0, 0);
+               binder_release_entire_buffer(proc, NULL, buffer, false);
                binder_alloc_free_buf(&proc->alloc, buffer);
                kfree(t_outdated);
                binder_stats_deleted(BINDER_STAT_TRANSACTION);
@@ -2904,6 +2919,7 @@ static void binder_transaction(struct binder_proc *proc,
        binder_size_t last_fixup_min_off = 0;
        struct binder_context *context = proc->context;
        int t_debug_id = atomic_inc_return(&binder_last_id);
+       ktime_t t_start_time = ktime_get();
        char *secctx = NULL;
        u32 secctx_sz = 0;
        struct list_head sgc_head;
@@ -3145,6 +3161,7 @@ static void binder_transaction(struct binder_proc *proc,
        binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
 
        t->debug_id = t_debug_id;
+       t->start_time = t_start_time;
 
        if (reply)
                binder_debug(BINDER_DEBUG_TRANSACTION,
@@ -3169,6 +3186,8 @@ static void binder_transaction(struct binder_proc *proc,
                t->from = thread;
        else
                t->from = NULL;
+       t->from_pid = proc->pid;
+       t->from_tid = thread->pid;
        t->sender_euid = task_euid(proc->tsk);
        t->to_proc = target_proc;
        t->to_thread = target_thread;
@@ -3775,7 +3794,7 @@ binder_free_buf(struct binder_proc *proc,
                binder_node_inner_unlock(buf_node);
        }
        trace_binder_transaction_buffer_release(buffer);
-       binder_transaction_buffer_release(proc, thread, buffer, 0, is_failure);
+       binder_release_entire_buffer(proc, thread, buffer, is_failure);
        binder_alloc_free_buf(&proc->alloc, buffer);
 }
 
@@ -5930,17 +5949,19 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
 {
        struct binder_proc *to_proc;
        struct binder_buffer *buffer = t->buffer;
+       ktime_t current_time = ktime_get();
 
        spin_lock(&t->lock);
        to_proc = t->to_proc;
        seq_printf(m,
-                  "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d",
+                  "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d elapsed %lldms",
                   prefix, t->debug_id, t,
-                  t->from ? t->from->proc->pid : 0,
-                  t->from ? t->from->pid : 0,
+                  t->from_pid,
+                  t->from_tid,
                   to_proc ? to_proc->pid : 0,
                   t->to_thread ? t->to_thread->pid : 0,
-                  t->code, t->flags, t->priority, t->need_reply);
+                  t->code, t->flags, t->priority, t->need_reply,
+                  ktime_ms_delta(current_time, t->start_time));
        spin_unlock(&t->lock);
 
        if (proc != to_proc) {
index 55a3c3c2409f0108ccbff79307e45036ad7c7701..662a2a2e2e84a77b6fc9294d34c376f3e27712f2 100644 (file)
@@ -212,8 +212,8 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
                mm = alloc->mm;
 
        if (mm) {
-               mmap_read_lock(mm);
-               vma = vma_lookup(mm, alloc->vma_addr);
+               mmap_write_lock(mm);
+               vma = alloc->vma;
        }
 
        if (!vma && need_mm) {
@@ -270,7 +270,7 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
                trace_binder_alloc_page_end(alloc, index);
        }
        if (mm) {
-               mmap_read_unlock(mm);
+               mmap_write_unlock(mm);
                mmput(mm);
        }
        return 0;
@@ -303,21 +303,24 @@ err_page_ptr_cleared:
        }
 err_no_vma:
        if (mm) {
-               mmap_read_unlock(mm);
+               mmap_write_unlock(mm);
                mmput(mm);
        }
        return vma ? -ENOMEM : -ESRCH;
 }
 
+static inline void binder_alloc_set_vma(struct binder_alloc *alloc,
+               struct vm_area_struct *vma)
+{
+       /* pairs with smp_load_acquire in binder_alloc_get_vma() */
+       smp_store_release(&alloc->vma, vma);
+}
+
 static inline struct vm_area_struct *binder_alloc_get_vma(
                struct binder_alloc *alloc)
 {
-       struct vm_area_struct *vma = NULL;
-
-       if (alloc->vma_addr)
-               vma = vma_lookup(alloc->mm, alloc->vma_addr);
-
-       return vma;
+       /* pairs with smp_store_release in binder_alloc_set_vma() */
+       return smp_load_acquire(&alloc->vma);
 }
 
 static bool debug_low_async_space_locked(struct binder_alloc *alloc, int pid)
@@ -380,15 +383,13 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
        size_t size, data_offsets_size;
        int ret;
 
-       mmap_read_lock(alloc->mm);
+       /* Check binder_alloc is fully initialized */
        if (!binder_alloc_get_vma(alloc)) {
-               mmap_read_unlock(alloc->mm);
                binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
                                   "%d: binder_alloc_buf, no vma\n",
                                   alloc->pid);
                return ERR_PTR(-ESRCH);
        }
-       mmap_read_unlock(alloc->mm);
 
        data_offsets_size = ALIGN(data_size, sizeof(void *)) +
                ALIGN(offsets_size, sizeof(void *));
@@ -778,7 +779,9 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
        buffer->free = 1;
        binder_insert_free_buffer(alloc, buffer);
        alloc->free_async_space = alloc->buffer_size / 2;
-       alloc->vma_addr = vma->vm_start;
+
+       /* Signal binder_alloc is fully initialized */
+       binder_alloc_set_vma(alloc, vma);
 
        return 0;
 
@@ -808,8 +811,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc)
 
        buffers = 0;
        mutex_lock(&alloc->mutex);
-       BUG_ON(alloc->vma_addr &&
-              vma_lookup(alloc->mm, alloc->vma_addr));
+       BUG_ON(alloc->vma);
 
        while ((n = rb_first(&alloc->allocated_buffers))) {
                buffer = rb_entry(n, struct binder_buffer, rb_node);
@@ -916,25 +918,17 @@ void binder_alloc_print_pages(struct seq_file *m,
         * Make sure the binder_alloc is fully initialized, otherwise we might
         * read inconsistent state.
         */
-
-       mmap_read_lock(alloc->mm);
-       if (binder_alloc_get_vma(alloc) == NULL) {
-               mmap_read_unlock(alloc->mm);
-               goto uninitialized;
-       }
-
-       mmap_read_unlock(alloc->mm);
-       for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
-               page = &alloc->pages[i];
-               if (!page->page_ptr)
-                       free++;
-               else if (list_empty(&page->lru))
-                       active++;
-               else
-                       lru++;
+       if (binder_alloc_get_vma(alloc) != NULL) {
+               for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
+                       page = &alloc->pages[i];
+                       if (!page->page_ptr)
+                               free++;
+                       else if (list_empty(&page->lru))
+                               active++;
+                       else
+                               lru++;
+               }
        }
-
-uninitialized:
        mutex_unlock(&alloc->mutex);
        seq_printf(m, "  pages: %d:%d:%d\n", active, lru, free);
        seq_printf(m, "  pages high watermark: %zu\n", alloc->pages_high);
@@ -969,7 +963,7 @@ int binder_alloc_get_allocated_count(struct binder_alloc *alloc)
  */
 void binder_alloc_vma_close(struct binder_alloc *alloc)
 {
-       alloc->vma_addr = 0;
+       binder_alloc_set_vma(alloc, NULL);
 }
 
 /**
index 0f811ac4bcffd1f922a6bd895cd5682ad9acd08c..138d1d5af9ce36051893ee50a8e728d7bfbc2940 100644 (file)
@@ -75,7 +75,7 @@ struct binder_lru_page {
 /**
  * struct binder_alloc - per-binder proc state for binder allocator
  * @mutex:              protects binder_alloc fields
- * @vma_addr:           vm_area_struct->vm_start passed to mmap_handler
+ * @vma:                vm_area_struct passed to mmap_handler
  *                      (invariant after mmap)
  * @mm:                 copy of task->mm (invariant after open)
  * @buffer:             base of per-proc address space mapped via mmap
@@ -99,7 +99,7 @@ struct binder_lru_page {
  */
 struct binder_alloc {
        struct mutex mutex;
-       unsigned long vma_addr;
+       struct vm_area_struct *vma;
        struct mm_struct *mm;
        void __user *buffer;
        struct list_head buffers;
index 43a881073a42832feb96c906c53e0ad34d2b2970..c2b323bc3b3a53043fa5783fb4f809de93b24644 100644 (file)
@@ -287,7 +287,7 @@ void binder_selftest_alloc(struct binder_alloc *alloc)
        if (!binder_selftest_run)
                return;
        mutex_lock(&binder_selftest_lock);
-       if (!binder_selftest_run || !alloc->vma_addr)
+       if (!binder_selftest_run || !alloc->vma)
                goto done;
        pr_info("STARTED\n");
        binder_selftest_alloc_offset(alloc, end_offset, 0);
index 28ef5b3704b1a9b02d559b7f427bd403886ce8d1..7270d4d22207021007af32638b79b0e48bdd313c 100644 (file)
@@ -515,6 +515,8 @@ struct binder_transaction {
        int debug_id;
        struct binder_work work;
        struct binder_thread *from;
+       pid_t from_pid;
+       pid_t from_tid;
        struct binder_transaction *from_parent;
        struct binder_proc *to_proc;
        struct binder_thread *to_thread;
@@ -528,6 +530,7 @@ struct binder_transaction {
        long    priority;
        long    saved_priority;
        kuid_t  sender_euid;
+       ktime_t start_time;
        struct list_head fd_fixups;
        binder_uintptr_t security_ctx;
        /**
index 7bb12deab70c465bb2a701548bdc044cd8bcb11f..8ce90284eb344b6a49e8d40ad5be930e8d7485f7 100644 (file)
@@ -2694,18 +2694,36 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
        return 0;
 }
 
-static struct ata_device *ata_find_dev(struct ata_port *ap, int devno)
+static struct ata_device *ata_find_dev(struct ata_port *ap, unsigned int devno)
 {
-       if (!sata_pmp_attached(ap)) {
-               if (likely(devno >= 0 &&
-                          devno < ata_link_max_devices(&ap->link)))
+       /*
+        * For the non-PMP case, ata_link_max_devices() returns 1 (SATA case),
+        * or 2 (IDE master + slave case). However, the former case includes
+        * libsas hosted devices which are numbered per scsi host, leading
+        * to devno potentially being larger than 0 but with each struct
+        * ata_device having its own struct ata_port and struct ata_link.
+        * To accommodate these, ignore devno and always use device number 0.
+        */
+       if (likely(!sata_pmp_attached(ap))) {
+               int link_max_devices = ata_link_max_devices(&ap->link);
+
+               if (link_max_devices == 1)
+                       return &ap->link.device[0];
+
+               if (devno < link_max_devices)
                        return &ap->link.device[devno];
-       } else {
-               if (likely(devno >= 0 &&
-                          devno < ap->nr_pmp_links))
-                       return &ap->pmp_link[devno].device[0];
+
+               return NULL;
        }
 
+       /*
+        * For PMP-attached devices, the device number corresponds to C
+        * (channel) of SCSI [H:C:I:L], indicating the port pmp link
+        * for the device.
+        */
+       if (devno < ap->nr_pmp_links)
+               return &ap->pmp_link[devno].device[0];
+
        return NULL;
 }
 
index bba3482ddeb82e72b8578f4db36bdb5d78511a6f..cbae8be1fe52005553e3d9dded77a21595d2cafc 100644 (file)
@@ -388,6 +388,16 @@ static int cache_shared_cpu_map_setup(unsigned int cpu)
                                continue;/* skip if itself or no cacheinfo */
                        for (sib_index = 0; sib_index < cache_leaves(i); sib_index++) {
                                sib_leaf = per_cpu_cacheinfo_idx(i, sib_index);
+
+                               /*
+                                * Comparing cache IDs only makes sense if the leaves
+                                * belong to the same cache level of same type. Skip
+                                * the check if level and type do not match.
+                                */
+                               if (sib_leaf->level != this_leaf->level ||
+                                   sib_leaf->type != this_leaf->type)
+                                       continue;
+
                                if (cache_leaves_are_shared(this_leaf, sib_leaf)) {
                                        cpumask_set_cpu(cpu, &sib_leaf->shared_cpu_map);
                                        cpumask_set_cpu(i, &this_leaf->shared_cpu_map);
@@ -400,11 +410,14 @@ static int cache_shared_cpu_map_setup(unsigned int cpu)
                        coherency_max_size = this_leaf->coherency_line_size;
        }
 
+       /* shared_cpu_map is now populated for the cpu */
+       this_cpu_ci->cpu_map_populated = true;
        return 0;
 }
 
 static void cache_shared_cpu_map_remove(unsigned int cpu)
 {
+       struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
        struct cacheinfo *this_leaf, *sib_leaf;
        unsigned int sibling, index, sib_index;
 
@@ -419,6 +432,16 @@ static void cache_shared_cpu_map_remove(unsigned int cpu)
 
                        for (sib_index = 0; sib_index < cache_leaves(sibling); sib_index++) {
                                sib_leaf = per_cpu_cacheinfo_idx(sibling, sib_index);
+
+                               /*
+                                * Comparing cache IDs only makes sense if the leaves
+                                * belong to the same cache level of same type. Skip
+                                * the check if level and type do not match.
+                                */
+                               if (sib_leaf->level != this_leaf->level ||
+                                   sib_leaf->type != this_leaf->type)
+                                       continue;
+
                                if (cache_leaves_are_shared(this_leaf, sib_leaf)) {
                                        cpumask_clear_cpu(cpu, &sib_leaf->shared_cpu_map);
                                        cpumask_clear_cpu(sibling, &this_leaf->shared_cpu_map);
@@ -427,6 +450,9 @@ static void cache_shared_cpu_map_remove(unsigned int cpu)
                        }
                }
        }
+
+       /* cpu is no longer populated in the shared map */
+       this_cpu_ci->cpu_map_populated = false;
 }
 
 static void free_cache_attributes(unsigned int cpu)
index ac1808d1a2e8f0012beb816b97a7101b048b688c..05d9df90f621be89cdbd7d1ecee888c18a6b688b 100644 (file)
@@ -320,6 +320,7 @@ void class_dev_iter_init(struct class_dev_iter *iter, const struct class *class,
                start_knode = &start->p->knode_class;
        klist_iter_init_node(&sp->klist_devices, &iter->ki, start_knode);
        iter->type = type;
+       iter->sp = sp;
 }
 EXPORT_SYMBOL_GPL(class_dev_iter_init);
 
@@ -361,6 +362,7 @@ EXPORT_SYMBOL_GPL(class_dev_iter_next);
 void class_dev_iter_exit(struct class_dev_iter *iter)
 {
        klist_iter_exit(&iter->ki);
+       subsys_put(iter->sp);
 }
 EXPORT_SYMBOL_GPL(class_dev_iter_exit);
 
index 9d79d5ad9102417386de44356c0d6d2af45f8e47..b58c42f1b1ce658157c2c832bca8ea929286b139 100644 (file)
@@ -812,7 +812,7 @@ static void fw_log_firmware_info(const struct firmware *fw, const char *name, st
        char *outbuf;
 
        alg = crypto_alloc_shash("sha256", 0, 0);
-       if (!alg)
+       if (IS_ERR(alg))
                return;
 
        sha256buf = kmalloc(SHA256_DIGEST_SIZE, GFP_KERNEL);
index 33a8366e22a584a5681b9434cfac240e238d750c..0db2021f7477f2abd40ee69ff23dd759dbc6a1a7 100644 (file)
@@ -4,16 +4,23 @@
 # subsystems should select the appropriate symbols.
 
 config REGMAP
+       bool "Register Map support" if KUNIT_ALL_TESTS
        default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO || REGMAP_FSI)
        select IRQ_DOMAIN if REGMAP_IRQ
        select MDIO_BUS if REGMAP_MDIO
-       bool
+       help
+         Enable support for the Register Map (regmap) access API.
+
+         Usually, this option is automatically selected when needed.
+         However, you may want to enable it manually for running the regmap
+         KUnit tests.
+
+         If unsure, say N.
 
 config REGMAP_KUNIT
        tristate "KUnit tests for regmap"
-       depends on KUNIT
+       depends on KUNIT && REGMAP
        default KUNIT_ALL_TESTS
-       select REGMAP
        select REGMAP_RAM
 
 config REGMAP_AC97
index 9b1b559107ef4d8016536ab8ba589be4b02aa725..c2e3a0f6c2183bd2c3cc59561d162317dfea8d50 100644 (file)
@@ -203,15 +203,18 @@ static int regcache_maple_sync(struct regmap *map, unsigned int min,
 
        mas_for_each(&mas, entry, max) {
                for (r = max(mas.index, lmin); r <= min(mas.last, lmax); r++) {
+                       mas_pause(&mas);
+                       rcu_read_unlock();
                        ret = regcache_sync_val(map, r, entry[r - mas.index]);
                        if (ret != 0)
                                goto out;
+                       rcu_read_lock();
                }
        }
 
-out:
        rcu_read_unlock();
 
+out:
        map->cache_bypass = false;
 
        return ret;
index 09899ae99fc199b0585c7f417c1f76043dced7d0..159c0b740b001c18f1c9510d956c97316f9689b6 100644 (file)
@@ -59,6 +59,10 @@ static int regmap_sdw_config_check(const struct regmap_config *config)
        if (config->pad_bits != 0)
                return -ENOTSUPP;
 
+       /* Only bulk writes are supported not multi-register writes */
+       if (config->can_multi_write)
+               return -ENOTSUPP;
+
        return 0;
 }
 
index db7851f0e3b8cd7542b93a09d9a9224557868fd7..fa2d3fba6ac9d1d9df6f3a8ef63506c16f1e0cb0 100644 (file)
@@ -2082,6 +2082,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
        size_t val_count = val_len / val_bytes;
        size_t chunk_count, chunk_bytes;
        size_t chunk_regs = val_count;
+       size_t max_data = map->max_raw_write - map->format.reg_bytes -
+                       map->format.pad_bytes;
        int ret, i;
 
        if (!val_count)
@@ -2089,8 +2091,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
 
        if (map->use_single_write)
                chunk_regs = 1;
-       else if (map->max_raw_write && val_len > map->max_raw_write)
-               chunk_regs = map->max_raw_write / val_bytes;
+       else if (map->max_raw_write && val_len > max_data)
+               chunk_regs = max_data / val_bytes;
 
        chunk_count = val_count / chunk_regs;
        chunk_bytes = chunk_regs * val_bytes;
index 9c35c958f2c884ec92cde079dbdfacd94cb4e703..65ecde3e2a5be810461a99cca98824dedbbbae1d 100644 (file)
@@ -1666,7 +1666,7 @@ static int nbd_dev_dbg_init(struct nbd_device *nbd)
                return -EIO;
 
        dir = debugfs_create_dir(nbd_name(nbd), nbd_dbg_dir);
-       if (!dir) {
+       if (IS_ERR(dir)) {
                dev_err(nbd_to_dev(nbd), "Failed to create debugfs dir for '%s'\n",
                        nbd_name(nbd));
                return -EIO;
@@ -1692,7 +1692,7 @@ static int nbd_dbg_init(void)
        struct dentry *dbg_dir;
 
        dbg_dir = debugfs_create_dir("nbd", NULL);
-       if (!dbg_dir)
+       if (IS_ERR(dbg_dir))
                return -EIO;
 
        nbd_dbg_dir = dbg_dir;
index ea7ac8bca63cfa1d0b39fe53a4420a4de9d65a44..da1d0542d7e2c243b823a0a50c6fd32359a52c3c 100644 (file)
@@ -241,7 +241,7 @@ static inline blk_opf_t rnbd_to_bio_flags(u32 rnbd_opf)
                bio_opf = REQ_OP_WRITE;
                break;
        case RNBD_OP_FLUSH:
-               bio_opf = REQ_OP_FLUSH | REQ_PREFLUSH;
+               bio_opf = REQ_OP_WRITE | REQ_PREFLUSH;
                break;
        case RNBD_OP_DISCARD:
                bio_opf = REQ_OP_DISCARD;
index c7331f51975031aaf8f2d838cd7a37701651ea4b..33d3298a0da16f1f70ecc87495f77746f2e6a4af 100644 (file)
@@ -1120,6 +1120,11 @@ static inline bool ublk_queue_ready(struct ublk_queue *ubq)
        return ubq->nr_io_ready == ubq->q_depth;
 }
 
+static void ublk_cmd_cancel_cb(struct io_uring_cmd *cmd, unsigned issue_flags)
+{
+       io_uring_cmd_done(cmd, UBLK_IO_RES_ABORT, 0, issue_flags);
+}
+
 static void ublk_cancel_queue(struct ublk_queue *ubq)
 {
        int i;
@@ -1131,8 +1136,8 @@ static void ublk_cancel_queue(struct ublk_queue *ubq)
                struct ublk_io *io = &ubq->ios[i];
 
                if (io->flags & UBLK_IO_FLAG_ACTIVE)
-                       io_uring_cmd_done(io->cmd, UBLK_IO_RES_ABORT, 0,
-                                               IO_URING_F_UNLOCKED);
+                       io_uring_cmd_complete_in_task(io->cmd,
+                                                     ublk_cmd_cancel_cb);
        }
 
        /* all io commands are canceled */
@@ -1281,7 +1286,7 @@ static inline int ublk_check_cmd_op(u32 cmd_op)
 {
        u32 ioc_type = _IOC_TYPE(cmd_op);
 
-       if (IS_ENABLED(CONFIG_BLKDEV_UBLK_LEGACY_OPCODES) && ioc_type != 'u')
+       if (!IS_ENABLED(CONFIG_BLKDEV_UBLK_LEGACY_OPCODES) && ioc_type != 'u')
                return -EOPNOTSUPP;
 
        if (ioc_type != 'u' && ioc_type != 0)
index 23ed258b57f0e585e122a60d6d4dba7cc2972f02..c1890c8a9f6e7640d874237a988437ff4aa264d7 100644 (file)
@@ -780,7 +780,8 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
                ring_req->u.rw.handle = info->handle;
                ring_req->operation = rq_data_dir(req) ?
                        BLKIF_OP_WRITE : BLKIF_OP_READ;
-               if (req_op(req) == REQ_OP_FLUSH || req->cmd_flags & REQ_FUA) {
+               if (req_op(req) == REQ_OP_FLUSH ||
+                   (req_op(req) == REQ_OP_WRITE && (req->cmd_flags & REQ_FUA))) {
                        /*
                         * Ideally we can do an unordered flush-to-disk.
                         * In case the backend onlysupports barriers, use that.
index 3a34d7c1475bceeeca3a3c5d10a10243d4d9e0f4..52ef44688d38a3685c7974feaa60af7ace37dac6 100644 (file)
@@ -1319,17 +1319,17 @@ static void nxp_serdev_remove(struct serdev_device *serdev)
        hci_free_dev(hdev);
 }
 
-static struct btnxpuart_data w8987_data = {
+static struct btnxpuart_data w8987_data __maybe_unused = {
        .helper_fw_name = NULL,
        .fw_name = FIRMWARE_W8987,
 };
 
-static struct btnxpuart_data w8997_data = {
+static struct btnxpuart_data w8997_data __maybe_unused = {
        .helper_fw_name = FIRMWARE_HELPER,
        .fw_name = FIRMWARE_W8997,
 };
 
-static const struct of_device_id nxpuart_of_match_table[] = {
+static const struct of_device_id nxpuart_of_match_table[] __maybe_unused = {
        { .compatible = "nxp,88w8987-bt", .data = &w8987_data },
        { .compatible = "nxp,88w8997-bt", .data = &w8997_data },
        { }
index 4c84be378bf27b3306be720d95527d38b8fd488c..ec5f26a45641bda35f7593f99a5236fb6e24bc58 100644 (file)
@@ -45,6 +45,9 @@ static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
        struct fsl_mc_child_objs *objs;
        struct fsl_mc_device *mc_dev;
 
+       if (!dev_is_fsl_mc(dev))
+               return 0;
+
        mc_dev = to_fsl_mc_device(dev);
        objs = data;
 
@@ -64,6 +67,9 @@ static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
 
 static int __fsl_mc_device_remove(struct device *dev, void *data)
 {
+       if (!dev_is_fsl_mc(dev))
+               return 0;
+
        fsl_mc_device_remove(to_fsl_mc_device(dev));
        return 0;
 }
index 38511fd363257a3137324d3a39ac61b37b822681..d2cad4c670a0734c883b4e326480b52edd8a4097 100644 (file)
@@ -62,6 +62,8 @@
 #include <linux/mm.h>
 #include <linux/xarray.h>
 #include <linux/cdx/cdx_bus.h>
+#include <linux/iommu.h>
+#include <linux/dma-map-ops.h>
 #include "cdx.h"
 
 /* Default DMA mask for devices on a CDX bus */
@@ -257,6 +259,7 @@ static void cdx_shutdown(struct device *dev)
 
 static int cdx_dma_configure(struct device *dev)
 {
+       struct cdx_driver *cdx_drv = to_cdx_driver(dev->driver);
        struct cdx_device *cdx_dev = to_cdx_device(dev);
        u32 input_id = cdx_dev->req_id;
        int ret;
@@ -267,9 +270,23 @@ static int cdx_dma_configure(struct device *dev)
                return ret;
        }
 
+       if (!ret && !cdx_drv->driver_managed_dma) {
+               ret = iommu_device_use_default_domain(dev);
+               if (ret)
+                       arch_teardown_dma_ops(dev);
+       }
+
        return 0;
 }
 
+static void cdx_dma_cleanup(struct device *dev)
+{
+       struct cdx_driver *cdx_drv = to_cdx_driver(dev->driver);
+
+       if (!cdx_drv->driver_managed_dma)
+               iommu_device_unuse_default_domain(dev);
+}
+
 /* show configuration fields */
 #define cdx_config_attr(field, format_string)  \
 static ssize_t \
@@ -405,6 +422,7 @@ struct bus_type cdx_bus_type = {
        .remove         = cdx_remove,
        .shutdown       = cdx_shutdown,
        .dma_configure  = cdx_dma_configure,
+       .dma_cleanup    = cdx_dma_cleanup,
        .bus_groups     = cdx_bus_groups,
        .dev_groups     = cdx_dev_groups,
 };
index c3e3b9ff8dfe120a90633e58c8f753b95a0a3bca..61bf17fbe43360cc0712a75025abb1d1371ac648 100644 (file)
@@ -18,14 +18,4 @@ config CDX_CONTROLLER
 
          If unsure, say N.
 
-config MCDI_LOGGING
-       bool "MCDI Logging for the CDX controller"
-       depends on CDX_CONTROLLER
-       help
-         Enable MCDI Logging for
-         the CDX Controller for debug
-         purpose.
-
-         If unsure, say N.
-
 endif
index a211a2ca762e3c52863a756fd6eaeecddcae832e..1eedc5eeb315439ffa6ea5df206f3d9d01548b03 100644 (file)
@@ -31,10 +31,6 @@ struct cdx_mcdi_copy_buffer {
        struct cdx_dword buffer[DIV_ROUND_UP(MCDI_CTL_SDU_LEN_MAX, 4)];
 };
 
-#ifdef CONFIG_MCDI_LOGGING
-#define LOG_LINE_MAX           (1024 - 32)
-#endif
-
 static void cdx_mcdi_cancel_cmd(struct cdx_mcdi *cdx, struct cdx_mcdi_cmd *cmd);
 static void cdx_mcdi_wait_for_cleanup(struct cdx_mcdi *cdx);
 static int cdx_mcdi_rpc_async_internal(struct cdx_mcdi *cdx,
@@ -119,14 +115,9 @@ int cdx_mcdi_init(struct cdx_mcdi *cdx)
        mcdi = cdx_mcdi_if(cdx);
        mcdi->cdx = cdx;
 
-#ifdef CONFIG_MCDI_LOGGING
-       mcdi->logging_buffer = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
-       if (!mcdi->logging_buffer)
-               goto fail2;
-#endif
        mcdi->workqueue = alloc_ordered_workqueue("mcdi_wq", 0);
        if (!mcdi->workqueue)
-               goto fail3;
+               goto fail2;
        mutex_init(&mcdi->iface_lock);
        mcdi->mode = MCDI_MODE_EVENTS;
        INIT_LIST_HEAD(&mcdi->cmd_list);
@@ -135,11 +126,7 @@ int cdx_mcdi_init(struct cdx_mcdi *cdx)
        mcdi->new_epoch = true;
 
        return 0;
-fail3:
-#ifdef CONFIG_MCDI_LOGGING
-       kfree(mcdi->logging_buffer);
 fail2:
-#endif
        kfree(cdx->mcdi);
        cdx->mcdi = NULL;
 fail:
@@ -156,10 +143,6 @@ void cdx_mcdi_finish(struct cdx_mcdi *cdx)
 
        cdx_mcdi_wait_for_cleanup(cdx);
 
-#ifdef CONFIG_MCDI_LOGGING
-       kfree(mcdi->logging_buffer);
-#endif
-
        destroy_workqueue(mcdi->workqueue);
        kfree(cdx->mcdi);
        cdx->mcdi = NULL;
@@ -246,15 +229,9 @@ static void cdx_mcdi_send_request(struct cdx_mcdi *cdx,
        size_t hdr_len;
        bool not_epoch;
        u32 xflags;
-#ifdef CONFIG_MCDI_LOGGING
-       char *buf;
-#endif
 
        if (!mcdi)
                return;
-#ifdef CONFIG_MCDI_LOGGING
-       buf = mcdi->logging_buffer; /* page-sized */
-#endif
 
        mcdi->prev_seq = cmd->seq;
        mcdi->seq_held_by[cmd->seq] = cmd;
@@ -281,39 +258,12 @@ static void cdx_mcdi_send_request(struct cdx_mcdi *cdx,
                             MC_CMD_V2_EXTN_IN_MCDI_MESSAGE_TYPE_PLATFORM);
        hdr_len = 8;
 
-#ifdef CONFIG_MCDI_LOGGING
-       if (!WARN_ON_ONCE(!buf)) {
-               const struct cdx_dword *frags[] = { hdr, inbuf };
-               const size_t frag_len[] = { hdr_len, round_up(inlen, 4) };
-               int bytes = 0;
-               int i, j;
-
-               for (j = 0; j < ARRAY_SIZE(frags); j++) {
-                       const struct cdx_dword *frag;
-
-                       frag = frags[j];
-                       for (i = 0;
-                            i < frag_len[j] / 4;
-                            i++) {
-                               /*
-                                * Do not exceed the internal printk limit.
-                                * The string before that is just over 70 bytes.
-                                */
-                               if ((bytes + 75) > LOG_LINE_MAX) {
-                                       pr_info("MCDI RPC REQ:%s \\\n", buf);
-                                       bytes = 0;
-                               }
-                               bytes += snprintf(buf + bytes,
-                                                 LOG_LINE_MAX - bytes, " %08x",
-                                                 le32_to_cpu(frag[i].cdx_u32));
-                       }
-               }
-
-               pr_info("MCDI RPC REQ:%s\n", buf);
-       }
-#endif
        hdr[0].cdx_u32 |= (__force __le32)(cdx_mcdi_payload_csum(hdr, hdr_len, inbuf, inlen) <<
                         MCDI_HEADER_XFLAGS_LBN);
+
+       print_hex_dump_debug("MCDI REQ HEADER: ", DUMP_PREFIX_NONE, 32, 4, hdr, hdr_len, false);
+       print_hex_dump_debug("MCDI REQ PAYLOAD: ", DUMP_PREFIX_NONE, 32, 4, inbuf, inlen, false);
+
        cdx->mcdi_ops->mcdi_request(cdx, hdr, hdr_len, inbuf, inlen);
 
        mcdi->new_epoch = false;
@@ -700,28 +650,10 @@ static bool cdx_mcdi_complete_cmd(struct cdx_mcdi_iface *mcdi,
                resp_data_len = 0;
        }
 
-#ifdef CONFIG_MCDI_LOGGING
-       if (!WARN_ON_ONCE(!mcdi->logging_buffer)) {
-               char *log = mcdi->logging_buffer;
-               int i, bytes = 0;
-               size_t rlen;
-
-               WARN_ON_ONCE(resp_hdr_len % 4);
-
-               rlen = resp_hdr_len / 4 + DIV_ROUND_UP(resp_data_len, 4);
-
-               for (i = 0; i < rlen; i++) {
-                       if ((bytes + 75) > LOG_LINE_MAX) {
-                               pr_info("MCDI RPC RESP:%s \\\n", log);
-                               bytes = 0;
-                       }
-                       bytes += snprintf(log + bytes, LOG_LINE_MAX - bytes,
-                                         " %08x", le32_to_cpu(outbuf[i].cdx_u32));
-               }
-
-               pr_info("MCDI RPC RESP:%s\n", log);
-       }
-#endif
+       print_hex_dump_debug("MCDI RESP HEADER: ", DUMP_PREFIX_NONE, 32, 4,
+                            outbuf, resp_hdr_len, false);
+       print_hex_dump_debug("MCDI RESP PAYLOAD: ", DUMP_PREFIX_NONE, 32, 4,
+                            outbuf + (resp_hdr_len / 4), resp_data_len, false);
 
        if (error && resp_data_len == 0) {
                /* MC rebooted during command */
index 0bfbeab04e43235572a4e08078e585da0572d4f2..54a65e9760aeee30df21111f8298c2a7dbfa0e05 100644 (file)
@@ -153,8 +153,6 @@ struct cdx_mcdi_cmd {
  * @mode: Poll for mcdi completion, or wait for an mcdi_event
  * @prev_seq: The last used sequence number
  * @new_epoch: Indicates start of day or start of MC reboot recovery
- * @logging_buffer: Buffer that may be used to build MCDI tracing messages
- * @logging_enabled: Whether to trace MCDI
  */
 struct cdx_mcdi_iface {
        struct cdx_mcdi *cdx;
@@ -170,10 +168,6 @@ struct cdx_mcdi_iface {
        enum cdx_mcdi_mode mode;
        u8 prev_seq;
        bool new_epoch;
-#ifdef CONFIG_MCDI_LOGGING
-       bool logging_enabled;
-       char *logging_buffer;
-#endif
 };
 
 /**
index 801d6c83f896163426f073400937b2de4e290215..625af75833fc37047bbb93228dbf7131404a64a5 100644 (file)
@@ -34,6 +34,7 @@ config TTY_PRINTK_LEVEL
 config PRINTER
        tristate "Parallel printer support"
        depends on PARPORT
+       depends on HAS_IOPORT || PARPORT_NOT_PC
        help
          If you intend to attach a printer to the parallel port of your Linux
          box (as opposed to using a serial printer; if the connector at the
@@ -340,7 +341,7 @@ config NVRAM
 
 config DEVPORT
        bool "/dev/port character device"
-       depends on ISA || PCI
+       depends on HAS_IOPORT
        default y
        help
          Say Y here if you want to support the /dev/port device. The /dev/port
index d68d05d5d38388523b0fecfdd45cb6e32488c784..514f9f287a781dd910de9da4034a6ea74529bc11 100644 (file)
@@ -90,6 +90,9 @@ parisc_agp_tlbflush(struct agp_memory *mem)
 {
        struct _parisc_agp_info *info = &parisc_agp_info;
 
+       /* force fdc ops to be visible to IOMMU */
+       asm_io_sync();
+
        writeq(info->gart_base | ilog2(info->gart_size), info->ioc_regs+IOC_PCOM);
        readq(info->ioc_regs+IOC_PCOM); /* flush */
 }
@@ -158,6 +161,7 @@ parisc_agp_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
                        info->gatt[j] =
                                parisc_agp_mask_memory(agp_bridge,
                                        paddr, type);
+                       asm_io_fdc(&info->gatt[j]);
                }
        }
 
@@ -191,7 +195,16 @@ static unsigned long
 parisc_agp_mask_memory(struct agp_bridge_data *bridge, dma_addr_t addr,
                       int type)
 {
-       return SBA_PDIR_VALID_BIT | addr;
+       unsigned ci;                    /* coherent index */
+       dma_addr_t pa;
+
+       pa = addr & IOVP_MASK;
+       asm("lci 0(%1), %0" : "=r" (ci) : "r" (phys_to_virt(pa)));
+
+       pa |= (ci >> PAGE_SHIFT) & 0xff;/* move CI (8 bits) into lowest byte */
+       pa |= SBA_PDIR_VALID_BIT;       /* set "valid" bit */
+
+       return cpu_to_le64(pa);
 }
 
 static void
index c10a4aa9737366f949d3fb0602971ef85ae3d5a6..cd48033b804a3871529ce9d31acb34d7ec64819e 100644 (file)
@@ -571,6 +571,10 @@ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 {
        struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng);
 
+       /* Give back zero bytes, as TPM chip has not yet fully resumed: */
+       if (chip->flags & TPM_CHIP_FLAG_SUSPENDED)
+               return 0;
+
        return tpm_get_random(chip, data, max);
 }
 
index 4463d00182909b37773101c0b826b95e4e92c8bf..586ca10b0d72e5a0ed6fb84171b8ba1754def0d8 100644 (file)
@@ -412,6 +412,8 @@ int tpm_pm_suspend(struct device *dev)
        }
 
 suspended:
+       chip->flags |= TPM_CHIP_FLAG_SUSPENDED;
+
        if (rc)
                dev_err(dev, "Ignoring error %d while suspending\n", rc);
        return 0;
@@ -429,6 +431,14 @@ int tpm_pm_resume(struct device *dev)
        if (chip == NULL)
                return -ENODEV;
 
+       chip->flags &= ~TPM_CHIP_FLAG_SUSPENDED;
+
+       /*
+        * Guarantee that SUSPENDED is written last, so that hwrng does not
+        * activate before the chip has been fully resumed.
+        */
+       wmb();
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(tpm_pm_resume);
index 7af389806643379fa76507755550fdae92871de9..7db3593941eaa0bce84ac5b5c217b814e8ae2772 100644 (file)
@@ -122,6 +122,29 @@ static const struct dmi_system_id tpm_tis_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T490s"),
                },
        },
+       {
+               .callback = tpm_tis_disable_irq,
+               .ident = "ThinkStation P360 Tiny",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkStation P360 Tiny"),
+               },
+       },
+       {
+               .callback = tpm_tis_disable_irq,
+               .ident = "ThinkPad L490",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L490"),
+               },
+       },
+       {
+               .callback = tpm_tis_disable_irq,
+               .ident = "UPX-TGL",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
+               },
+       },
        {}
 };
 
index 02945d53fcefafae4e0c72ef3b2a4cf6a8cb85e5..558144fa707ae7ad0937d1ae2a16ac3afba7e310 100644 (file)
@@ -1209,25 +1209,20 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
        u32 intmask;
        int rc;
 
-       if (chip->ops->clk_enable != NULL)
-               chip->ops->clk_enable(chip, true);
-
-       /* reenable interrupts that device may have lost or
-        * BIOS/firmware may have disabled
+       /*
+        * Re-enable interrupts that device may have lost or BIOS/firmware may
+        * have disabled.
         */
        rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), priv->irq);
-       if (rc < 0)
-               goto out;
+       if (rc < 0) {
+               dev_err(&chip->dev, "Setting IRQ failed.\n");
+               return;
+       }
 
        intmask = priv->int_mask | TPM_GLOBAL_INT_ENABLE;
-
-       tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
-
-out:
-       if (chip->ops->clk_enable != NULL)
-               chip->ops->clk_enable(chip, false);
-
-       return;
+       rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
+       if (rc < 0)
+               dev_err(&chip->dev, "Enabling interrupts failed.\n");
 }
 
 int tpm_tis_resume(struct device *dev)
@@ -1235,27 +1230,27 @@ int tpm_tis_resume(struct device *dev)
        struct tpm_chip *chip = dev_get_drvdata(dev);
        int ret;
 
-       ret = tpm_tis_request_locality(chip, 0);
-       if (ret < 0)
+       ret = tpm_chip_start(chip);
+       if (ret)
                return ret;
 
        if (chip->flags & TPM_CHIP_FLAG_IRQ)
                tpm_tis_reenable_interrupts(chip);
 
-       ret = tpm_pm_resume(dev);
-       if (ret)
-               goto out;
-
        /*
         * TPM 1.2 requires self-test on resume. This function actually returns
         * an error code but for unknown reason it isn't handled.
         */
        if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
                tpm1_do_selftest(chip);
-out:
-       tpm_tis_relinquish_locality(chip, 0);
 
-       return ret;
+       tpm_chip_stop(chip);
+
+       ret = tpm_pm_resume(dev);
+       if (ret)
+               return ret;
+
+       return 0;
 }
 EXPORT_SYMBOL_GPL(tpm_tis_resume);
 #endif
index e978f457fd4d4ce083a7a9f9689df5f2d7a8ed9d..610bfadb6acf1c1731575842eca18f1d8c6ea395 100644 (file)
@@ -84,10 +84,10 @@ enum tis_defaults {
 #define ILB_REMAP_SIZE                 0x100
 
 enum tpm_tis_flags {
-       TPM_TIS_ITPM_WORKAROUND         = BIT(0),
-       TPM_TIS_INVALID_STATUS          = BIT(1),
-       TPM_TIS_DEFAULT_CANCELLATION    = BIT(2),
-       TPM_TIS_IRQ_TESTED              = BIT(3),
+       TPM_TIS_ITPM_WORKAROUND         = 0,
+       TPM_TIS_INVALID_STATUS          = 1,
+       TPM_TIS_DEFAULT_CANCELLATION    = 2,
+       TPM_TIS_IRQ_TESTED              = 3,
 };
 
 struct tpm_tis_data {
index a46f637da9599afebb80c2bb5627671b21b08ea1..00e5cf42babc9c302b72de7ec026a3d80d45792c 100644 (file)
@@ -721,27 +721,6 @@ static struct hwicap_driver_config fifo_icap_config = {
        .reset = fifo_icap_reset,
 };
 
-static int hwicap_remove(struct device *dev)
-{
-       struct hwicap_drvdata *drvdata;
-
-       drvdata = dev_get_drvdata(dev);
-
-       if (!drvdata)
-               return 0;
-
-       device_destroy(icap_class, drvdata->devt);
-       cdev_del(&drvdata->cdev);
-       iounmap(drvdata->base_address);
-       release_mem_region(drvdata->mem_start, drvdata->mem_size);
-       kfree(drvdata);
-
-       mutex_lock(&icap_sem);
-       probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;
-       mutex_unlock(&icap_sem);
-       return 0;               /* success */
-}
-
 #ifdef CONFIG_OF
 static int hwicap_of_probe(struct platform_device *op,
                                     const struct hwicap_driver_config *config)
@@ -825,9 +804,22 @@ static int hwicap_drv_probe(struct platform_device *pdev)
                        &buffer_icap_config, regs);
 }
 
-static int hwicap_drv_remove(struct platform_device *pdev)
+static void hwicap_drv_remove(struct platform_device *pdev)
 {
-       return hwicap_remove(&pdev->dev);
+       struct device *dev = &pdev->dev;
+       struct hwicap_drvdata *drvdata;
+
+       drvdata = dev_get_drvdata(dev);
+
+       device_destroy(icap_class, drvdata->devt);
+       cdev_del(&drvdata->cdev);
+       iounmap(drvdata->base_address);
+       release_mem_region(drvdata->mem_start, drvdata->mem_size);
+       kfree(drvdata);
+
+       mutex_lock(&icap_sem);
+       probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;
+       mutex_unlock(&icap_sem);
 }
 
 #ifdef CONFIG_OF
@@ -844,7 +836,7 @@ MODULE_DEVICE_TABLE(of, hwicap_of_match);
 
 static struct platform_driver hwicap_platform_driver = {
        .probe = hwicap_drv_probe,
-       .remove = hwicap_drv_remove,
+       .remove_new = hwicap_drv_remove,
        .driver = {
                .name = DRIVER_NAME,
                .of_match_table = hwicap_of_match,
index 9af280735cbaa1db0d59dc154bcb3be7c1cc7df1..7a8d402f05be1668b1d084ad08f4834c8560cd5b 100644 (file)
@@ -67,6 +67,7 @@ config COMEDI_TEST
 
 config COMEDI_PARPORT
        tristate "Parallel port support"
+       depends on HAS_IOPORT
        help
          Enable support for the standard parallel port.
          A cheap and easy way to get a few more digital I/O lines. Steal
@@ -79,6 +80,7 @@ config COMEDI_PARPORT
 config COMEDI_SSV_DNP
        tristate "SSV Embedded Systems DIL/Net-PC support"
        depends on X86_32 || COMPILE_TEST
+       depends on HAS_IOPORT
        help
          Enable support for SSV Embedded Systems DIL/Net-PC
 
@@ -89,6 +91,7 @@ endif # COMEDI_MISC_DRIVERS
 
 menuconfig COMEDI_ISA_DRIVERS
        bool "Comedi ISA and PC/104 drivers"
+       depends on ISA
        help
          Enable comedi ISA and PC/104 drivers to be built
 
@@ -100,7 +103,8 @@ if COMEDI_ISA_DRIVERS
 
 config COMEDI_PCL711
        tristate "Advantech PCL-711/711b and ADlink ACL-8112 ISA card support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        help
          Enable support for Advantech PCL-711 and 711b, ADlink ACL-8112
 
@@ -161,8 +165,9 @@ config COMEDI_PCL730
 
 config COMEDI_PCL812
        tristate "Advantech PCL-812/813 and ADlink ACL-8112/8113/8113/8216"
+       depends on HAS_IOPORT
        select COMEDI_ISADMA if ISA_DMA_API
-       select COMEDI_8254
+       depends on COMEDI_8254
        help
          Enable support for Advantech PCL-812/PG, PCL-813/B, ADLink
          ACL-8112DG/HG/PG, ACL-8113, ACL-8216, ICP DAS A-821PGH/PGL/PGL-NDA,
@@ -173,8 +178,9 @@ config COMEDI_PCL812
 
 config COMEDI_PCL816
        tristate "Advantech PCL-814 and PCL-816 ISA card support"
+       depends on HAS_IOPORT
        select COMEDI_ISADMA if ISA_DMA_API
-       select COMEDI_8254
+       depends on COMEDI_8254
        help
          Enable support for Advantech PCL-814 and PCL-816 ISA cards
 
@@ -183,8 +189,9 @@ config COMEDI_PCL816
 
 config COMEDI_PCL818
        tristate "Advantech PCL-718 and PCL-818 ISA card support"
+       depends on HAS_IOPORT
        select COMEDI_ISADMA if ISA_DMA_API
-       select COMEDI_8254
+       depends on COMEDI_8254
        help
          Enable support for Advantech PCL-818 ISA cards
          PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818 and PCL-718
@@ -203,7 +210,7 @@ config COMEDI_PCM3724
 
 config COMEDI_AMPLC_DIO200_ISA
        tristate "Amplicon PC212E/PC214E/PC215E/PC218E/PC272E"
-       select COMEDI_AMPLC_DIO200
+       depends on COMEDI_AMPLC_DIO200
        help
          Enable support for Amplicon PC212E, PC214E, PC215E, PC218E and
          PC272E ISA DIO boards
@@ -255,7 +262,8 @@ config COMEDI_DAC02
 
 config COMEDI_DAS16M1
        tristate "MeasurementComputing CIO-DAS16/M1DAS-16 ISA card support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        select COMEDI_8255
        help
          Enable support for Measurement Computing CIO-DAS16/M1 ISA cards.
@@ -265,7 +273,7 @@ config COMEDI_DAS16M1
 
 config COMEDI_DAS08_ISA
        tristate "DAS-08 compatible ISA and PC/104 card support"
-       select COMEDI_DAS08
+       depends on COMEDI_DAS08
        help
          Enable support for Keithley Metrabyte/ComputerBoards DAS08
          and compatible ISA and PC/104 cards:
@@ -278,8 +286,9 @@ config COMEDI_DAS08_ISA
 
 config COMEDI_DAS16
        tristate "DAS-16 compatible ISA and PC/104 card support"
+       depends on HAS_IOPORT
        select COMEDI_ISADMA if ISA_DMA_API
-       select COMEDI_8254
+       depends on COMEDI_8254
        select COMEDI_8255
        help
          Enable support for Keithley Metrabyte/ComputerBoards DAS16
@@ -296,7 +305,8 @@ config COMEDI_DAS16
 
 config COMEDI_DAS800
        tristate "DAS800 and compatible ISA card support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        help
          Enable support for Keithley Metrabyte DAS800 and compatible ISA cards
          Keithley Metrabyte DAS-800, DAS-801, DAS-802
@@ -308,8 +318,9 @@ config COMEDI_DAS800
 
 config COMEDI_DAS1800
        tristate "DAS1800 and compatible ISA card support"
+       depends on HAS_IOPORT
        select COMEDI_ISADMA if ISA_DMA_API
-       select COMEDI_8254
+       depends on COMEDI_8254
        help
          Enable support for DAS1800 and compatible ISA cards
          Keithley Metrabyte DAS-1701ST, DAS-1701ST-DA, DAS-1701/AO,
@@ -323,7 +334,8 @@ config COMEDI_DAS1800
 
 config COMEDI_DAS6402
        tristate "DAS6402 and compatible ISA card support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        help
          Enable support for DAS6402 and compatible ISA cards
          Computerboards, Keithley Metrabyte DAS6402 and compatibles
@@ -402,7 +414,8 @@ config COMEDI_FL512
 
 config COMEDI_AIO_AIO12_8
        tristate "I/O Products PC/104 AIO12-8 Analog I/O Board support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        select COMEDI_8255
        help
          Enable support for I/O Products PC/104 AIO12-8 Analog I/O Board
@@ -456,8 +469,9 @@ config COMEDI_ADQ12B
 
 config COMEDI_NI_AT_A2150
        tristate "NI AT-A2150 ISA card support"
+       depends on HAS_IOPORT
        select COMEDI_ISADMA if ISA_DMA_API
-       select COMEDI_8254
+       depends on COMEDI_8254
        help
          Enable support for National Instruments AT-A2150 cards
 
@@ -466,7 +480,8 @@ config COMEDI_NI_AT_A2150
 
 config COMEDI_NI_AT_AO
        tristate "NI AT-AO-6/10 EISA card support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        help
          Enable support for National Instruments AT-AO-6/10 cards
 
@@ -497,7 +512,7 @@ config COMEDI_NI_ATMIO16D
 
 config COMEDI_NI_LABPC_ISA
        tristate "NI Lab-PC and compatibles ISA support"
-       select COMEDI_NI_LABPC
+       depends on COMEDI_NI_LABPC
        help
          Enable support for National Instruments Lab-PC and compatibles
          Lab-PC-1200, Lab-PC-1200AI, Lab-PC+.
@@ -561,7 +576,7 @@ endif # COMEDI_ISA_DRIVERS
 
 menuconfig COMEDI_PCI_DRIVERS
        tristate "Comedi PCI drivers"
-       depends on PCI
+       depends on PCI && HAS_IOPORT
        help
          Enable support for comedi PCI drivers.
 
@@ -710,7 +725,8 @@ config COMEDI_ADL_PCI8164
 
 config COMEDI_ADL_PCI9111
        tristate "ADLink PCI-9111HR support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        help
          Enable support for ADlink PCI9111 cards
 
@@ -720,7 +736,7 @@ config COMEDI_ADL_PCI9111
 config COMEDI_ADL_PCI9118
        tristate "ADLink PCI-9118DG, PCI-9118HG, PCI-9118HR support"
        depends on HAS_DMA
-       select COMEDI_8254
+       depends on COMEDI_8254
        help
          Enable support for ADlink PCI-9118DG, PCI-9118HG, PCI-9118HR cards
 
@@ -729,7 +745,8 @@ config COMEDI_ADL_PCI9118
 
 config COMEDI_ADV_PCI1710
        tristate "Advantech PCI-171x and PCI-1731 support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        help
          Enable support for Advantech PCI-1710, PCI-1710HG, PCI-1711,
          PCI-1713 and PCI-1731
@@ -773,7 +790,8 @@ config COMEDI_ADV_PCI1760
 
 config COMEDI_ADV_PCI_DIO
        tristate "Advantech PCI DIO card support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        select COMEDI_8255
        help
          Enable support for Advantech PCI DIO cards
@@ -786,7 +804,7 @@ config COMEDI_ADV_PCI_DIO
 
 config COMEDI_AMPLC_DIO200_PCI
        tristate "Amplicon PCI215/PCI272/PCIe215/PCIe236/PCIe296 DIO support"
-       select COMEDI_AMPLC_DIO200
+       depends on COMEDI_AMPLC_DIO200
        help
          Enable support for Amplicon PCI215, PCI272, PCIe215, PCIe236
          and PCIe296 DIO boards.
@@ -814,7 +832,8 @@ config COMEDI_AMPLC_PC263_PCI
 
 config COMEDI_AMPLC_PCI224
        tristate "Amplicon PCI224 and PCI234 support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        help
          Enable support for Amplicon PCI224 and PCI234 AO boards
 
@@ -823,7 +842,8 @@ config COMEDI_AMPLC_PCI224
 
 config COMEDI_AMPLC_PCI230
        tristate "Amplicon PCI230 and PCI260 support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        select COMEDI_8255
        help
          Enable support for Amplicon PCI230 and PCI260 Multifunction I/O
@@ -842,7 +862,7 @@ config COMEDI_CONTEC_PCI_DIO
 
 config COMEDI_DAS08_PCI
        tristate "DAS-08 PCI support"
-       select COMEDI_DAS08
+       depends on COMEDI_DAS08
        help
          Enable support for PCI DAS-08 cards.
 
@@ -929,7 +949,8 @@ config COMEDI_CB_PCIDAS64
 
 config COMEDI_CB_PCIDAS
        tristate "MeasurementComputing PCI-DAS support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        select COMEDI_8255
        help
          Enable support for ComputerBoards/MeasurementComputing PCI-DAS with
@@ -953,7 +974,8 @@ config COMEDI_CB_PCIDDA
 
 config COMEDI_CB_PCIMDAS
        tristate "MeasurementComputing PCIM-DAS1602/16, PCIe-DAS1602/16 support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        select COMEDI_8255
        help
          Enable support for ComputerBoards/MeasurementComputing PCI Migration
@@ -973,7 +995,8 @@ config COMEDI_CB_PCIMDDA
 
 config COMEDI_ME4000
        tristate "Meilhaus ME-4000 support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        help
          Enable support for Meilhaus PCI data acquisition cards
          ME-4650, ME-4670i, ME-4680, ME-4680i and ME-4680is
@@ -1031,7 +1054,7 @@ config COMEDI_NI_670X
 
 config COMEDI_NI_LABPC_PCI
        tristate "NI Lab-PC PCI-1200 support"
-       select COMEDI_NI_LABPC
+       depends on COMEDI_NI_LABPC
        help
          Enable support for National Instruments Lab-PC PCI-1200.
 
@@ -1053,6 +1076,7 @@ config COMEDI_NI_PCIDIO
 config COMEDI_NI_PCIMIO
        tristate "NI PCI-MIO-E series and M series support"
        depends on HAS_DMA
+       depends on HAS_IOPORT
        select COMEDI_NI_TIOCMD
        select COMEDI_8255
        help
@@ -1074,7 +1098,8 @@ config COMEDI_NI_PCIMIO
 
 config COMEDI_RTD520
        tristate "Real Time Devices PCI4520/DM7520 support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        help
          Enable support for Real Time Devices PCI4520/DM7520
 
@@ -1114,7 +1139,8 @@ if COMEDI_PCMCIA_DRIVERS
 
 config COMEDI_CB_DAS16_CS
        tristate "CB DAS16 series PCMCIA support"
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        help
          Enable support for the ComputerBoards/MeasurementComputing PCMCIA
          cards DAS16/16, PCM-DAS16D/12 and PCM-DAS16s/16
@@ -1124,7 +1150,7 @@ config COMEDI_CB_DAS16_CS
 
 config COMEDI_DAS08_CS
        tristate "CB DAS08 PCMCIA support"
-       select COMEDI_DAS08
+       depends on COMEDI_DAS08
        help
          Enable support for the ComputerBoards/MeasurementComputing DAS-08
          PCMCIA card
@@ -1134,6 +1160,7 @@ config COMEDI_DAS08_CS
 
 config COMEDI_NI_DAQ_700_CS
        tristate "NI DAQCard-700 PCMCIA support"
+       depends on HAS_IOPORT
        help
          Enable support for the National Instruments PCMCIA DAQCard-700 DIO
 
@@ -1142,6 +1169,7 @@ config COMEDI_NI_DAQ_700_CS
 
 config COMEDI_NI_DAQ_DIO24_CS
        tristate "NI DAQ-Card DIO-24 PCMCIA support"
+       depends on HAS_IOPORT
        select COMEDI_8255
        help
          Enable support for the National Instruments PCMCIA DAQ-Card DIO-24
@@ -1151,7 +1179,7 @@ config COMEDI_NI_DAQ_DIO24_CS
 
 config COMEDI_NI_LABPC_CS
        tristate "NI DAQCard-1200 PCMCIA support"
-       select COMEDI_NI_LABPC
+       depends on COMEDI_NI_LABPC
        help
          Enable support for the National Instruments PCMCIA DAQCard-1200
 
@@ -1160,6 +1188,7 @@ config COMEDI_NI_LABPC_CS
 
 config COMEDI_NI_MIO_CS
        tristate "NI DAQCard E series PCMCIA support"
+       depends on HAS_IOPORT
        select COMEDI_NI_TIO
        select COMEDI_8255
        help
@@ -1172,6 +1201,7 @@ config COMEDI_NI_MIO_CS
 
 config COMEDI_QUATECH_DAQP_CS
        tristate "Quatech DAQP PCMCIA data capture card support"
+       depends on HAS_IOPORT
        help
          Enable support for the Quatech DAQP PCMCIA data capture cards
          DAQP-208 and DAQP-308
@@ -1248,12 +1278,14 @@ endif # COMEDI_USB_DRIVERS
 
 config COMEDI_8254
        tristate
+       depends on HAS_IOPORT
 
 config COMEDI_8255
        tristate
 
 config COMEDI_8255_SA
        tristate "Standalone 8255 support"
+       depends on HAS_IOPORT
        select COMEDI_8255
        help
          Enable support for 8255 digital I/O as a standalone driver.
@@ -1285,7 +1317,7 @@ config COMEDI_KCOMEDILIB
          called kcomedilib.
 
 config COMEDI_AMPLC_DIO200
-       select COMEDI_8254
+       depends on COMEDI_8254
        tristate
 
 config COMEDI_AMPLC_PC236
@@ -1294,7 +1326,7 @@ config COMEDI_AMPLC_PC236
 
 config COMEDI_DAS08
        tristate
-       select COMEDI_8254
+       depends on COMEDI_8254
        select COMEDI_8255
 
 config COMEDI_ISADMA
@@ -1302,7 +1334,8 @@ config COMEDI_ISADMA
 
 config COMEDI_NI_LABPC
        tristate
-       select COMEDI_8254
+       depends on HAS_IOPORT
+       depends on COMEDI_8254
        select COMEDI_8255
 
 config COMEDI_NI_LABPC_ISADMA
index d9cb937665cfcf657a80bbb150b2b04858599c8c..ed1f57511955856af1bbb76fc8b3e81ce51ae7b8 100644 (file)
@@ -5,10 +5,11 @@
  *
  * This driver supports the ACCES 104-QUAD-8 and ACCES 104-QUAD-4.
  */
-#include <linux/bitops.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
 #include <linux/counter.h>
 #include <linux/device.h>
-#include <linux/errno.h>
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/types.h>
+#include <linux/regmap.h>
 #include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/unaligned.h>
 
 #define QUAD8_EXTENT 32
 
@@ -34,118 +38,196 @@ MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers");
 
 #define QUAD8_NUM_COUNTERS 8
 
-/**
- * struct channel_reg - channel register structure
- * @data:      Count data
- * @control:   Channel flags and control
- */
-struct channel_reg {
-       u8 data;
-       u8 control;
-};
-
-/**
- * struct quad8_reg - device register structure
- * @channel:           quadrature counter data and control
- * @interrupt_status:  channel interrupt status
- * @channel_oper:      enable/reset counters and interrupt functions
- * @index_interrupt:   enable channel interrupts
- * @reserved:          reserved for Factory Use
- * @index_input_levels:        index signal logical input level
- * @cable_status:      differential encoder cable status
- */
-struct quad8_reg {
-       struct channel_reg channel[QUAD8_NUM_COUNTERS];
-       u8 interrupt_status;
-       u8 channel_oper;
-       u8 index_interrupt;
-       u8 reserved[3];
-       u8 index_input_levels;
-       u8 cable_status;
-};
+#define QUAD8_DATA(_channel) ((_channel) * 2)
+#define QUAD8_CONTROL(_channel) (QUAD8_DATA(_channel) + 1)
+#define QUAD8_INTERRUPT_STATUS 0x10
+#define QUAD8_CHANNEL_OPERATION 0x11
+#define QUAD8_INDEX_INTERRUPT 0x12
+#define QUAD8_INDEX_INPUT_LEVELS 0x16
+#define QUAD8_CABLE_STATUS 0x17
 
 /**
  * struct quad8 - device private data structure
  * @lock:              lock to prevent clobbering device states during R/W ops
- * @counter:           instance of the counter_device
+ * @cmr:               array of Counter Mode Register states
+ * @ior:               array of Input / Output Control Register states
+ * @idr:               array of Index Control Register states
  * @fck_prescaler:     array of filter clock prescaler configurations
  * @preset:            array of preset values
- * @count_mode:                array of count mode configurations
- * @quadrature_mode:   array of quadrature mode configurations
- * @quadrature_scale:  array of quadrature mode scale configurations
- * @ab_enable:         array of A and B inputs enable configurations
- * @preset_enable:     array of set_to_preset_on_index attribute configurations
- * @irq_trigger:       array of current IRQ trigger function configurations
- * @synchronous_mode:  array of index function synchronous mode configurations
- * @index_polarity:    array of index function polarity configurations
  * @cable_fault_enable:        differential encoder cable status enable configurations
- * @reg:               I/O address offset for the device registers
+ * @map:               regmap for the device
  */
 struct quad8 {
        spinlock_t lock;
+       u8 cmr[QUAD8_NUM_COUNTERS];
+       u8 ior[QUAD8_NUM_COUNTERS];
+       u8 idr[QUAD8_NUM_COUNTERS];
        unsigned int fck_prescaler[QUAD8_NUM_COUNTERS];
        unsigned int preset[QUAD8_NUM_COUNTERS];
-       unsigned int count_mode[QUAD8_NUM_COUNTERS];
-       unsigned int quadrature_mode[QUAD8_NUM_COUNTERS];
-       unsigned int quadrature_scale[QUAD8_NUM_COUNTERS];
-       unsigned int ab_enable[QUAD8_NUM_COUNTERS];
-       unsigned int preset_enable[QUAD8_NUM_COUNTERS];
-       unsigned int irq_trigger[QUAD8_NUM_COUNTERS];
-       unsigned int synchronous_mode[QUAD8_NUM_COUNTERS];
-       unsigned int index_polarity[QUAD8_NUM_COUNTERS];
        unsigned int cable_fault_enable;
-       struct quad8_reg __iomem *reg;
+       struct regmap *map;
+};
+
+static const struct regmap_range quad8_wr_ranges[] = {
+       regmap_reg_range(0x0, 0xF), regmap_reg_range(0x11, 0x12), regmap_reg_range(0x17, 0x17),
+};
+static const struct regmap_range quad8_rd_ranges[] = {
+       regmap_reg_range(0x0, 0x12), regmap_reg_range(0x16, 0x18),
+};
+static const struct regmap_access_table quad8_wr_table = {
+       .yes_ranges = quad8_wr_ranges,
+       .n_yes_ranges = ARRAY_SIZE(quad8_wr_ranges),
+};
+static const struct regmap_access_table quad8_rd_table = {
+       .yes_ranges = quad8_rd_ranges,
+       .n_yes_ranges = ARRAY_SIZE(quad8_rd_ranges),
+};
+static const struct regmap_config quad8_regmap_config = {
+       .reg_bits = 8,
+       .reg_stride = 1,
+       .val_bits = 8,
+       .io_port = true,
+       .wr_table = &quad8_wr_table,
+       .rd_table = &quad8_rd_table,
 };
 
 /* Error flag */
-#define QUAD8_FLAG_E BIT(4)
+#define FLAG_E BIT(4)
 /* Up/Down flag */
-#define QUAD8_FLAG_UD BIT(5)
+#define FLAG_UD BIT(5)
+/* Counting up */
+#define UP 0x1
+
+#define REGISTER_SELECTION GENMASK(6, 5)
+
 /* Reset and Load Signal Decoders */
-#define QUAD8_CTR_RLD 0x00
+#define SELECT_RLD u8_encode_bits(0x0, REGISTER_SELECTION)
 /* Counter Mode Register */
-#define QUAD8_CTR_CMR 0x20
+#define SELECT_CMR u8_encode_bits(0x1, REGISTER_SELECTION)
 /* Input / Output Control Register */
-#define QUAD8_CTR_IOR 0x40
+#define SELECT_IOR u8_encode_bits(0x2, REGISTER_SELECTION)
 /* Index Control Register */
-#define QUAD8_CTR_IDR 0x60
+#define SELECT_IDR u8_encode_bits(0x3, REGISTER_SELECTION)
+
+/*
+ * Reset and Load Signal Decoders
+ */
+#define RESETS GENMASK(2, 1)
+#define LOADS GENMASK(4, 3)
 /* Reset Byte Pointer (three byte data pointer) */
-#define QUAD8_RLD_RESET_BP 0x01
-/* Reset Counter */
-#define QUAD8_RLD_RESET_CNTR 0x02
-/* Reset Borrow Toggle, Carry Toggle, Compare Toggle, and Sign flags */
-#define QUAD8_RLD_RESET_FLAGS 0x04
+#define RESET_BP BIT(0)
+/* Reset Borrow Toggle, Carry toggle, Compare toggle, Sign, and Index flags */
+#define RESET_BT_CT_CPT_S_IDX u8_encode_bits(0x2, RESETS)
 /* Reset Error flag */
-#define QUAD8_RLD_RESET_E 0x06
+#define RESET_E u8_encode_bits(0x3, RESETS)
 /* Preset Register to Counter */
-#define QUAD8_RLD_PRESET_CNTR 0x08
+#define TRANSFER_PR_TO_CNTR u8_encode_bits(0x1, LOADS)
 /* Transfer Counter to Output Latch */
-#define QUAD8_RLD_CNTR_OUT 0x10
+#define TRANSFER_CNTR_TO_OL u8_encode_bits(0x2, LOADS)
 /* Transfer Preset Register LSB to FCK Prescaler */
-#define QUAD8_RLD_PRESET_PSC 0x18
-#define QUAD8_CHAN_OP_RESET_COUNTERS 0x01
-#define QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC 0x04
-#define QUAD8_CMR_QUADRATURE_X1 0x08
-#define QUAD8_CMR_QUADRATURE_X2 0x10
-#define QUAD8_CMR_QUADRATURE_X4 0x18
+#define TRANSFER_PR0_TO_PSC u8_encode_bits(0x3, LOADS)
+
+/*
+ * Counter Mode Registers
+ */
+#define COUNT_ENCODING BIT(0)
+#define COUNT_MODE GENMASK(2, 1)
+#define QUADRATURE_MODE GENMASK(4, 3)
+/* Binary count */
+#define BINARY u8_encode_bits(0x0, COUNT_ENCODING)
+/* Normal count */
+#define NORMAL_COUNT 0x0
+/* Range Limit */
+#define RANGE_LIMIT 0x1
+/* Non-recycle count */
+#define NON_RECYCLE_COUNT 0x2
+/* Modulo-N */
+#define MODULO_N 0x3
+/* Non-quadrature */
+#define NON_QUADRATURE 0x0
+/* Quadrature X1 */
+#define QUADRATURE_X1 0x1
+/* Quadrature X2 */
+#define QUADRATURE_X2 0x2
+/* Quadrature X4 */
+#define QUADRATURE_X4 0x3
+
+/*
+ * Input/Output Control Register
+ */
+#define AB_GATE BIT(0)
+#define LOAD_PIN BIT(1)
+#define FLG_PINS GENMASK(4, 3)
+/* Disable inputs A and B */
+#define DISABLE_AB u8_encode_bits(0x0, AB_GATE)
+/* Load Counter input */
+#define LOAD_CNTR 0x0
+/* FLG1 = CARRY(active low); FLG2 = BORROW(active low) */
+#define FLG1_CARRY_FLG2_BORROW 0x0
+/* FLG1 = COMPARE(active low); FLG2 = BORROW(active low) */
+#define FLG1_COMPARE_FLG2_BORROW 0x1
+/* FLG1 = Carry(active low)/Borrow(active low); FLG2 = U/D(active low) flag */
+#define FLG1_CARRYBORROW_FLG2_UD 0x2
+/* FLG1 = INDX (low pulse at INDEX pin active level); FLG2 = E flag */
+#define FLG1_INDX_FLG2_E 0x3
+
+/*
+ * INDEX CONTROL REGISTERS
+ */
+#define INDEX_MODE BIT(0)
+#define INDEX_POLARITY BIT(1)
+/* Disable Index mode */
+#define DISABLE_INDEX_MODE 0x0
+/* Enable Index mode */
+#define ENABLE_INDEX_MODE 0x1
+/* Negative Index Polarity */
+#define NEGATIVE_INDEX_POLARITY 0x0
+/* Positive Index Polarity */
+#define POSITIVE_INDEX_POLARITY 0x1
+
+/*
+ * Channel Operation Register
+ */
+#define COUNTERS_OPERATION BIT(0)
+#define INTERRUPT_FUNCTION BIT(2)
+/* Enable all Counters */
+#define ENABLE_COUNTERS u8_encode_bits(0x0, COUNTERS_OPERATION)
+/* Reset all Counters */
+#define RESET_COUNTERS u8_encode_bits(0x1, COUNTERS_OPERATION)
+/* Disable the interrupt function */
+#define DISABLE_INTERRUPT_FUNCTION u8_encode_bits(0x0, INTERRUPT_FUNCTION)
+/* Enable the interrupt function */
+#define ENABLE_INTERRUPT_FUNCTION u8_encode_bits(0x1, INTERRUPT_FUNCTION)
+/* Any write to the Channel Operation register clears any pending interrupts */
+#define CLEAR_PENDING_INTERRUPTS (ENABLE_COUNTERS | ENABLE_INTERRUPT_FUNCTION)
 
 /* Each Counter is 24 bits wide */
 #define LS7267_CNTR_MAX GENMASK(23, 0)
 
+static __always_inline int quad8_control_register_update(struct regmap *const map, u8 *const buf,
+                                                        const size_t channel, const u8 val,
+                                                        const u8 field)
+{
+       u8p_replace_bits(&buf[channel], val, field);
+       return regmap_write(map, QUAD8_CONTROL(channel), buf[channel]);
+}
+
 static int quad8_signal_read(struct counter_device *counter,
                             struct counter_signal *signal,
                             enum counter_signal_level *level)
 {
        const struct quad8 *const priv = counter_priv(counter);
-       unsigned int state;
+       int ret;
 
        /* Only Index signal levels can be read */
        if (signal->id < 16)
                return -EINVAL;
 
-       state = ioread8(&priv->reg->index_input_levels) & BIT(signal->id - 16);
+       ret = regmap_test_bits(priv->map, QUAD8_INDEX_INPUT_LEVELS, BIT(signal->id - 16));
+       if (ret < 0)
+               return ret;
 
-       *level = (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
+       *level = (ret) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
 
        return 0;
 }
@@ -154,65 +236,81 @@ static int quad8_count_read(struct counter_device *counter,
                            struct counter_count *count, u64 *val)
 {
        struct quad8 *const priv = counter_priv(counter);
-       struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
        unsigned long irqflags;
-       int i;
-
-       *val = 0;
+       u8 value[3];
+       int ret;
 
        spin_lock_irqsave(&priv->lock, irqflags);
 
-       /* Reset Byte Pointer; transfer Counter to Output Latch */
-       iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
-                &chan->control);
-
-       for (i = 0; i < 3; i++)
-               *val |= (unsigned long)ioread8(&chan->data) << (8 * i);
+       ret = regmap_write(priv->map, QUAD8_CONTROL(count->id),
+                          SELECT_RLD | RESET_BP | TRANSFER_CNTR_TO_OL);
+       if (ret)
+               goto exit_unlock;
+       ret = regmap_noinc_read(priv->map, QUAD8_DATA(count->id), value, sizeof(value));
 
+exit_unlock:
        spin_unlock_irqrestore(&priv->lock, irqflags);
 
-       return 0;
+       *val = get_unaligned_le24(value);
+
+       return ret;
+}
+
+static int quad8_preset_register_set(struct quad8 *const priv, const size_t id,
+                                    const unsigned long preset)
+{
+       u8 value[3];
+       int ret;
+
+       put_unaligned_le24(preset, value);
+
+       ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BP);
+       if (ret)
+               return ret;
+       return regmap_noinc_write(priv->map, QUAD8_DATA(id), value, sizeof(value));
+}
+
+static int quad8_flag_register_reset(struct quad8 *const priv, const size_t id)
+{
+       int ret;
+
+       ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BT_CT_CPT_S_IDX);
+       if (ret)
+               return ret;
+       return regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_E);
 }
 
 static int quad8_count_write(struct counter_device *counter,
                             struct counter_count *count, u64 val)
 {
        struct quad8 *const priv = counter_priv(counter);
-       struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
        unsigned long irqflags;
-       int i;
+       int ret;
 
        if (val > LS7267_CNTR_MAX)
                return -ERANGE;
 
        spin_lock_irqsave(&priv->lock, irqflags);
 
-       /* Reset Byte Pointer */
-       iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
-
        /* Counter can only be set via Preset Register */
-       for (i = 0; i < 3; i++)
-               iowrite8(val >> (8 * i), &chan->data);
+       ret = quad8_preset_register_set(priv, count->id, val);
+       if (ret)
+               goto exit_unlock;
+       ret = regmap_write(priv->map, QUAD8_CONTROL(count->id), SELECT_RLD | TRANSFER_PR_TO_CNTR);
+       if (ret)
+               goto exit_unlock;
 
-       /* Transfer Preset Register to Counter */
-       iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, &chan->control);
-
-       /* Reset Byte Pointer */
-       iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
+       ret = quad8_flag_register_reset(priv, count->id);
+       if (ret)
+               goto exit_unlock;
 
        /* Set Preset Register back to original value */
-       val = priv->preset[count->id];
-       for (i = 0; i < 3; i++)
-               iowrite8(val >> (8 * i), &chan->data);
-
-       /* Reset Borrow, Carry, Compare, and Sign flags */
-       iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control);
-       /* Reset Error flag */
-       iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control);
+       ret = quad8_preset_register_set(priv, count->id, priv->preset[count->id]);
 
+exit_unlock:
        spin_unlock_irqrestore(&priv->lock, irqflags);
 
-       return 0;
+       return ret;
 }
 
 static const enum counter_function quad8_count_functions_list[] = {
@@ -225,19 +323,17 @@ static const enum counter_function quad8_count_functions_list[] = {
 static int quad8_function_get(const struct quad8 *const priv, const size_t id,
                              enum counter_function *const function)
 {
-       if (!priv->quadrature_mode[id]) {
+       switch (u8_get_bits(priv->cmr[id], QUADRATURE_MODE)) {
+       case NON_QUADRATURE:
                *function = COUNTER_FUNCTION_PULSE_DIRECTION;
                return 0;
-       }
-
-       switch (priv->quadrature_scale[id]) {
-       case 0:
+       case QUADRATURE_X1:
                *function = COUNTER_FUNCTION_QUADRATURE_X1_A;
                return 0;
-       case 1:
+       case QUADRATURE_X2:
                *function = COUNTER_FUNCTION_QUADRATURE_X2_A;
                return 0;
-       case 2:
+       case QUADRATURE_X4:
                *function = COUNTER_FUNCTION_QUADRATURE_X4;
                return 0;
        default:
@@ -269,60 +365,46 @@ static int quad8_function_write(struct counter_device *counter,
 {
        struct quad8 *const priv = counter_priv(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 *const synchronous_mode = priv->synchronous_mode + id;
-       u8 __iomem *const control = &priv->reg->channel[id].control;
        unsigned long irqflags;
        unsigned int mode_cfg;
-       unsigned int idr_cfg;
+       bool synchronous_mode;
+       int ret;
 
-       spin_lock_irqsave(&priv->lock, irqflags);
-
-       mode_cfg = priv->count_mode[id] << 1;
-       idr_cfg = priv->index_polarity[id] << 1;
-
-       if (function == COUNTER_FUNCTION_PULSE_DIRECTION) {
-               *quadrature_mode = 0;
-
-               /* Quadrature scaling only available in quadrature mode */
-               *scale = 0;
+       switch (function) {
+       case COUNTER_FUNCTION_PULSE_DIRECTION:
+               mode_cfg = NON_QUADRATURE;
+               break;
+       case COUNTER_FUNCTION_QUADRATURE_X1_A:
+               mode_cfg = QUADRATURE_X1;
+               break;
+       case COUNTER_FUNCTION_QUADRATURE_X2_A:
+               mode_cfg = QUADRATURE_X2;
+               break;
+       case COUNTER_FUNCTION_QUADRATURE_X4:
+               mode_cfg = QUADRATURE_X4;
+               break;
+       default:
+               /* should never reach this path */
+               return -EINVAL;
+       }
 
-               /* Synchronous function not supported in non-quadrature mode */
-               if (*synchronous_mode) {
-                       *synchronous_mode = 0;
-                       /* Disable synchronous function mode */
-                       iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
-               }
-       } else {
-               *quadrature_mode = 1;
+       spin_lock_irqsave(&priv->lock, irqflags);
 
-               switch (function) {
-               case COUNTER_FUNCTION_QUADRATURE_X1_A:
-                       *scale = 0;
-                       mode_cfg |= QUAD8_CMR_QUADRATURE_X1;
-                       break;
-               case COUNTER_FUNCTION_QUADRATURE_X2_A:
-                       *scale = 1;
-                       mode_cfg |= QUAD8_CMR_QUADRATURE_X2;
-                       break;
-               case COUNTER_FUNCTION_QUADRATURE_X4:
-                       *scale = 2;
-                       mode_cfg |= QUAD8_CMR_QUADRATURE_X4;
-                       break;
-               default:
-                       /* should never reach this path */
-                       spin_unlock_irqrestore(&priv->lock, irqflags);
-                       return -EINVAL;
-               }
+       /* Synchronous function not supported in non-quadrature mode */
+       synchronous_mode = u8_get_bits(priv->idr[id], INDEX_MODE) == ENABLE_INDEX_MODE;
+       if (synchronous_mode && mode_cfg == NON_QUADRATURE) {
+               ret = quad8_control_register_update(priv->map, priv->idr, id, DISABLE_INDEX_MODE,
+                                                   INDEX_MODE);
+               if (ret)
+                       goto exit_unlock;
        }
 
-       /* Load mode configuration to Counter Mode Register */
-       iowrite8(QUAD8_CTR_CMR | mode_cfg, control);
+       ret = quad8_control_register_update(priv->map, priv->cmr, id, mode_cfg, QUADRATURE_MODE);
 
+exit_unlock:
        spin_unlock_irqrestore(&priv->lock, irqflags);
 
-       return 0;
+       return ret;
 }
 
 static int quad8_direction_read(struct counter_device *counter,
@@ -330,13 +412,13 @@ static int quad8_direction_read(struct counter_device *counter,
                                enum counter_count_direction *direction)
 {
        const struct quad8 *const priv = counter_priv(counter);
-       unsigned int ud_flag;
-       u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control;
-
-       /* U/D flag: nonzero = up, zero = down */
-       ud_flag = ioread8(flag_addr) & QUAD8_FLAG_UD;
+       unsigned int flag;
+       int ret;
 
-       *direction = (ud_flag) ? COUNTER_COUNT_DIRECTION_FORWARD :
+       ret = regmap_read(priv->map, QUAD8_CONTROL(count->id), &flag);
+       if (ret)
+               return ret;
+       *direction = (u8_get_bits(flag, FLAG_UD) == UP) ? COUNTER_COUNT_DIRECTION_FORWARD :
                COUNTER_COUNT_DIRECTION_BACKWARD;
 
        return 0;
@@ -366,13 +448,13 @@ static int quad8_action_read(struct counter_device *counter,
        const size_t signal_a_id = count->synapses[0].signal->id;
        enum counter_count_direction direction;
 
+       /* Default action mode */
+       *action = COUNTER_SYNAPSE_ACTION_NONE;
+
        /* Handle Index signals */
        if (synapse->signal->id >= 16) {
-               if (!priv->preset_enable[count->id])
+               if (u8_get_bits(priv->ior[count->id], LOAD_PIN) == LOAD_CNTR)
                        *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
-               else
-                       *action = COUNTER_SYNAPSE_ACTION_NONE;
-
                return 0;
        }
 
@@ -392,9 +474,6 @@ static int quad8_action_read(struct counter_device *counter,
 
        spin_unlock_irqrestore(&priv->lock, irqflags);
 
-       /* Default action mode */
-       *action = COUNTER_SYNAPSE_ACTION_NONE;
-
        /* Determine action mode based on current count function mode */
        switch (function) {
        case COUNTER_FUNCTION_PULSE_DIRECTION:
@@ -422,67 +501,57 @@ static int quad8_action_read(struct counter_device *counter,
        }
 }
 
-enum {
-       QUAD8_EVENT_CARRY = 0,
-       QUAD8_EVENT_COMPARE = 1,
-       QUAD8_EVENT_CARRY_BORROW = 2,
-       QUAD8_EVENT_INDEX = 3,
-};
-
 static int quad8_events_configure(struct counter_device *counter)
 {
        struct quad8 *const priv = counter_priv(counter);
        unsigned long irq_enabled = 0;
        unsigned long irqflags;
        struct counter_event_node *event_node;
-       unsigned int next_irq_trigger;
-       unsigned long ior_cfg;
+       u8 flg_pins;
+       int ret;
 
        spin_lock_irqsave(&priv->lock, irqflags);
 
        list_for_each_entry(event_node, &counter->events_list, l) {
                switch (event_node->event) {
                case COUNTER_EVENT_OVERFLOW:
-                       next_irq_trigger = QUAD8_EVENT_CARRY;
+                       flg_pins = FLG1_CARRY_FLG2_BORROW;
                        break;
                case COUNTER_EVENT_THRESHOLD:
-                       next_irq_trigger = QUAD8_EVENT_COMPARE;
+                       flg_pins = FLG1_COMPARE_FLG2_BORROW;
                        break;
                case COUNTER_EVENT_OVERFLOW_UNDERFLOW:
-                       next_irq_trigger = QUAD8_EVENT_CARRY_BORROW;
+                       flg_pins = FLG1_CARRYBORROW_FLG2_UD;
                        break;
                case COUNTER_EVENT_INDEX:
-                       next_irq_trigger = QUAD8_EVENT_INDEX;
+                       flg_pins = FLG1_INDX_FLG2_E;
                        break;
                default:
                        /* should never reach this path */
-                       spin_unlock_irqrestore(&priv->lock, irqflags);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto exit_unlock;
                }
 
                /* Enable IRQ line */
                irq_enabled |= BIT(event_node->channel);
 
                /* Skip configuration if it is the same as previously set */
-               if (priv->irq_trigger[event_node->channel] == next_irq_trigger)
+               if (flg_pins == u8_get_bits(priv->ior[event_node->channel], FLG_PINS))
                        continue;
 
                /* Save new IRQ function configuration */
-               priv->irq_trigger[event_node->channel] = next_irq_trigger;
-
-               /* Load configuration to I/O Control Register */
-               ior_cfg = priv->ab_enable[event_node->channel] |
-                         priv->preset_enable[event_node->channel] << 1 |
-                         priv->irq_trigger[event_node->channel] << 3;
-               iowrite8(QUAD8_CTR_IOR | ior_cfg,
-                        &priv->reg->channel[event_node->channel].control);
+               ret = quad8_control_register_update(priv->map, priv->ior, event_node->channel,
+                                                   flg_pins, FLG_PINS);
+               if (ret)
+                       goto exit_unlock;
        }
 
-       iowrite8(irq_enabled, &priv->reg->index_interrupt);
+       ret = regmap_write(priv->map, QUAD8_INDEX_INTERRUPT, irq_enabled);
 
+exit_unlock:
        spin_unlock_irqrestore(&priv->lock, irqflags);
 
-       return 0;
+       return ret;
 }
 
 static int quad8_watch_validate(struct counter_device *counter,
@@ -531,7 +600,7 @@ static int quad8_index_polarity_get(struct counter_device *counter,
        const struct quad8 *const priv = counter_priv(counter);
        const size_t channel_id = signal->id - 16;
 
-       *index_polarity = priv->index_polarity[channel_id];
+       *index_polarity = u8_get_bits(priv->idr[channel_id], INDEX_POLARITY);
 
        return 0;
 }
@@ -542,22 +611,17 @@ static int quad8_index_polarity_set(struct counter_device *counter,
 {
        struct quad8 *const priv = counter_priv(counter);
        const size_t channel_id = signal->id - 16;
-       u8 __iomem *const control = &priv->reg->channel[channel_id].control;
        unsigned long irqflags;
-       unsigned int idr_cfg = index_polarity << 1;
+       int ret;
 
        spin_lock_irqsave(&priv->lock, irqflags);
 
-       idr_cfg |= priv->synchronous_mode[channel_id];
-
-       priv->index_polarity[channel_id] = index_polarity;
-
-       /* Load Index Control configuration to Index Control Register */
-       iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
+       ret = quad8_control_register_update(priv->map, priv->idr, channel_id, index_polarity,
+                                           INDEX_POLARITY);
 
        spin_unlock_irqrestore(&priv->lock, irqflags);
 
-       return 0;
+       return ret;
 }
 
 static int quad8_polarity_read(struct counter_device *counter,
@@ -571,7 +635,7 @@ static int quad8_polarity_read(struct counter_device *counter,
        if (err)
                return err;
 
-       *polarity = (index_polarity) ? COUNTER_SIGNAL_POLARITY_POSITIVE :
+       *polarity = (index_polarity == POSITIVE_INDEX_POLARITY) ? COUNTER_SIGNAL_POLARITY_POSITIVE :
                COUNTER_SIGNAL_POLARITY_NEGATIVE;
 
        return 0;
@@ -581,7 +645,8 @@ static int quad8_polarity_write(struct counter_device *counter,
                                struct counter_signal *signal,
                                enum counter_signal_polarity polarity)
 {
-       const u32 pol = (polarity == COUNTER_SIGNAL_POLARITY_POSITIVE) ? 1 : 0;
+       const u32 pol = (polarity == COUNTER_SIGNAL_POLARITY_POSITIVE) ? POSITIVE_INDEX_POLARITY :
+                                                                        NEGATIVE_INDEX_POLARITY;
 
        return quad8_index_polarity_set(counter, signal, pol);
 }
@@ -598,7 +663,7 @@ static int quad8_synchronous_mode_get(struct counter_device *counter,
        const struct quad8 *const priv = counter_priv(counter);
        const size_t channel_id = signal->id - 16;
 
-       *synchronous_mode = priv->synchronous_mode[channel_id];
+       *synchronous_mode = u8_get_bits(priv->idr[channel_id], INDEX_MODE);
 
        return 0;
 }
@@ -609,28 +674,26 @@ static int quad8_synchronous_mode_set(struct counter_device *counter,
 {
        struct quad8 *const priv = counter_priv(counter);
        const size_t channel_id = signal->id - 16;
-       u8 __iomem *const control = &priv->reg->channel[channel_id].control;
+       u8 quadrature_mode;
        unsigned long irqflags;
-       unsigned int idr_cfg = synchronous_mode;
+       int ret;
 
        spin_lock_irqsave(&priv->lock, irqflags);
 
-       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]) {
-               spin_unlock_irqrestore(&priv->lock, irqflags);
-               return -EINVAL;
+       quadrature_mode = u8_get_bits(priv->idr[channel_id], QUADRATURE_MODE);
+       if (synchronous_mode && quadrature_mode == NON_QUADRATURE) {
+               ret = -EINVAL;
+               goto exit_unlock;
        }
 
-       priv->synchronous_mode[channel_id] = synchronous_mode;
-
-       /* Load Index Control configuration to Index Control Register */
-       iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
+       ret = quad8_control_register_update(priv->map, priv->idr, channel_id, synchronous_mode,
+                                           INDEX_MODE);
 
+exit_unlock:
        spin_unlock_irqrestore(&priv->lock, irqflags);
 
-       return 0;
+       return ret;
 }
 
 static int quad8_count_floor_read(struct counter_device *counter,
@@ -648,18 +711,17 @@ static int quad8_count_mode_read(struct counter_device *counter,
 {
        const struct quad8 *const priv = counter_priv(counter);
 
-       /* Map 104-QUAD-8 count mode to Generic Counter count mode */
-       switch (priv->count_mode[count->id]) {
-       case 0:
+       switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) {
+       case NORMAL_COUNT:
                *cnt_mode = COUNTER_COUNT_MODE_NORMAL;
                break;
-       case 1:
+       case RANGE_LIMIT:
                *cnt_mode = COUNTER_COUNT_MODE_RANGE_LIMIT;
                break;
-       case 2:
+       case NON_RECYCLE_COUNT:
                *cnt_mode = COUNTER_COUNT_MODE_NON_RECYCLE;
                break;
-       case 3:
+       case MODULO_N:
                *cnt_mode = COUNTER_COUNT_MODE_MODULO_N;
                break;
        }
@@ -673,23 +735,21 @@ static int quad8_count_mode_write(struct counter_device *counter,
 {
        struct quad8 *const priv = counter_priv(counter);
        unsigned int count_mode;
-       unsigned int mode_cfg;
-       u8 __iomem *const control = &priv->reg->channel[count->id].control;
        unsigned long irqflags;
+       int ret;
 
-       /* Map Generic Counter count mode to 104-QUAD-8 count mode */
        switch (cnt_mode) {
        case COUNTER_COUNT_MODE_NORMAL:
-               count_mode = 0;
+               count_mode = NORMAL_COUNT;
                break;
        case COUNTER_COUNT_MODE_RANGE_LIMIT:
-               count_mode = 1;
+               count_mode = RANGE_LIMIT;
                break;
        case COUNTER_COUNT_MODE_NON_RECYCLE:
-               count_mode = 2;
+               count_mode = NON_RECYCLE_COUNT;
                break;
        case COUNTER_COUNT_MODE_MODULO_N:
-               count_mode = 3;
+               count_mode = MODULO_N;
                break;
        default:
                /* should never reach this path */
@@ -698,21 +758,12 @@ static int quad8_count_mode_write(struct counter_device *counter,
 
        spin_lock_irqsave(&priv->lock, irqflags);
 
-       priv->count_mode[count->id] = count_mode;
-
-       /* Set count mode configuration value */
-       mode_cfg = count_mode << 1;
-
-       /* Add quadrature mode configuration */
-       if (priv->quadrature_mode[count->id])
-               mode_cfg |= (priv->quadrature_scale[count->id] + 1) << 3;
-
-       /* Load mode configuration to Counter Mode Register */
-       iowrite8(QUAD8_CTR_CMR | mode_cfg, control);
+       ret = quad8_control_register_update(priv->map, priv->cmr, count->id, count_mode,
+                                           COUNT_MODE);
 
        spin_unlock_irqrestore(&priv->lock, irqflags);
 
-       return 0;
+       return ret;
 }
 
 static int quad8_count_enable_read(struct counter_device *counter,
@@ -720,7 +771,7 @@ static int quad8_count_enable_read(struct counter_device *counter,
 {
        const struct quad8 *const priv = counter_priv(counter);
 
-       *enable = priv->ab_enable[count->id];
+       *enable = u8_get_bits(priv->ior[count->id], AB_GATE);
 
        return 0;
 }
@@ -729,23 +780,16 @@ static int quad8_count_enable_write(struct counter_device *counter,
                                    struct counter_count *count, u8 enable)
 {
        struct quad8 *const priv = counter_priv(counter);
-       u8 __iomem *const control = &priv->reg->channel[count->id].control;
        unsigned long irqflags;
-       unsigned int ior_cfg;
+       int ret;
 
        spin_lock_irqsave(&priv->lock, irqflags);
 
-       priv->ab_enable[count->id] = enable;
-
-       ior_cfg = enable | priv->preset_enable[count->id] << 1 |
-                 priv->irq_trigger[count->id] << 3;
-
-       /* Load I/O control configuration */
-       iowrite8(QUAD8_CTR_IOR | ior_cfg, control);
+       ret = quad8_control_register_update(priv->map, priv->ior, count->id, enable, AB_GATE);
 
        spin_unlock_irqrestore(&priv->lock, irqflags);
 
-       return 0;
+       return ret;
 }
 
 static const char *const quad8_noise_error_states[] = {
@@ -757,9 +801,13 @@ static int quad8_error_noise_get(struct counter_device *counter,
                                 struct counter_count *count, u32 *noise_error)
 {
        const struct quad8 *const priv = counter_priv(counter);
-       u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control;
+       unsigned int flag;
+       int ret;
 
-       *noise_error = !!(ioread8(flag_addr) & QUAD8_FLAG_E);
+       ret = regmap_read(priv->map, QUAD8_CONTROL(count->id), &flag);
+       if (ret)
+               return ret;
+       *noise_error = u8_get_bits(flag, FLAG_E);
 
        return 0;
 }
@@ -774,38 +822,24 @@ static int quad8_count_preset_read(struct counter_device *counter,
        return 0;
 }
 
-static void quad8_preset_register_set(struct quad8 *const priv, const int id,
-                                     const unsigned int preset)
-{
-       struct channel_reg __iomem *const chan = priv->reg->channel + id;
-       int i;
-
-       priv->preset[id] = preset;
-
-       /* Reset Byte Pointer */
-       iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
-
-       /* Set Preset Register */
-       for (i = 0; i < 3; i++)
-               iowrite8(preset >> (8 * i), &chan->data);
-}
-
 static int quad8_count_preset_write(struct counter_device *counter,
                                    struct counter_count *count, u64 preset)
 {
        struct quad8 *const priv = counter_priv(counter);
        unsigned long irqflags;
+       int ret;
 
        if (preset > LS7267_CNTR_MAX)
                return -ERANGE;
 
        spin_lock_irqsave(&priv->lock, irqflags);
 
-       quad8_preset_register_set(priv, count->id, preset);
+       priv->preset[count->id] = preset;
+       ret = quad8_preset_register_set(priv, count->id, preset);
 
        spin_unlock_irqrestore(&priv->lock, irqflags);
 
-       return 0;
+       return ret;
 }
 
 static int quad8_count_ceiling_read(struct counter_device *counter,
@@ -817,9 +851,9 @@ static int quad8_count_ceiling_read(struct counter_device *counter,
        spin_lock_irqsave(&priv->lock, irqflags);
 
        /* Range Limit and Modulo-N count modes use preset value as ceiling */
-       switch (priv->count_mode[count->id]) {
-       case 1:
-       case 3:
+       switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) {
+       case RANGE_LIMIT:
+       case MODULO_N:
                *ceiling = priv->preset[count->id];
                break;
        default:
@@ -837,6 +871,7 @@ static int quad8_count_ceiling_write(struct counter_device *counter,
 {
        struct quad8 *const priv = counter_priv(counter);
        unsigned long irqflags;
+       int ret;
 
        if (ceiling > LS7267_CNTR_MAX)
                return -ERANGE;
@@ -844,17 +879,20 @@ static int quad8_count_ceiling_write(struct counter_device *counter,
        spin_lock_irqsave(&priv->lock, irqflags);
 
        /* Range Limit and Modulo-N count modes use preset value as ceiling */
-       switch (priv->count_mode[count->id]) {
-       case 1:
-       case 3:
-               quad8_preset_register_set(priv, count->id, ceiling);
-               spin_unlock_irqrestore(&priv->lock, irqflags);
-               return 0;
+       switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) {
+       case RANGE_LIMIT:
+       case MODULO_N:
+               priv->preset[count->id] = ceiling;
+               ret = quad8_preset_register_set(priv, count->id, ceiling);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
        }
 
        spin_unlock_irqrestore(&priv->lock, irqflags);
 
-       return -EINVAL;
+       return ret;
 }
 
 static int quad8_count_preset_enable_read(struct counter_device *counter,
@@ -863,7 +901,8 @@ static int quad8_count_preset_enable_read(struct counter_device *counter,
 {
        const struct quad8 *const priv = counter_priv(counter);
 
-       *preset_enable = !priv->preset_enable[count->id];
+       /* Preset enable is active low in Input/Output Control register */
+       *preset_enable = !u8_get_bits(priv->ior[count->id], LOAD_PIN);
 
        return 0;
 }
@@ -873,26 +912,18 @@ static int quad8_count_preset_enable_write(struct counter_device *counter,
                                           u8 preset_enable)
 {
        struct quad8 *const priv = counter_priv(counter);
-       u8 __iomem *const control = &priv->reg->channel[count->id].control;
        unsigned long irqflags;
-       unsigned int ior_cfg;
-
-       /* Preset enable is active low in Input/Output Control register */
-       preset_enable = !preset_enable;
+       int ret;
 
        spin_lock_irqsave(&priv->lock, irqflags);
 
-       priv->preset_enable[count->id] = preset_enable;
-
-       ior_cfg = priv->ab_enable[count->id] | preset_enable << 1 |
-                 priv->irq_trigger[count->id] << 3;
-
-       /* Load I/O control configuration to Input / Output Control Register */
-       iowrite8(QUAD8_CTR_IOR | ior_cfg, control);
+       /* Preset enable is active low in Input/Output Control register */
+       ret = quad8_control_register_update(priv->map, priv->ior, count->id, !preset_enable,
+                                           LOAD_PIN);
 
        spin_unlock_irqrestore(&priv->lock, irqflags);
 
-       return 0;
+       return ret;
 }
 
 static int quad8_signal_cable_fault_read(struct counter_device *counter,
@@ -903,7 +934,7 @@ static int quad8_signal_cable_fault_read(struct counter_device *counter,
        const size_t channel_id = signal->id / 2;
        unsigned long irqflags;
        bool disabled;
-       unsigned int status;
+       int ret;
 
        spin_lock_irqsave(&priv->lock, irqflags);
 
@@ -914,13 +945,16 @@ static int quad8_signal_cable_fault_read(struct counter_device *counter,
                return -EINVAL;
        }
 
-       /* Logic 0 = cable fault */
-       status = ioread8(&priv->reg->cable_status);
+       ret = regmap_test_bits(priv->map, QUAD8_CABLE_STATUS, BIT(channel_id));
+       if (ret < 0) {
+               spin_unlock_irqrestore(&priv->lock, irqflags);
+               return ret;
+       }
 
        spin_unlock_irqrestore(&priv->lock, irqflags);
 
-       /* Mask respective channel and invert logic */
-       *cable_fault = !(status & BIT(channel_id));
+       /* Logic 0 = cable fault */
+       *cable_fault = !ret;
 
        return 0;
 }
@@ -945,6 +979,7 @@ static int quad8_signal_cable_fault_enable_write(struct counter_device *counter,
        const size_t channel_id = signal->id / 2;
        unsigned long irqflags;
        unsigned int cable_fault_enable;
+       int ret;
 
        spin_lock_irqsave(&priv->lock, irqflags);
 
@@ -956,11 +991,11 @@ static int quad8_signal_cable_fault_enable_write(struct counter_device *counter,
        /* Enable is active low in Differential Encoder Cable Status register */
        cable_fault_enable = ~priv->cable_fault_enable;
 
-       iowrite8(cable_fault_enable, &priv->reg->cable_status);
+       ret = regmap_write(priv->map, QUAD8_CABLE_STATUS, cable_fault_enable);
 
        spin_unlock_irqrestore(&priv->lock, irqflags);
 
-       return 0;
+       return ret;
 }
 
 static int quad8_signal_fck_prescaler_read(struct counter_device *counter,
@@ -974,30 +1009,37 @@ static int quad8_signal_fck_prescaler_read(struct counter_device *counter,
        return 0;
 }
 
+static int quad8_filter_clock_prescaler_set(struct quad8 *const priv, const size_t id,
+                                           const u8 prescaler)
+{
+       int ret;
+
+       ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BP);
+       if (ret)
+               return ret;
+       ret = regmap_write(priv->map, QUAD8_DATA(id), prescaler);
+       if (ret)
+               return ret;
+       return regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | TRANSFER_PR0_TO_PSC);
+}
+
 static int quad8_signal_fck_prescaler_write(struct counter_device *counter,
                                            struct counter_signal *signal,
                                            u8 prescaler)
 {
        struct quad8 *const priv = counter_priv(counter);
        const size_t channel_id = signal->id / 2;
-       struct channel_reg __iomem *const chan = priv->reg->channel + channel_id;
        unsigned long irqflags;
+       int ret;
 
        spin_lock_irqsave(&priv->lock, irqflags);
 
        priv->fck_prescaler[channel_id] = prescaler;
-
-       /* Reset Byte Pointer */
-       iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
-
-       /* Set filter clock factor */
-       iowrite8(prescaler, &chan->data);
-       iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
-                &chan->control);
+       ret = quad8_filter_clock_prescaler_set(priv, channel_id, prescaler);
 
        spin_unlock_irqrestore(&priv->lock, irqflags);
 
-       return 0;
+       return ret;
 }
 
 static struct counter_comp quad8_signal_ext[] = {
@@ -1150,77 +1192,93 @@ static irqreturn_t quad8_irq_handler(int irq, void *private)
 {
        struct counter_device *counter = private;
        struct quad8 *const priv = counter_priv(counter);
+       unsigned int status;
        unsigned long irq_status;
        unsigned long channel;
+       unsigned int flg_pins;
        u8 event;
+       int ret;
 
-       irq_status = ioread8(&priv->reg->interrupt_status);
-       if (!irq_status)
+       ret = regmap_read(priv->map, QUAD8_INTERRUPT_STATUS, &status);
+       if (ret)
+               return ret;
+       if (!status)
                return IRQ_NONE;
 
+       irq_status = status;
        for_each_set_bit(channel, &irq_status, QUAD8_NUM_COUNTERS) {
-               switch (priv->irq_trigger[channel]) {
-               case QUAD8_EVENT_CARRY:
+               flg_pins = u8_get_bits(priv->ior[channel], FLG_PINS);
+               switch (flg_pins) {
+               case FLG1_CARRY_FLG2_BORROW:
                        event = COUNTER_EVENT_OVERFLOW;
                                break;
-               case QUAD8_EVENT_COMPARE:
+               case FLG1_COMPARE_FLG2_BORROW:
                        event = COUNTER_EVENT_THRESHOLD;
                                break;
-               case QUAD8_EVENT_CARRY_BORROW:
+               case FLG1_CARRYBORROW_FLG2_UD:
                        event = COUNTER_EVENT_OVERFLOW_UNDERFLOW;
                                break;
-               case QUAD8_EVENT_INDEX:
+               case FLG1_INDX_FLG2_E:
                        event = COUNTER_EVENT_INDEX;
                                break;
                default:
                        /* should never reach this path */
                        WARN_ONCE(true, "invalid interrupt trigger function %u configured for channel %lu\n",
-                                 priv->irq_trigger[channel], channel);
+                                 flg_pins, channel);
                        continue;
                }
 
                counter_push_event(counter, event, channel);
        }
 
-       /* Clear pending interrupts on device */
-       iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper);
+       ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION, CLEAR_PENDING_INTERRUPTS);
+       if (ret)
+               return ret;
 
        return IRQ_HANDLED;
 }
 
-static void quad8_init_counter(struct channel_reg __iomem *const chan)
+static int quad8_init_counter(struct quad8 *const priv, const size_t channel)
 {
-       unsigned long i;
+       int ret;
+
+       ret = quad8_filter_clock_prescaler_set(priv, channel, 0);
+       if (ret)
+               return ret;
+       ret = quad8_preset_register_set(priv, channel, 0);
+       if (ret)
+               return ret;
+       ret = quad8_flag_register_reset(priv, channel);
+       if (ret)
+               return ret;
 
-       /* Reset Byte Pointer */
-       iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
-       /* Reset filter clock factor */
-       iowrite8(0, &chan->data);
-       iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
-                &chan->control);
-       /* Reset Byte Pointer */
-       iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
-       /* Reset Preset Register */
-       for (i = 0; i < 3; i++)
-               iowrite8(0x00, &chan->data);
-       /* Reset Borrow, Carry, Compare, and Sign flags */
-       iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control);
-       /* Reset Error flag */
-       iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control);
        /* Binary encoding; Normal count; non-quadrature mode */
-       iowrite8(QUAD8_CTR_CMR, &chan->control);
+       priv->cmr[channel] = SELECT_CMR | BINARY | u8_encode_bits(NORMAL_COUNT, COUNT_MODE) |
+                            u8_encode_bits(NON_QUADRATURE, QUADRATURE_MODE);
+       ret = regmap_write(priv->map, QUAD8_CONTROL(channel), priv->cmr[channel]);
+       if (ret)
+               return ret;
+
        /* Disable A and B inputs; preset on index; FLG1 as Carry */
-       iowrite8(QUAD8_CTR_IOR, &chan->control);
+       priv->ior[channel] = SELECT_IOR | DISABLE_AB | u8_encode_bits(LOAD_CNTR, LOAD_PIN) |
+                            u8_encode_bits(FLG1_CARRY_FLG2_BORROW, FLG_PINS);
+       ret = regmap_write(priv->map, QUAD8_CONTROL(channel), priv->ior[channel]);
+       if (ret)
+               return ret;
+
        /* Disable index function; negative index polarity */
-       iowrite8(QUAD8_CTR_IDR, &chan->control);
+       priv->idr[channel] = SELECT_IDR | u8_encode_bits(DISABLE_INDEX_MODE, INDEX_MODE) |
+                            u8_encode_bits(NEGATIVE_INDEX_POLARITY, INDEX_POLARITY);
+       return regmap_write(priv->map, QUAD8_CONTROL(channel), priv->idr[channel]);
 }
 
 static int quad8_probe(struct device *dev, unsigned int id)
 {
        struct counter_device *counter;
        struct quad8 *priv;
+       void __iomem *regs;
        unsigned long i;
-       int err;
+       int ret;
 
        if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) {
                dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
@@ -1233,10 +1291,15 @@ static int quad8_probe(struct device *dev, unsigned int id)
                return -ENOMEM;
        priv = counter_priv(counter);
 
-       priv->reg = devm_ioport_map(dev, base[id], QUAD8_EXTENT);
-       if (!priv->reg)
+       regs = devm_ioport_map(dev, base[id], QUAD8_EXTENT);
+       if (!regs)
                return -ENOMEM;
 
+       priv->map = devm_regmap_init_mmio(dev, regs, &quad8_regmap_config);
+       if (IS_ERR(priv->map))
+               return dev_err_probe(dev, PTR_ERR(priv->map),
+                                    "Unable to initialize register map\n");
+
        /* Initialize Counter device and driver data */
        counter->name = dev_name(dev);
        counter->parent = dev;
@@ -1249,25 +1312,38 @@ static int quad8_probe(struct device *dev, unsigned int id)
        spin_lock_init(&priv->lock);
 
        /* Reset Index/Interrupt Register */
-       iowrite8(0x00, &priv->reg->index_interrupt);
+       ret = regmap_write(priv->map, QUAD8_INDEX_INTERRUPT, 0x00);
+       if (ret)
+               return ret;
        /* Reset all counters and disable interrupt function */
-       iowrite8(QUAD8_CHAN_OP_RESET_COUNTERS, &priv->reg->channel_oper);
+       ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION,
+                          RESET_COUNTERS | DISABLE_INTERRUPT_FUNCTION);
+       if (ret)
+               return ret;
        /* Set initial configuration for all counters */
-       for (i = 0; i < QUAD8_NUM_COUNTERS; i++)
-               quad8_init_counter(priv->reg->channel + i);
+       for (i = 0; i < QUAD8_NUM_COUNTERS; i++) {
+               ret = quad8_init_counter(priv, i);
+               if (ret)
+                       return ret;
+       }
        /* Disable Differential Encoder Cable Status for all channels */
-       iowrite8(0xFF, &priv->reg->cable_status);
+       ret = regmap_write(priv->map, QUAD8_CABLE_STATUS, GENMASK(7, 0));
+       if (ret)
+               return ret;
        /* Enable all counters and enable interrupt function */
-       iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper);
+       ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION,
+                          ENABLE_COUNTERS | ENABLE_INTERRUPT_FUNCTION);
+       if (ret)
+               return ret;
 
-       err = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler,
+       ret = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler,
                               IRQF_SHARED, counter->name, counter);
-       if (err)
-               return err;
+       if (ret)
+               return ret;
 
-       err = devm_counter_add(dev, counter);
-       if (err < 0)
-               return dev_err_probe(dev, err, "Failed to add counter\n");
+       ret = devm_counter_add(dev, counter);
+       if (ret < 0)
+               return dev_err_probe(dev, ret, "Failed to add counter\n");
 
        return 0;
 }
index 4228be917038dec3ab3cd3ffe42c719c038b99b1..bca21df5116865b5fe8138c54f7003211c4ed8e2 100644 (file)
@@ -10,20 +10,37 @@ menuconfig COUNTER
          interface. You only need to enable this, if you also want to enable
          one or more of the counter device drivers below.
 
+config I8254
+       tristate
+       select COUNTER
+       select REGMAP
+       help
+         Enables support for the i8254 interface library functions. The i8254
+         interface library provides functions to facilitate communication with
+         interfaces compatible with the venerable Intel 8254 Programmable
+         Interval Timer (PIT). The Intel 825x family of chips was first
+         released in the early 1980s but compatible interfaces are nowadays
+         typically found embedded in larger VLSI processing chips and FPGA
+         components.
+
+         If built as a module its name will be i8254.
+
 if COUNTER
 
 config 104_QUAD_8
        tristate "ACCES 104-QUAD-8 driver"
        depends on (PC104 && X86) || COMPILE_TEST
+       depends on HAS_IOPORT_MAP
        select ISA_BUS_API
+       select REGMAP_MMIO
        help
          Say yes here to build support for the ACCES 104-QUAD-8 quadrature
          encoder counter/interface device family (104-QUAD-8, 104-QUAD-4).
 
          A counter's respective error flag may be cleared by performing a write
-         operation on the respective count value attribute. Although the
-         104-QUAD-8 counters have a 25-bit range, only the lower 24 bits may be
-         set, either directly or via the counter's preset attribute.
+         operation on the respective count value attribute. The 104-QUAD-8
+         counters may be set either directly or via the counter's preset
+         attribute.
 
          The base port addresses for the devices may be configured via the base
          array module parameter. The interrupt line numbers for the devices may
index 933fdd50b3e4cf7ee6e745e4ebebede77b28c317..fa3c1d08f7068835aa912aa13bc92bcfd44d16fb 100644 (file)
@@ -6,6 +6,7 @@
 obj-$(CONFIG_COUNTER) += counter.o
 counter-y := counter-core.o counter-sysfs.o counter-chrdev.o
 
+obj-$(CONFIG_I8254)            += i8254.o
 obj-$(CONFIG_104_QUAD_8)       += 104-quad-8.o
 obj-$(CONFIG_INTERRUPT_CNT)            += interrupt-cnt.o
 obj-$(CONFIG_RZ_MTU3_CNT)      += rz-mtu3-cnt.o
index b9efe66f9f8d86fb8e337a3d7ca285d0d9e39bbc..42c523343d32870834e29ef5b507eacdae00e302 100644 (file)
@@ -88,7 +88,13 @@ static const char *const counter_count_mode_str[] = {
        [COUNTER_COUNT_MODE_NORMAL] = "normal",
        [COUNTER_COUNT_MODE_RANGE_LIMIT] = "range limit",
        [COUNTER_COUNT_MODE_NON_RECYCLE] = "non-recycle",
-       [COUNTER_COUNT_MODE_MODULO_N] = "modulo-n"
+       [COUNTER_COUNT_MODE_MODULO_N] = "modulo-n",
+       [COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT] = "interrupt on terminal count",
+       [COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT] = "hardware retriggerable one-shot",
+       [COUNTER_COUNT_MODE_RATE_GENERATOR] = "rate generator",
+       [COUNTER_COUNT_MODE_SQUARE_WAVE_MODE] = "square wave mode",
+       [COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE] = "software triggered strobe",
+       [COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE] = "hardware triggered strobe",
 };
 
 static const char *const counter_signal_polarity_str[] = {
diff --git a/drivers/counter/i8254.c b/drivers/counter/i8254.c
new file mode 100644 (file)
index 0000000..c41e4fd
--- /dev/null
@@ -0,0 +1,447 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel 8254 Programmable Interval Timer
+ * Copyright (C) William Breathitt Gray
+ */
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/counter.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/i8254.h>
+#include <linux/limits.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+
+#include <asm/unaligned.h>
+
+#define I8254_COUNTER_REG(_counter) (_counter)
+#define I8254_CONTROL_REG 0x3
+
+#define I8254_SC GENMASK(7, 6)
+#define I8254_RW GENMASK(5, 4)
+#define I8254_M GENMASK(3, 1)
+#define I8254_CONTROL(_sc, _rw, _m) \
+       (u8_encode_bits(_sc, I8254_SC) | u8_encode_bits(_rw, I8254_RW) | \
+        u8_encode_bits(_m, I8254_M))
+
+#define I8254_RW_TWO_BYTE 0x3
+#define I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT 0
+#define I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT 1
+#define I8254_MODE_RATE_GENERATOR 2
+#define I8254_MODE_SQUARE_WAVE_MODE 3
+#define I8254_MODE_SOFTWARE_TRIGGERED_STROBE 4
+#define I8254_MODE_HARDWARE_TRIGGERED_STROBE 5
+
+#define I8254_COUNTER_LATCH(_counter) I8254_CONTROL(_counter, 0x0, 0x0)
+#define I8254_PROGRAM_COUNTER(_counter, _mode) I8254_CONTROL(_counter, I8254_RW_TWO_BYTE, _mode)
+
+#define I8254_NUM_COUNTERS 3
+
+/**
+ * struct i8254 - I8254 device private data structure
+ * @lock:      synchronization lock to prevent I/O race conditions
+ * @preset:    array of Counter Register states
+ * @out_mode:  array of mode configuration states
+ * @map:       Regmap for the device
+ */
+struct i8254 {
+       struct mutex lock;
+       u16 preset[I8254_NUM_COUNTERS];
+       u8 out_mode[I8254_NUM_COUNTERS];
+       struct regmap *map;
+};
+
+static int i8254_count_read(struct counter_device *const counter, struct counter_count *const count,
+                           u64 *const val)
+{
+       struct i8254 *const priv = counter_priv(counter);
+       int ret;
+       u8 value[2];
+
+       mutex_lock(&priv->lock);
+
+       ret = regmap_write(priv->map, I8254_CONTROL_REG, I8254_COUNTER_LATCH(count->id));
+       if (ret) {
+               mutex_unlock(&priv->lock);
+               return ret;
+       }
+       ret = regmap_noinc_read(priv->map, I8254_COUNTER_REG(count->id), value, sizeof(value));
+       if (ret) {
+               mutex_unlock(&priv->lock);
+               return ret;
+       }
+
+       mutex_unlock(&priv->lock);
+
+       *val = get_unaligned_le16(value);
+
+       return ret;
+}
+
+static int i8254_function_read(struct counter_device *const counter,
+                              struct counter_count *const count,
+                              enum counter_function *const function)
+{
+       *function = COUNTER_FUNCTION_DECREASE;
+       return 0;
+}
+
+#define I8254_SYNAPSES_PER_COUNT 2
+#define I8254_SIGNAL_ID_CLK 0
+#define I8254_SIGNAL_ID_GATE 1
+
+static int i8254_action_read(struct counter_device *const counter,
+                            struct counter_count *const count,
+                            struct counter_synapse *const synapse,
+                            enum counter_synapse_action *const action)
+{
+       struct i8254 *const priv = counter_priv(counter);
+
+       switch (synapse->signal->id % I8254_SYNAPSES_PER_COUNT) {
+       case I8254_SIGNAL_ID_CLK:
+               *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE;
+               return 0;
+       case I8254_SIGNAL_ID_GATE:
+               switch (priv->out_mode[count->id]) {
+               case I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT:
+               case I8254_MODE_RATE_GENERATOR:
+               case I8254_MODE_SQUARE_WAVE_MODE:
+               case I8254_MODE_HARDWARE_TRIGGERED_STROBE:
+                       *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
+                       return 0;
+               default:
+                       *action = COUNTER_SYNAPSE_ACTION_NONE;
+                       return 0;
+               }
+       default:
+               /* should never reach this path */
+               return -EINVAL;
+       }
+}
+
+static int i8254_count_ceiling_read(struct counter_device *const counter,
+                                   struct counter_count *const count, u64 *const ceiling)
+{
+       struct i8254 *const priv = counter_priv(counter);
+
+       mutex_lock(&priv->lock);
+
+       switch (priv->out_mode[count->id]) {
+       case I8254_MODE_RATE_GENERATOR:
+               /* Rate Generator decrements 0 by one and the counter "wraps around" */
+               *ceiling = (priv->preset[count->id] == 0) ? U16_MAX : priv->preset[count->id];
+               break;
+       case I8254_MODE_SQUARE_WAVE_MODE:
+               if (priv->preset[count->id] % 2)
+                       *ceiling = priv->preset[count->id] - 1;
+               else if (priv->preset[count->id] == 0)
+                       /* Square Wave Mode decrements 0 by two and the counter "wraps around" */
+                       *ceiling = U16_MAX - 1;
+               else
+                       *ceiling = priv->preset[count->id];
+               break;
+       default:
+               *ceiling = U16_MAX;
+               break;
+       }
+
+       mutex_unlock(&priv->lock);
+
+       return 0;
+}
+
+static int i8254_count_mode_read(struct counter_device *const counter,
+                                struct counter_count *const count,
+                                enum counter_count_mode *const count_mode)
+{
+       const struct i8254 *const priv = counter_priv(counter);
+
+       switch (priv->out_mode[count->id]) {
+       case I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT:
+               *count_mode = COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT;
+               return 0;
+       case I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT:
+               *count_mode = COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT;
+               return 0;
+       case I8254_MODE_RATE_GENERATOR:
+               *count_mode = COUNTER_COUNT_MODE_RATE_GENERATOR;
+               return 0;
+       case I8254_MODE_SQUARE_WAVE_MODE:
+               *count_mode = COUNTER_COUNT_MODE_SQUARE_WAVE_MODE;
+               return 0;
+       case I8254_MODE_SOFTWARE_TRIGGERED_STROBE:
+               *count_mode = COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE;
+               return 0;
+       case I8254_MODE_HARDWARE_TRIGGERED_STROBE:
+               *count_mode = COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE;
+               return 0;
+       default:
+               /* should never reach this path */
+               return -EINVAL;
+       }
+}
+
+static int i8254_count_mode_write(struct counter_device *const counter,
+                                 struct counter_count *const count,
+                                 const enum counter_count_mode count_mode)
+{
+       struct i8254 *const priv = counter_priv(counter);
+       u8 out_mode;
+       int ret;
+
+       switch (count_mode) {
+       case COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT:
+               out_mode = I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT;
+               break;
+       case COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT:
+               out_mode = I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT;
+               break;
+       case COUNTER_COUNT_MODE_RATE_GENERATOR:
+               out_mode = I8254_MODE_RATE_GENERATOR;
+               break;
+       case COUNTER_COUNT_MODE_SQUARE_WAVE_MODE:
+               out_mode = I8254_MODE_SQUARE_WAVE_MODE;
+               break;
+       case COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE:
+               out_mode = I8254_MODE_SOFTWARE_TRIGGERED_STROBE;
+               break;
+       case COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE:
+               out_mode = I8254_MODE_HARDWARE_TRIGGERED_STROBE;
+               break;
+       default:
+               /* should never reach this path */
+               return -EINVAL;
+       }
+
+       mutex_lock(&priv->lock);
+
+       /* Counter Register is cleared when the counter is programmed */
+       priv->preset[count->id] = 0;
+       priv->out_mode[count->id] = out_mode;
+       ret = regmap_write(priv->map, I8254_CONTROL_REG,
+                          I8254_PROGRAM_COUNTER(count->id, out_mode));
+
+       mutex_unlock(&priv->lock);
+
+       return ret;
+}
+
+static int i8254_count_floor_read(struct counter_device *const counter,
+                                 struct counter_count *const count, u64 *const floor)
+{
+       struct i8254 *const priv = counter_priv(counter);
+
+       mutex_lock(&priv->lock);
+
+       switch (priv->out_mode[count->id]) {
+       case I8254_MODE_RATE_GENERATOR:
+               /* counter is always reloaded after 1, but 0 is a possible reload value */
+               *floor = (priv->preset[count->id] == 0) ? 0 : 1;
+               break;
+       case I8254_MODE_SQUARE_WAVE_MODE:
+               /* counter is always reloaded after 2 for even preset values */
+               *floor = (priv->preset[count->id] % 2 || priv->preset[count->id] == 0) ? 0 : 2;
+               break;
+       default:
+               *floor = 0;
+               break;
+       }
+
+       mutex_unlock(&priv->lock);
+
+       return 0;
+}
+
+static int i8254_count_preset_read(struct counter_device *const counter,
+                                  struct counter_count *const count, u64 *const preset)
+{
+       const struct i8254 *const priv = counter_priv(counter);
+
+       *preset = priv->preset[count->id];
+
+       return 0;
+}
+
+static int i8254_count_preset_write(struct counter_device *const counter,
+                                   struct counter_count *const count, const u64 preset)
+{
+       struct i8254 *const priv = counter_priv(counter);
+       int ret;
+       u8 value[2];
+
+       if (preset > U16_MAX)
+               return -ERANGE;
+
+       mutex_lock(&priv->lock);
+
+       if (priv->out_mode[count->id] == I8254_MODE_RATE_GENERATOR ||
+           priv->out_mode[count->id] == I8254_MODE_SQUARE_WAVE_MODE) {
+               if (preset == 1) {
+                       mutex_unlock(&priv->lock);
+                       return -EINVAL;
+               }
+       }
+
+       priv->preset[count->id] = preset;
+
+       put_unaligned_le16(preset, value);
+       ret = regmap_noinc_write(priv->map, I8254_COUNTER_REG(count->id), value, 2);
+
+       mutex_unlock(&priv->lock);
+
+       return ret;
+}
+
+static int i8254_init_hw(struct regmap *const map)
+{
+       unsigned long i;
+       int ret;
+
+       for (i = 0; i < I8254_NUM_COUNTERS; i++) {
+               /* Initialize each counter to Mode 0 */
+               ret = regmap_write(map, I8254_CONTROL_REG,
+                                  I8254_PROGRAM_COUNTER(i, I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT));
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static const struct counter_ops i8254_ops = {
+       .count_read = i8254_count_read,
+       .function_read = i8254_function_read,
+       .action_read = i8254_action_read,
+};
+
+#define I8254_SIGNAL(_id, _name) {             \
+       .id = (_id),                            \
+       .name = (_name),                        \
+}
+
+static struct counter_signal i8254_signals[] = {
+       I8254_SIGNAL(0, "CLK 0"), I8254_SIGNAL(1, "GATE 0"),
+       I8254_SIGNAL(2, "CLK 1"), I8254_SIGNAL(3, "GATE 1"),
+       I8254_SIGNAL(4, "CLK 2"), I8254_SIGNAL(5, "GATE 2"),
+};
+
+static const enum counter_synapse_action i8254_clk_actions[] = {
+       COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
+};
+static const enum counter_synapse_action i8254_gate_actions[] = {
+       COUNTER_SYNAPSE_ACTION_NONE,
+       COUNTER_SYNAPSE_ACTION_RISING_EDGE,
+};
+
+#define I8254_SYNAPSES_BASE(_id) ((_id) * I8254_SYNAPSES_PER_COUNT)
+#define I8254_SYNAPSE_CLK(_id) {                                       \
+       .actions_list   = i8254_clk_actions,                            \
+       .num_actions    = ARRAY_SIZE(i8254_clk_actions),                \
+       .signal         = &i8254_signals[I8254_SYNAPSES_BASE(_id) + 0], \
+}
+#define I8254_SYNAPSE_GATE(_id) {                                      \
+       .actions_list   = i8254_gate_actions,                           \
+       .num_actions    = ARRAY_SIZE(i8254_gate_actions),               \
+       .signal         = &i8254_signals[I8254_SYNAPSES_BASE(_id) + 1], \
+}
+
+static struct counter_synapse i8254_synapses[] = {
+       I8254_SYNAPSE_CLK(0), I8254_SYNAPSE_GATE(0),
+       I8254_SYNAPSE_CLK(1), I8254_SYNAPSE_GATE(1),
+       I8254_SYNAPSE_CLK(2), I8254_SYNAPSE_GATE(2),
+};
+
+static const enum counter_function i8254_functions_list[] = {
+       COUNTER_FUNCTION_DECREASE,
+};
+
+static const enum counter_count_mode i8254_count_modes[] = {
+       COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT,
+       COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT,
+       COUNTER_COUNT_MODE_RATE_GENERATOR,
+       COUNTER_COUNT_MODE_SQUARE_WAVE_MODE,
+       COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE,
+       COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE,
+};
+
+static DEFINE_COUNTER_AVAILABLE(i8254_count_modes_available, i8254_count_modes);
+
+static struct counter_comp i8254_count_ext[] = {
+       COUNTER_COMP_CEILING(i8254_count_ceiling_read, NULL),
+       COUNTER_COMP_COUNT_MODE(i8254_count_mode_read, i8254_count_mode_write,
+                               i8254_count_modes_available),
+       COUNTER_COMP_FLOOR(i8254_count_floor_read, NULL),
+       COUNTER_COMP_PRESET(i8254_count_preset_read, i8254_count_preset_write),
+};
+
+#define I8254_COUNT(_id, _name) {                              \
+       .id = (_id),                                            \
+       .name = (_name),                                        \
+       .functions_list = i8254_functions_list,                 \
+       .num_functions = ARRAY_SIZE(i8254_functions_list),      \
+       .synapses = &i8254_synapses[I8254_SYNAPSES_BASE(_id)],  \
+       .num_synapses = I8254_SYNAPSES_PER_COUNT,               \
+       .ext = i8254_count_ext,                                 \
+       .num_ext = ARRAY_SIZE(i8254_count_ext)                  \
+}
+
+static struct counter_count i8254_counts[I8254_NUM_COUNTERS] = {
+       I8254_COUNT(0, "Counter 0"), I8254_COUNT(1, "Counter 1"), I8254_COUNT(2, "Counter 2"),
+};
+
+/**
+ * devm_i8254_regmap_register - Register an i8254 Counter device
+ * @dev: device that is registering this i8254 Counter device
+ * @config: configuration for i8254_regmap_config
+ *
+ * Registers an Intel 8254 Programmable Interval Timer Counter device. Returns 0 on success and
+ * negative error number on failure.
+ */
+int devm_i8254_regmap_register(struct device *const dev,
+                              const struct i8254_regmap_config *const config)
+{
+       struct counter_device *counter;
+       struct i8254 *priv;
+       int err;
+
+       if (!config->parent)
+               return -EINVAL;
+
+       if (!config->map)
+               return -EINVAL;
+
+       counter = devm_counter_alloc(dev, sizeof(*priv));
+       if (!counter)
+               return -ENOMEM;
+       priv = counter_priv(counter);
+       priv->map = config->map;
+
+       counter->name = dev_name(config->parent);
+       counter->parent = config->parent;
+       counter->ops = &i8254_ops;
+       counter->counts = i8254_counts;
+       counter->num_counts = ARRAY_SIZE(i8254_counts);
+       counter->signals = i8254_signals;
+       counter->num_signals = ARRAY_SIZE(i8254_signals);
+
+       mutex_init(&priv->lock);
+
+       err = i8254_init_hw(priv->map);
+       if (err)
+               return err;
+
+       err = devm_counter_add(dev, counter);
+       if (err < 0)
+               return dev_err_probe(dev, err, "Failed to add counter\n");
+
+       return 0;
+}
+EXPORT_SYMBOL_NS_GPL(devm_i8254_regmap_register, I8254);
+
+MODULE_AUTHOR("William Breathitt Gray");
+MODULE_DESCRIPTION("Intel 8254 Programmable Interval Timer");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(COUNTER);
index 9bf20a5d6bda8f9d4f47821708588a922bea36f8..6206d2dc3d47098aea85d854ad212dac9751baee 100644 (file)
@@ -342,6 +342,9 @@ static int stm32_timer_cnt_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, priv);
 
+       /* Reset input selector to its default input */
+       regmap_write(priv->regmap, TIM_TISEL, 0x0);
+
        /* Register Counter device */
        ret = devm_counter_add(dev, counter);
        if (ret < 0)
index 29904395e95f9ca3b6c24d845584a5da141a99b0..b2f05d27167e393c92b63bda89b17a9b48cad923 100644 (file)
@@ -975,7 +975,7 @@ static int __init acpi_cpufreq_probe(struct platform_device *pdev)
 
        /* don't keep reloading if cpufreq_driver exists */
        if (cpufreq_get_current_driver())
-               return -EEXIST;
+               return -ENODEV;
 
        pr_debug("%s\n", __func__);
 
index 5a3d4aa0f45a6a18e1abb3cceb6c972c4b3f3e19..ddd346a239e0b55acfaef158cb12ea1a8612f948 100644 (file)
@@ -444,9 +444,8 @@ static int amd_pstate_verify(struct cpufreq_policy_data *policy)
        return 0;
 }
 
-static int amd_pstate_target(struct cpufreq_policy *policy,
-                            unsigned int target_freq,
-                            unsigned int relation)
+static int amd_pstate_update_freq(struct cpufreq_policy *policy,
+                                 unsigned int target_freq, bool fast_switch)
 {
        struct cpufreq_freqs freqs;
        struct amd_cpudata *cpudata = policy->driver_data;
@@ -465,26 +464,51 @@ static int amd_pstate_target(struct cpufreq_policy *policy,
        des_perf = DIV_ROUND_CLOSEST(target_freq * cap_perf,
                                     cpudata->max_freq);
 
-       cpufreq_freq_transition_begin(policy, &freqs);
+       WARN_ON(fast_switch && !policy->fast_switch_enabled);
+       /*
+        * If fast_switch is desired, then there aren't any registered
+        * transition notifiers. See comment for
+        * cpufreq_enable_fast_switch().
+        */
+       if (!fast_switch)
+               cpufreq_freq_transition_begin(policy, &freqs);
+
        amd_pstate_update(cpudata, min_perf, des_perf,
-                         max_perf, false, policy->governor->flags);
-       cpufreq_freq_transition_end(policy, &freqs, false);
+                       max_perf, fast_switch, policy->governor->flags);
+
+       if (!fast_switch)
+               cpufreq_freq_transition_end(policy, &freqs, false);
 
        return 0;
 }
 
+static int amd_pstate_target(struct cpufreq_policy *policy,
+                            unsigned int target_freq,
+                            unsigned int relation)
+{
+       return amd_pstate_update_freq(policy, target_freq, false);
+}
+
+static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
+                                 unsigned int target_freq)
+{
+       return amd_pstate_update_freq(policy, target_freq, true);
+}
+
 static void amd_pstate_adjust_perf(unsigned int cpu,
                                   unsigned long _min_perf,
                                   unsigned long target_perf,
                                   unsigned long capacity)
 {
        unsigned long max_perf, min_perf, des_perf,
-                     cap_perf, lowest_nonlinear_perf;
+                     cap_perf, lowest_nonlinear_perf, max_freq;
        struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
        struct amd_cpudata *cpudata = policy->driver_data;
+       unsigned int target_freq;
 
        cap_perf = READ_ONCE(cpudata->highest_perf);
        lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
+       max_freq = READ_ONCE(cpudata->max_freq);
 
        des_perf = cap_perf;
        if (target_perf < capacity)
@@ -501,6 +525,10 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
        if (max_perf < min_perf)
                max_perf = min_perf;
 
+       des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
+       target_freq = div_u64(des_perf * max_freq, max_perf);
+       policy->cur = target_freq;
+
        amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true,
                        policy->governor->flags);
        cpufreq_cpu_put(policy);
@@ -715,6 +743,7 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy *policy)
 
        freq_qos_remove_request(&cpudata->req[1]);
        freq_qos_remove_request(&cpudata->req[0]);
+       policy->fast_switch_possible = false;
        kfree(cpudata);
 
        return 0;
@@ -1079,7 +1108,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
        policy->policy = CPUFREQ_POLICY_POWERSAVE;
 
        if (boot_cpu_has(X86_FEATURE_CPPC)) {
-               policy->fast_switch_possible = true;
                ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value);
                if (ret)
                        return ret;
@@ -1102,7 +1130,6 @@ free_cpudata1:
 static int amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
 {
        pr_debug("CPU %d exiting\n", policy->cpu);
-       policy->fast_switch_possible = false;
        return 0;
 }
 
@@ -1309,6 +1336,7 @@ static struct cpufreq_driver amd_pstate_driver = {
        .flags          = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
        .verify         = amd_pstate_verify,
        .target         = amd_pstate_target,
+       .fast_switch    = amd_pstate_fast_switch,
        .init           = amd_pstate_cpu_init,
        .exit           = amd_pstate_cpu_exit,
        .suspend        = amd_pstate_cpu_suspend,
index 1d2cfea9858afc121d8ecf4048d5bf2bfc9afe4a..73efbcf5513b2cde60faa7d3223479c1c5efd1bd 100644 (file)
@@ -583,7 +583,7 @@ static int __init pcc_cpufreq_probe(struct platform_device *pdev)
 
        /* Skip initialization if another cpufreq driver is there. */
        if (cpufreq_get_current_driver())
-               return -EEXIST;
+               return -ENODEV;
 
        if (acpi_disabled)
                return -ENODEV;
index 23b9ff920d7e85c8f347fc11bb8fe738635c31a4..bea9cf31a12df9a3f258e47e98ca5af3582ea856 100644 (file)
@@ -1028,7 +1028,7 @@ static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds)
  * cxl_dev_state_identify() - Send the IDENTIFY command to the device.
  * @cxlds: The device data for the operation
  *
- * Return: 0 if identify was executed successfully.
+ * Return: 0 if identify was executed successfully or media not ready.
  *
  * This will dispatch the identify command to the device and on success populate
  * structures to be exported to sysfs.
@@ -1041,6 +1041,9 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds)
        u32 val;
        int rc;
 
+       if (!cxlds->media_ready)
+               return 0;
+
        mbox_cmd = (struct cxl_mbox_cmd) {
                .opcode = CXL_MBOX_OP_IDENTIFY,
                .size_out = sizeof(id),
@@ -1102,6 +1105,13 @@ int cxl_mem_create_range_info(struct cxl_dev_state *cxlds)
        struct device *dev = cxlds->dev;
        int rc;
 
+       if (!cxlds->media_ready) {
+               cxlds->dpa_res = DEFINE_RES_MEM(0, 0);
+               cxlds->ram_res = DEFINE_RES_MEM(0, 0);
+               cxlds->pmem_res = DEFINE_RES_MEM(0, 0);
+               return 0;
+       }
+
        cxlds->dpa_res =
                (struct resource)DEFINE_RES_MEM(0, cxlds->total_bytes);
 
index bdbd907884ce799d02e401f9b07cfdee7b0f88ac..67f4ab6daa34f0144380c27d41d9ca252c52ef04 100644 (file)
@@ -101,23 +101,57 @@ int devm_cxl_port_enumerate_dports(struct cxl_port *port)
 }
 EXPORT_SYMBOL_NS_GPL(devm_cxl_port_enumerate_dports, CXL);
 
-/*
- * Wait up to @media_ready_timeout for the device to report memory
- * active.
- */
-int cxl_await_media_ready(struct cxl_dev_state *cxlds)
+static int cxl_dvsec_mem_range_valid(struct cxl_dev_state *cxlds, int id)
+{
+       struct pci_dev *pdev = to_pci_dev(cxlds->dev);
+       int d = cxlds->cxl_dvsec;
+       bool valid = false;
+       int rc, i;
+       u32 temp;
+
+       if (id > CXL_DVSEC_RANGE_MAX)
+               return -EINVAL;
+
+       /* Check MEM INFO VALID bit first, give up after 1s */
+       i = 1;
+       do {
+               rc = pci_read_config_dword(pdev,
+                                          d + CXL_DVSEC_RANGE_SIZE_LOW(id),
+                                          &temp);
+               if (rc)
+                       return rc;
+
+               valid = FIELD_GET(CXL_DVSEC_MEM_INFO_VALID, temp);
+               if (valid)
+                       break;
+               msleep(1000);
+       } while (i--);
+
+       if (!valid) {
+               dev_err(&pdev->dev,
+                       "Timeout awaiting memory range %d valid after 1s.\n",
+                       id);
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int cxl_dvsec_mem_range_active(struct cxl_dev_state *cxlds, int id)
 {
        struct pci_dev *pdev = to_pci_dev(cxlds->dev);
        int d = cxlds->cxl_dvsec;
        bool active = false;
-       u64 md_status;
        int rc, i;
+       u32 temp;
 
-       for (i = media_ready_timeout; i; i--) {
-               u32 temp;
+       if (id > CXL_DVSEC_RANGE_MAX)
+               return -EINVAL;
 
+       /* Check MEM ACTIVE bit, up to 60s timeout by default */
+       for (i = media_ready_timeout; i; i--) {
                rc = pci_read_config_dword(
-                       pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(0), &temp);
+                       pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(id), &temp);
                if (rc)
                        return rc;
 
@@ -134,6 +168,39 @@ int cxl_await_media_ready(struct cxl_dev_state *cxlds)
                return -ETIMEDOUT;
        }
 
+       return 0;
+}
+
+/*
+ * Wait up to @media_ready_timeout for the device to report memory
+ * active.
+ */
+int cxl_await_media_ready(struct cxl_dev_state *cxlds)
+{
+       struct pci_dev *pdev = to_pci_dev(cxlds->dev);
+       int d = cxlds->cxl_dvsec;
+       int rc, i, hdm_count;
+       u64 md_status;
+       u16 cap;
+
+       rc = pci_read_config_word(pdev,
+                                 d + CXL_DVSEC_CAP_OFFSET, &cap);
+       if (rc)
+               return rc;
+
+       hdm_count = FIELD_GET(CXL_DVSEC_HDM_COUNT_MASK, cap);
+       for (i = 0; i < hdm_count; i++) {
+               rc = cxl_dvsec_mem_range_valid(cxlds, i);
+               if (rc)
+                       return rc;
+       }
+
+       for (i = 0; i < hdm_count; i++) {
+               rc = cxl_dvsec_mem_range_active(cxlds, i);
+               if (rc)
+                       return rc;
+       }
+
        md_status = readq(cxlds->regs.memdev + CXLMDEV_STATUS_OFFSET);
        if (!CXLMDEV_READY(md_status))
                return -EIO;
@@ -241,17 +308,36 @@ static void disable_hdm(void *_cxlhdm)
               hdm + CXL_HDM_DECODER_CTRL_OFFSET);
 }
 
-static int devm_cxl_enable_hdm(struct device *host, struct cxl_hdm *cxlhdm)
+int devm_cxl_enable_hdm(struct cxl_port *port, struct cxl_hdm *cxlhdm)
 {
-       void __iomem *hdm = cxlhdm->regs.hdm_decoder;
+       void __iomem *hdm;
        u32 global_ctrl;
 
+       /*
+        * If the hdm capability was not mapped there is nothing to enable and
+        * the caller is responsible for what happens next.  For example,
+        * emulate a passthrough decoder.
+        */
+       if (IS_ERR(cxlhdm))
+               return 0;
+
+       hdm = cxlhdm->regs.hdm_decoder;
        global_ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET);
+
+       /*
+        * If the HDM decoder capability was enabled on entry, skip
+        * registering disable_hdm() since this decode capability may be
+        * owned by platform firmware.
+        */
+       if (global_ctrl & CXL_HDM_DECODER_ENABLE)
+               return 0;
+
        writel(global_ctrl | CXL_HDM_DECODER_ENABLE,
               hdm + CXL_HDM_DECODER_CTRL_OFFSET);
 
-       return devm_add_action_or_reset(host, disable_hdm, cxlhdm);
+       return devm_add_action_or_reset(&port->dev, disable_hdm, cxlhdm);
 }
+EXPORT_SYMBOL_NS_GPL(devm_cxl_enable_hdm, CXL);
 
 int cxl_dvsec_rr_decode(struct device *dev, int d,
                        struct cxl_endpoint_dvsec_info *info)
@@ -425,7 +511,7 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
        if (info->mem_enabled)
                return 0;
 
-       rc = devm_cxl_enable_hdm(&port->dev, cxlhdm);
+       rc = devm_cxl_enable_hdm(port, cxlhdm);
        if (rc)
                return rc;
 
@@ -571,6 +657,7 @@ void read_cdat_data(struct cxl_port *port)
                /* Don't leave table data allocated on error */
                devm_kfree(dev, cdat_table);
                dev_err(dev, "CDAT data read error\n");
+               return;
        }
 
        port->cdat.table = cdat_table + sizeof(__le32);
index da2068475fa26c5b4cea086e8433bcec77299f07..e7c284c890bc111eeefd19e369e996b4b6966f3f 100644 (file)
@@ -750,11 +750,10 @@ struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport,
 
        parent_port = parent_dport ? parent_dport->port : NULL;
        if (IS_ERR(port)) {
-               dev_dbg(uport, "Failed to add %s%s%s%s: %ld\n",
-                       dev_name(&port->dev),
-                       parent_port ? " to " : "",
+               dev_dbg(uport, "Failed to add%s%s%s: %ld\n",
+                       parent_port ? " port to " : "",
                        parent_port ? dev_name(&parent_port->dev) : "",
-                       parent_port ? "" : " (root port)",
+                       parent_port ? "" : " root port",
                        PTR_ERR(port));
        } else {
                dev_dbg(uport, "%s added%s%s%s\n",
index 044a92d9813e239d1b97e7a4935f36850c30e154..f93a285389621cc77e86ae792c095b1671f30c85 100644 (file)
@@ -710,6 +710,7 @@ struct cxl_endpoint_dvsec_info {
 struct cxl_hdm;
 struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port,
                                   struct cxl_endpoint_dvsec_info *info);
+int devm_cxl_enable_hdm(struct cxl_port *port, struct cxl_hdm *cxlhdm);
 int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
                                struct cxl_endpoint_dvsec_info *info);
 int devm_cxl_add_passthrough_decoder(struct cxl_port *port);
index db12b6313afbf734fba7c38302a28c56c44950a1..a2845a7a69d820d9b4f04ae6a681839728d0f31c 100644 (file)
@@ -266,6 +266,7 @@ struct cxl_poison_state {
  * @regs: Parsed register blocks
  * @cxl_dvsec: Offset to the PCIe device DVSEC
  * @rcd: operating in RCD mode (CXL 3.0 9.11.8 CXL Devices Attached to an RCH)
+ * @media_ready: Indicate whether the device media is usable
  * @payload_size: Size of space for payload
  *                (CXL 2.0 8.2.8.4.3 Mailbox Capabilities Register)
  * @lsa_size: Size of Label Storage Area
@@ -303,6 +304,7 @@ struct cxl_dev_state {
        int cxl_dvsec;
 
        bool rcd;
+       bool media_ready;
        size_t payload_size;
        size_t lsa_size;
        struct mutex mbox_mutex; /* Protects device mailbox and firmware */
index 0465ef963cd6a0b23dae3cfb7177d9a033dcde18..7c02e55b80429a9390d3322407701033bb6c01ce 100644 (file)
@@ -31,6 +31,8 @@
 #define   CXL_DVSEC_RANGE_BASE_LOW(i)  (0x24 + (i * 0x10))
 #define     CXL_DVSEC_MEM_BASE_LOW_MASK        GENMASK(31, 28)
 
+#define CXL_DVSEC_RANGE_MAX            2
+
 /* CXL 2.0 8.1.4: Non-CXL Function Map DVSEC */
 #define CXL_DVSEC_FUNCTION_MAP                                 2
 
index 10caf180b3fa0bff3e1363c269ad4fe77cc7cff8..519edd0eb1967d8c0d0ec7bb5e934b267e37c1ff 100644 (file)
@@ -124,6 +124,9 @@ static int cxl_mem_probe(struct device *dev)
        struct dentry *dentry;
        int rc;
 
+       if (!cxlds->media_ready)
+               return -EBUSY;
+
        /*
         * Someone is trying to reattach this device after it lost its port
         * connection (an endpoint port previously registered by this memdev was
index f7a5b8e9c102411ca5bfde2f1995488498aa7e91..0872f2233ed0c88aa9fec7e9e93935dfa1f0e740 100644 (file)
@@ -708,6 +708,12 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (rc)
                dev_dbg(&pdev->dev, "Failed to map RAS capability.\n");
 
+       rc = cxl_await_media_ready(cxlds);
+       if (rc == 0)
+               cxlds->media_ready = true;
+       else
+               dev_warn(&pdev->dev, "Media not active (%d)\n", rc);
+
        rc = cxl_pci_setup_mailbox(cxlds);
        if (rc)
                return rc;
index eb57324c4ad4a0e54c9a35500df9c3a216f603a2..c23b6164e1c0fa5c1e9a9c671c2e1d29da604c69 100644 (file)
@@ -60,13 +60,17 @@ static int discover_region(struct device *dev, void *root)
 static int cxl_switch_port_probe(struct cxl_port *port)
 {
        struct cxl_hdm *cxlhdm;
-       int rc;
+       int rc, nr_dports;
 
-       rc = devm_cxl_port_enumerate_dports(port);
-       if (rc < 0)
-               return rc;
+       nr_dports = devm_cxl_port_enumerate_dports(port);
+       if (nr_dports < 0)
+               return nr_dports;
 
        cxlhdm = devm_cxl_setup_hdm(port, NULL);
+       rc = devm_cxl_enable_hdm(port, cxlhdm);
+       if (rc)
+               return rc;
+
        if (!IS_ERR(cxlhdm))
                return devm_cxl_enumerate_decoders(cxlhdm, NULL);
 
@@ -75,7 +79,7 @@ static int cxl_switch_port_probe(struct cxl_port *port)
                return PTR_ERR(cxlhdm);
        }
 
-       if (rc == 1) {
+       if (nr_dports == 1) {
                dev_dbg(&port->dev, "Fallback to passthrough decoder\n");
                return devm_cxl_add_passthrough_decoder(port);
        }
@@ -113,12 +117,6 @@ static int cxl_endpoint_port_probe(struct cxl_port *port)
        if (rc)
                return rc;
 
-       rc = cxl_await_media_ready(cxlds);
-       if (rc) {
-               dev_err(&port->dev, "Media not active (%d)\n", rc);
-               return rc;
-       }
-
        rc = devm_cxl_enumerate_decoders(cxlhdm, &info);
        if (rc)
                return rc;
index 8858470246e1552e5e278a2b254f8ae874df894b..ee3a219e3a897c56ac69d7a902ef90ccc0262822 100644 (file)
 #define ATC_DST_PIP            BIT(12)         /* Destination Picture-in-Picture enabled */
 #define ATC_SRC_DSCR_DIS       BIT(16)         /* Src Descriptor fetch disable */
 #define ATC_DST_DSCR_DIS       BIT(20)         /* Dst Descriptor fetch disable */
-#define ATC_FC                 GENMASK(22, 21) /* Choose Flow Controller */
+#define ATC_FC                 GENMASK(23, 21) /* Choose Flow Controller */
 #define ATC_FC_MEM2MEM         0x0             /* Mem-to-Mem (DMA) */
 #define ATC_FC_MEM2PER         0x1             /* Mem-to-Periph (DMA) */
 #define ATC_FC_PER2MEM         0x2             /* Periph-to-Mem (DMA) */
 #define ATC_AUTO               BIT(31)         /* Auto multiple buffer tx enable */
 
 /* Bitfields in CFG */
-#define ATC_PER_MSB(h) ((0x30U & (h)) >> 4)    /* Extract most significant bits of a handshaking identifier */
-
 #define ATC_SRC_PER            GENMASK(3, 0)   /* Channel src rq associated with periph handshaking ifc h */
 #define ATC_DST_PER            GENMASK(7, 4)   /* Channel dst rq associated with periph handshaking ifc h */
 #define ATC_SRC_REP            BIT(8)          /* Source Replay Mod */
 #define ATC_DPIP_HOLE          GENMASK(15, 0)
 #define ATC_DPIP_BOUNDARY      GENMASK(25, 16)
 
-#define ATC_SRC_PER_ID(id)     (FIELD_PREP(ATC_SRC_PER_MSB, (id)) |    \
-                                FIELD_PREP(ATC_SRC_PER, (id)))
-#define ATC_DST_PER_ID(id)     (FIELD_PREP(ATC_DST_PER_MSB, (id)) |    \
-                                FIELD_PREP(ATC_DST_PER, (id)))
+#define ATC_PER_MSB            GENMASK(5, 4)   /* Extract MSBs of a handshaking identifier */
+#define ATC_SRC_PER_ID(id)                                            \
+       ({ typeof(id) _id = (id);                                      \
+          FIELD_PREP(ATC_SRC_PER_MSB, FIELD_GET(ATC_PER_MSB, _id)) |  \
+          FIELD_PREP(ATC_SRC_PER, _id); })
+#define ATC_DST_PER_ID(id)                                            \
+       ({ typeof(id) _id = (id);                                      \
+          FIELD_PREP(ATC_DST_PER_MSB, FIELD_GET(ATC_PER_MSB, _id)) |  \
+          FIELD_PREP(ATC_DST_PER, _id); })
 
 
 
index 7da6d9b6098e719e531052c9aa938b669dfc3149..c3b37168b21f166e9690076a1692d965392b37f5 100644 (file)
@@ -1102,6 +1102,8 @@ at_xdmac_prep_interleaved(struct dma_chan *chan,
                                                        NULL,
                                                        src_addr, dst_addr,
                                                        xt, xt->sgl);
+               if (!first)
+                       return NULL;
 
                /* Length of the block is (BLEN+1) microblocks. */
                for (i = 0; i < xt->numf - 1; i++)
@@ -1132,8 +1134,9 @@ at_xdmac_prep_interleaved(struct dma_chan *chan,
                                                               src_addr, dst_addr,
                                                               xt, chunk);
                        if (!desc) {
-                               list_splice_tail_init(&first->descs_list,
-                                                     &atchan->free_descs_list);
+                               if (first)
+                                       list_splice_tail_init(&first->descs_list,
+                                                             &atchan->free_descs_list);
                                return NULL;
                        }
 
index ecbf67c2ad2b07d51ec6b05764be8dc4c51068db..d32deb9b4e3dee466fd056230596aa42198d8285 100644 (file)
@@ -277,7 +277,6 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
                if (wq_dedicated(wq)) {
                        rc = idxd_wq_set_pasid(wq, pasid);
                        if (rc < 0) {
-                               iommu_sva_unbind_device(sva);
                                dev_err(dev, "wq set pasid failed: %d\n", rc);
                                goto failed_set_pasid;
                        }
index 0d9257fbdfb0d90d902761406de722eff92b1888..b4731fe6bbc14fc7360723726b535a6194383429 100644 (file)
@@ -1050,7 +1050,7 @@ static bool _trigger(struct pl330_thread *thrd)
        return true;
 }
 
-static bool _start(struct pl330_thread *thrd)
+static bool pl330_start_thread(struct pl330_thread *thrd)
 {
        switch (_state(thrd)) {
        case PL330_STATE_FAULT_COMPLETING:
@@ -1702,7 +1702,7 @@ static int pl330_update(struct pl330_dmac *pl330)
                        thrd->req_running = -1;
 
                        /* Get going again ASAP */
-                       _start(thrd);
+                       pl330_start_thread(thrd);
 
                        /* For now, just make a list of callbacks to be done */
                        list_add_tail(&descdone->rqd, &pl330->req_done);
@@ -2089,7 +2089,7 @@ static void pl330_tasklet(struct tasklet_struct *t)
        } else {
                /* Make sure the PL330 Channel thread is active */
                spin_lock(&pch->thread->dmac->lock);
-               _start(pch->thread);
+               pl330_start_thread(pch->thread);
                spin_unlock(&pch->thread->dmac->lock);
        }
 
@@ -2107,7 +2107,7 @@ static void pl330_tasklet(struct tasklet_struct *t)
                        if (power_down) {
                                pch->active = true;
                                spin_lock(&pch->thread->dmac->lock);
-                               _start(pch->thread);
+                               pl330_start_thread(pch->thread);
                                spin_unlock(&pch->thread->dmac->lock);
                                power_down = false;
                        }
index fc3a2a05ab7b70f33ab2c81e618a245941e1222a..b8329a23728d73f2a8a29e1c3965181b2712d635 100644 (file)
@@ -5527,7 +5527,7 @@ static int udma_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int udma_pm_suspend(struct device *dev)
+static int __maybe_unused udma_pm_suspend(struct device *dev)
 {
        struct udma_dev *ud = dev_get_drvdata(dev);
        struct dma_device *dma_dev = &ud->ddev;
@@ -5549,7 +5549,7 @@ static int udma_pm_suspend(struct device *dev)
        return 0;
 }
 
-static int udma_pm_resume(struct device *dev)
+static int __maybe_unused udma_pm_resume(struct device *dev)
 {
        struct udma_dev *ud = dev_get_drvdata(dev);
        struct dma_device *dma_dev = &ud->ddev;
index 290186e44e6bdbe34d1f41805bca894e38c7e741..0ef1971d22bb0b76796f02c2d608430e7b77dc3d 100644 (file)
@@ -185,6 +185,7 @@ config EXTCON_USBC_TUSB320
        tristate "TI TUSB320 USB-C extcon support"
        depends on I2C && TYPEC
        select REGMAP_I2C
+       depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH
        help
          Say Y here to enable support for USB Type C cable detection extcon
          support using a TUSB320.
index 180be768c2157b6c79f5718ef411d498ed2ffc34..a703a8315634df6aea13e1c43e53d3f643925638 100644 (file)
@@ -393,7 +393,7 @@ static int axp288_extcon_probe(struct platform_device *pdev)
                adev = acpi_dev_get_first_match_dev("INT3496", NULL, -1);
                if (adev) {
                        info->id_extcon = extcon_get_extcon_dev(acpi_dev_name(adev));
-                       put_device(&adev->dev);
+                       acpi_dev_put(adev);
                        if (IS_ERR(info->id_extcon))
                                return PTR_ERR(info->id_extcon);
 
index e8b2671eb29bce67e660fa05c04cafd75b77fb2d..e458ce0c45ab70ba607b756e0f75eb59f12e6353 100644 (file)
@@ -369,7 +369,7 @@ static struct i2c_driver fsa9480_i2c_driver = {
                .pm             = &fsa9480_pm_ops,
                .of_match_table = fsa9480_of_match,
        },
-       .probe_new              = fsa9480_probe,
+       .probe                  = fsa9480_probe,
        .id_table               = fsa9480_id,
 };
 
index 32f8b541770bf0f7d7223c1794fed598dd76f17a..d339b86804455b8863944a93edef68f3af9d71ca 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/mfd/palmas.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
-#include <linux/of_gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/workqueue.h>
 
index 017a07197f380e55dac9f3cc9e5b4580cbe02867..4616da7e5430ea54849b06c47d06b35a42917ac4 100644 (file)
@@ -348,7 +348,7 @@ static struct i2c_driver ptn5150_i2c_driver = {
                .name   = "ptn5150",
                .of_match_table = ptn5150_dt_match,
        },
-       .probe_new      = ptn5150_i2c_probe,
+       .probe          = ptn5150_i2c_probe,
        .id_table = ptn5150_i2c_id,
 };
 module_i2c_driver(ptn5150_i2c_driver);
index eb02cb962b5e18585ef4be6266351314527a8493..f72e90ceca53d5909a5c01e0ade3f5005d2d2323 100644 (file)
@@ -123,7 +123,7 @@ static int qcom_usb_extcon_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       info->id_irq = platform_get_irq_byname(pdev, "usb_id");
+       info->id_irq = platform_get_irq_byname_optional(pdev, "usb_id");
        if (info->id_irq > 0) {
                ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
                                        qcom_usb_irq_handler,
@@ -136,7 +136,7 @@ static int qcom_usb_extcon_probe(struct platform_device *pdev)
                }
        }
 
-       info->vbus_irq = platform_get_irq_byname(pdev, "usb_vbus");
+       info->vbus_irq = platform_get_irq_byname_optional(pdev, "usb_vbus");
        if (info->vbus_irq > 0) {
                ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
                                        qcom_usb_irq_handler,
index afc9b405d103010936a7881771bf57473d684f92..19bb49f13fb08c9f36eccca56e96de52bb263554 100644 (file)
@@ -695,7 +695,7 @@ static struct i2c_driver rt8973a_muic_i2c_driver = {
                .pm     = &rt8973a_muic_pm_ops,
                .of_match_table = rt8973a_dt_match,
        },
-       .probe_new = rt8973a_muic_i2c_probe,
+       .probe = rt8973a_muic_i2c_probe,
        .remove = rt8973a_muic_i2c_remove,
        .id_table = rt8973a_i2c_id,
 };
index 8401e8b277889a9b695baf39051cf4e4aecd986e..c8c4b9ef72aa1fe4d50d76bcecea53224dd6a328 100644 (file)
@@ -840,7 +840,7 @@ static struct i2c_driver sm5502_muic_i2c_driver = {
                .pm     = &sm5502_muic_pm_ops,
                .of_match_table = sm5502_dt_match,
        },
-       .probe_new = sm5022_muic_i2c_probe,
+       .probe = sm5022_muic_i2c_probe,
        .id_table = sm5502_i2c_id,
 };
 
index b408ce989c223900878be758ba44c9237a47966c..4d08c2123e5980e27cfe262607ee8320fb004242 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/module.h>
 #include <linux/regmap.h>
 #include <linux/usb/typec.h>
+#include <linux/usb/typec_altmode.h>
+#include <linux/usb/role.h>
 
 #define TUSB320_REG8                           0x8
 #define TUSB320_REG8_CURRENT_MODE_ADVERTISE    GENMASK(7, 6)
 #define TUSB320_REG8_CURRENT_MODE_DETECT_MED   0x1
 #define TUSB320_REG8_CURRENT_MODE_DETECT_ACC   0x2
 #define TUSB320_REG8_CURRENT_MODE_DETECT_HI    0x3
-#define TUSB320_REG8_ACCESSORY_CONNECTED       GENMASK(3, 2)
+#define TUSB320_REG8_ACCESSORY_CONNECTED       GENMASK(3, 1)
 #define TUSB320_REG8_ACCESSORY_CONNECTED_NONE  0x0
 #define TUSB320_REG8_ACCESSORY_CONNECTED_AUDIO 0x4
-#define TUSB320_REG8_ACCESSORY_CONNECTED_ACC   0x5
-#define TUSB320_REG8_ACCESSORY_CONNECTED_DEBUG 0x6
+#define TUSB320_REG8_ACCESSORY_CONNECTED_ACHRG 0x5
+#define TUSB320_REG8_ACCESSORY_CONNECTED_DBGDFP        0x6
+#define TUSB320_REG8_ACCESSORY_CONNECTED_DBGUFP        0x7
 #define TUSB320_REG8_ACTIVE_CABLE_DETECTION    BIT(0)
 
 #define TUSB320_REG9                           0x9
-#define TUSB320_REG9_ATTACHED_STATE_SHIFT      6
-#define TUSB320_REG9_ATTACHED_STATE_MASK       0x3
+#define TUSB320_REG9_ATTACHED_STATE            GENMASK(7, 6)
 #define TUSB320_REG9_CABLE_DIRECTION           BIT(5)
 #define TUSB320_REG9_INTERRUPT_STATUS          BIT(4)
 
@@ -78,6 +80,8 @@ struct tusb320_priv {
        struct typec_capability cap;
        enum typec_port_type port_type;
        enum typec_pwr_opmode pwr_opmode;
+       struct fwnode_handle *connector_fwnode;
+       struct usb_role_switch *role_sw;
 };
 
 static const char * const tusb_attached_states[] = {
@@ -249,8 +253,7 @@ static void tusb320_extcon_irq_handler(struct tusb320_priv *priv, u8 reg)
 {
        int state, polarity;
 
-       state = (reg >> TUSB320_REG9_ATTACHED_STATE_SHIFT) &
-               TUSB320_REG9_ATTACHED_STATE_MASK;
+       state = FIELD_GET(TUSB320_REG9_ATTACHED_STATE, reg);
        polarity = !!(reg & TUSB320_REG9_CABLE_DIRECTION);
 
        dev_dbg(priv->dev, "attached state: %s, polarity: %d\n",
@@ -276,32 +279,86 @@ static void tusb320_typec_irq_handler(struct tusb320_priv *priv, u8 reg9)
 {
        struct typec_port *port = priv->port;
        struct device *dev = priv->dev;
-       u8 mode, role, state;
+       int typec_mode;
+       enum usb_role usb_role;
+       enum typec_role pwr_role;
+       enum typec_data_role data_role;
+       u8 state, mode, accessory;
        int ret, reg8;
        bool ori;
 
+       ret = regmap_read(priv->regmap, TUSB320_REG8, &reg8);
+       if (ret) {
+               dev_err(dev, "error during reg8 i2c read, ret=%d!\n", ret);
+               return;
+       }
+
        ori = reg9 & TUSB320_REG9_CABLE_DIRECTION;
        typec_set_orientation(port, ori ? TYPEC_ORIENTATION_REVERSE :
                                          TYPEC_ORIENTATION_NORMAL);
 
-       state = (reg9 >> TUSB320_REG9_ATTACHED_STATE_SHIFT) &
-               TUSB320_REG9_ATTACHED_STATE_MASK;
-       if (state == TUSB320_ATTACHED_STATE_DFP)
-               role = TYPEC_SOURCE;
-       else
-               role = TYPEC_SINK;
+       state = FIELD_GET(TUSB320_REG9_ATTACHED_STATE, reg9);
+       accessory = FIELD_GET(TUSB320_REG8_ACCESSORY_CONNECTED, reg8);
+
+       switch (state) {
+       case TUSB320_ATTACHED_STATE_DFP:
+               typec_mode = TYPEC_MODE_USB2;
+               usb_role = USB_ROLE_HOST;
+               pwr_role = TYPEC_SOURCE;
+               data_role = TYPEC_HOST;
+               break;
+       case TUSB320_ATTACHED_STATE_UFP:
+               typec_mode = TYPEC_MODE_USB2;
+               usb_role = USB_ROLE_DEVICE;
+               pwr_role = TYPEC_SINK;
+               data_role = TYPEC_DEVICE;
+               break;
+       case TUSB320_ATTACHED_STATE_ACC:
+               /*
+                * Accessory detected. For debug accessories, just make some
+                * qualified guesses as to the role for lack of a better option.
+                */
+               if (accessory == TUSB320_REG8_ACCESSORY_CONNECTED_AUDIO ||
+                   accessory == TUSB320_REG8_ACCESSORY_CONNECTED_ACHRG) {
+                       typec_mode = TYPEC_MODE_AUDIO;
+                       usb_role = USB_ROLE_NONE;
+                       pwr_role = TYPEC_SINK;
+                       data_role = TYPEC_DEVICE;
+                       break;
+               } else if (accessory ==
+                          TUSB320_REG8_ACCESSORY_CONNECTED_DBGDFP) {
+                       typec_mode = TYPEC_MODE_DEBUG;
+                       pwr_role = TYPEC_SOURCE;
+                       usb_role = USB_ROLE_HOST;
+                       data_role = TYPEC_HOST;
+                       break;
+               } else if (accessory ==
+                          TUSB320_REG8_ACCESSORY_CONNECTED_DBGUFP) {
+                       typec_mode = TYPEC_MODE_DEBUG;
+                       pwr_role = TYPEC_SINK;
+                       usb_role = USB_ROLE_DEVICE;
+                       data_role = TYPEC_DEVICE;
+                       break;
+               }
 
-       typec_set_vconn_role(port, role);
-       typec_set_pwr_role(port, role);
-       typec_set_data_role(port, role == TYPEC_SOURCE ?
-                                 TYPEC_HOST : TYPEC_DEVICE);
+               dev_warn(priv->dev, "unexpected ACCESSORY_CONNECTED state %d\n",
+                        accessory);
 
-       ret = regmap_read(priv->regmap, TUSB320_REG8, &reg8);
-       if (ret) {
-               dev_err(dev, "error during reg8 i2c read, ret=%d!\n", ret);
-               return;
+               fallthrough;
+       default:
+               typec_mode = TYPEC_MODE_USB2;
+               usb_role = USB_ROLE_NONE;
+               pwr_role = TYPEC_SINK;
+               data_role = TYPEC_DEVICE;
+               break;
        }
 
+       typec_set_vconn_role(port, pwr_role);
+       typec_set_pwr_role(port, pwr_role);
+       typec_set_data_role(port, data_role);
+       typec_set_mode(port, typec_mode);
+       usb_role_switch_set_role(priv->role_sw, usb_role);
+
        mode = FIELD_GET(TUSB320_REG8_CURRENT_MODE_DETECT, reg8);
        if (mode == TUSB320_REG8_CURRENT_MODE_DETECT_DEF)
                typec_set_pwr_opmode(port, TYPEC_PWR_MODE_USB);
@@ -391,27 +448,25 @@ static int tusb320_typec_probe(struct i2c_client *client,
        /* Type-C connector found. */
        ret = typec_get_fw_cap(&priv->cap, connector);
        if (ret)
-               return ret;
+               goto err_put;
 
        priv->port_type = priv->cap.type;
 
        /* This goes into register 0x8 field CURRENT_MODE_ADVERTISE */
        ret = fwnode_property_read_string(connector, "typec-power-opmode", &cap_str);
        if (ret)
-               return ret;
+               goto err_put;
 
        ret = typec_find_pwr_opmode(cap_str);
        if (ret < 0)
-               return ret;
-       if (ret == TYPEC_PWR_MODE_PD)
-               return -EINVAL;
+               goto err_put;
 
        priv->pwr_opmode = ret;
 
        /* Initialize the hardware with the devicetree settings. */
        ret = tusb320_set_adv_pwr_mode(priv);
        if (ret)
-               return ret;
+               goto err_put;
 
        priv->cap.revision              = USB_TYPEC_REV_1_1;
        priv->cap.accessory[0]          = TYPEC_ACCESSORY_AUDIO;
@@ -422,10 +477,36 @@ static int tusb320_typec_probe(struct i2c_client *client,
        priv->cap.fwnode                = connector;
 
        priv->port = typec_register_port(&client->dev, &priv->cap);
-       if (IS_ERR(priv->port))
-               return PTR_ERR(priv->port);
+       if (IS_ERR(priv->port)) {
+               ret = PTR_ERR(priv->port);
+               goto err_put;
+       }
+
+       /* Find any optional USB role switch that needs reporting to */
+       priv->role_sw = fwnode_usb_role_switch_get(connector);
+       if (IS_ERR(priv->role_sw)) {
+               ret = PTR_ERR(priv->role_sw);
+               goto err_unreg;
+       }
+
+       priv->connector_fwnode = connector;
 
        return 0;
+
+err_unreg:
+       typec_unregister_port(priv->port);
+
+err_put:
+       fwnode_handle_put(connector);
+
+       return ret;
+}
+
+static void tusb320_typec_remove(struct tusb320_priv *priv)
+{
+       usb_role_switch_put(priv->role_sw);
+       typec_unregister_port(priv->port);
+       fwnode_handle_put(priv->connector_fwnode);
 }
 
 static int tusb320_probe(struct i2c_client *client)
@@ -438,7 +519,9 @@ static int tusb320_probe(struct i2c_client *client)
        priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
+
        priv->dev = &client->dev;
+       i2c_set_clientdata(client, priv);
 
        priv->regmap = devm_regmap_init_i2c(client, &tusb320_regmap_config);
        if (IS_ERR(priv->regmap))
@@ -489,10 +572,19 @@ static int tusb320_probe(struct i2c_client *client)
                                        tusb320_irq_handler,
                                        IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                                        client->name, priv);
+       if (ret)
+               tusb320_typec_remove(priv);
 
        return ret;
 }
 
+static void tusb320_remove(struct i2c_client *client)
+{
+       struct tusb320_priv *priv = i2c_get_clientdata(client);
+
+       tusb320_typec_remove(priv);
+}
+
 static const struct of_device_id tusb320_extcon_dt_match[] = {
        { .compatible = "ti,tusb320", .data = &tusb320_ops, },
        { .compatible = "ti,tusb320l", .data = &tusb320l_ops, },
@@ -501,7 +593,8 @@ static const struct of_device_id tusb320_extcon_dt_match[] = {
 MODULE_DEVICE_TABLE(of, tusb320_extcon_dt_match);
 
 static struct i2c_driver tusb320_extcon_driver = {
-       .probe_new      = tusb320_probe,
+       .probe          = tusb320_probe,
+       .remove         = tusb320_remove,
        .driver         = {
                .name   = "extcon-tusb320",
                .of_match_table = tusb320_extcon_dt_match,
index d43ba8e7260dd03ad893612669d3fde1104fc830..6f7a60d2ed9161b21625a5949c9a24868cf4de33 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/idr.h>
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/fs.h>
@@ -206,6 +207,14 @@ static const struct __extcon_info {
  * @attr_name:         "name" sysfs entry
  * @attr_state:                "state" sysfs entry
  * @attrs:             the array pointing to attr_name and attr_state for attr_g
+ * @usb_propval:       the array of USB connector properties
+ * @chg_propval:       the array of charger connector properties
+ * @jack_propval:      the array of jack connector properties
+ * @disp_propval:      the array of display connector properties
+ * @usb_bits:          the bit array of the USB connector property capabilities
+ * @chg_bits:          the bit array of the charger connector property capabilities
+ * @jack_bits:         the bit array of the jack connector property capabilities
+ * @disp_bits:         the bit array of the display connector property capabilities
  */
 struct extcon_cable {
        struct extcon_dev *edev;
@@ -222,20 +231,21 @@ struct extcon_cable {
        union extcon_property_value jack_propval[EXTCON_PROP_JACK_CNT];
        union extcon_property_value disp_propval[EXTCON_PROP_DISP_CNT];
 
-       unsigned long usb_bits[BITS_TO_LONGS(EXTCON_PROP_USB_CNT)];
-       unsigned long chg_bits[BITS_TO_LONGS(EXTCON_PROP_CHG_CNT)];
-       unsigned long jack_bits[BITS_TO_LONGS(EXTCON_PROP_JACK_CNT)];
-       unsigned long disp_bits[BITS_TO_LONGS(EXTCON_PROP_DISP_CNT)];
+       DECLARE_BITMAP(usb_bits, EXTCON_PROP_USB_CNT);
+       DECLARE_BITMAP(chg_bits, EXTCON_PROP_CHG_CNT);
+       DECLARE_BITMAP(jack_bits, EXTCON_PROP_JACK_CNT);
+       DECLARE_BITMAP(disp_bits, EXTCON_PROP_DISP_CNT);
 };
 
 static struct class *extcon_class;
 
+static DEFINE_IDA(extcon_dev_ids);
 static LIST_HEAD(extcon_dev_list);
 static DEFINE_MUTEX(extcon_dev_list_lock);
 
 static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
 {
-       int i = 0;
+       int i;
 
        if (!edev->mutually_exclusive)
                return 0;
@@ -362,12 +372,12 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
        struct extcon_dev *edev = dev_get_drvdata(dev);
 
        if (edev->max_supported == 0)
-               return sprintf(buf, "%u\n", edev->state);
+               return sysfs_emit(buf, "%u\n", edev->state);
 
        for (i = 0; i < edev->max_supported; i++) {
-               count += sprintf(buf + count, "%s=%d\n",
-                               extcon_info[edev->supported_cable[i]].name,
-                                !!(edev->state & BIT(i)));
+               count += sysfs_emit_at(buf, count, "%s=%d\n",
+                                      extcon_info[edev->supported_cable[i]].name,
+                                      !!(edev->state & BIT(i)));
        }
 
        return count;
@@ -379,7 +389,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
 {
        struct extcon_dev *edev = dev_get_drvdata(dev);
 
-       return sprintf(buf, "%s\n", edev->name);
+       return sysfs_emit(buf, "%s\n", edev->name);
 }
 static DEVICE_ATTR_RO(name);
 
@@ -390,8 +400,8 @@ static ssize_t cable_name_show(struct device *dev,
                                                  attr_name);
        int i = cable->cable_index;
 
-       return sprintf(buf, "%s\n",
-                       extcon_info[cable->edev->supported_cable[i]].name);
+       return sysfs_emit(buf, "%s\n",
+                         extcon_info[cable->edev->supported_cable[i]].name);
 }
 
 static ssize_t cable_state_show(struct device *dev,
@@ -402,8 +412,8 @@ static ssize_t cable_state_show(struct device *dev,
 
        int i = cable->cable_index;
 
-       return sprintf(buf, "%d\n",
-               extcon_get_state(cable->edev, cable->edev->supported_cable[i]));
+       return sysfs_emit(buf, "%d\n",
+                         extcon_get_state(cable->edev, cable->edev->supported_cable[i]));
 }
 
 /**
@@ -1012,12 +1022,13 @@ ATTRIBUTE_GROUPS(extcon);
 
 static int create_extcon_class(void)
 {
-       if (!extcon_class) {
-               extcon_class = class_create("extcon");
-               if (IS_ERR(extcon_class))
-                       return PTR_ERR(extcon_class);
-               extcon_class->dev_groups = extcon_groups;
-       }
+       if (extcon_class)
+               return 0;
+
+       extcon_class = class_create("extcon");
+       if (IS_ERR(extcon_class))
+               return PTR_ERR(extcon_class);
+       extcon_class->dev_groups = extcon_groups;
 
        return 0;
 }
@@ -1069,6 +1080,156 @@ void extcon_dev_free(struct extcon_dev *edev)
 }
 EXPORT_SYMBOL_GPL(extcon_dev_free);
 
+/**
+ * extcon_alloc_cables() - alloc the cables for extcon device
+ * @edev:      extcon device which has cables
+ *
+ * Returns 0 if success or error number if fail.
+ */
+static int extcon_alloc_cables(struct extcon_dev *edev)
+{
+       int index;
+       char *str;
+       struct extcon_cable *cable;
+
+       if (!edev)
+               return -EINVAL;
+
+       if (!edev->max_supported)
+               return 0;
+
+       edev->cables = kcalloc(edev->max_supported, sizeof(*edev->cables),
+                              GFP_KERNEL);
+       if (!edev->cables)
+               return -ENOMEM;
+
+       for (index = 0; index < edev->max_supported; index++) {
+               cable = &edev->cables[index];
+
+               str = kasprintf(GFP_KERNEL, "cable.%d", index);
+               if (!str) {
+                       for (index--; index >= 0; index--) {
+                               cable = &edev->cables[index];
+                               kfree(cable->attr_g.name);
+                       }
+
+                       kfree(edev->cables);
+                       return -ENOMEM;
+               }
+
+               cable->edev = edev;
+               cable->cable_index = index;
+               cable->attrs[0] = &cable->attr_name.attr;
+               cable->attrs[1] = &cable->attr_state.attr;
+               cable->attrs[2] = NULL;
+               cable->attr_g.name = str;
+               cable->attr_g.attrs = cable->attrs;
+
+               sysfs_attr_init(&cable->attr_name.attr);
+               cable->attr_name.attr.name = "name";
+               cable->attr_name.attr.mode = 0444;
+               cable->attr_name.show = cable_name_show;
+
+               sysfs_attr_init(&cable->attr_state.attr);
+               cable->attr_state.attr.name = "state";
+               cable->attr_state.attr.mode = 0444;
+               cable->attr_state.show = cable_state_show;
+       }
+
+       return 0;
+}
+
+/**
+ * extcon_alloc_muex() - alloc the mutual exclusive for extcon device
+ * @edev:      extcon device
+ *
+ * Returns 0 if success or error number if fail.
+ */
+static int extcon_alloc_muex(struct extcon_dev *edev)
+{
+       char *name;
+       int index;
+
+       if (!edev)
+               return -EINVAL;
+
+       if (!(edev->max_supported && edev->mutually_exclusive))
+               return 0;
+
+       /* Count the size of mutually_exclusive array */
+       for (index = 0; edev->mutually_exclusive[index]; index++)
+               ;
+
+       edev->attrs_muex = kcalloc(index + 1, sizeof(*edev->attrs_muex),
+                                  GFP_KERNEL);
+       if (!edev->attrs_muex)
+               return -ENOMEM;
+
+       edev->d_attrs_muex = kcalloc(index, sizeof(*edev->d_attrs_muex),
+                                    GFP_KERNEL);
+       if (!edev->d_attrs_muex) {
+               kfree(edev->attrs_muex);
+               return -ENOMEM;
+       }
+
+       for (index = 0; edev->mutually_exclusive[index]; index++) {
+               name = kasprintf(GFP_KERNEL, "0x%x",
+                                edev->mutually_exclusive[index]);
+               if (!name) {
+                       for (index--; index >= 0; index--)
+                               kfree(edev->d_attrs_muex[index].attr.name);
+
+                       kfree(edev->d_attrs_muex);
+                       kfree(edev->attrs_muex);
+                       return -ENOMEM;
+               }
+               sysfs_attr_init(&edev->d_attrs_muex[index].attr);
+               edev->d_attrs_muex[index].attr.name = name;
+               edev->d_attrs_muex[index].attr.mode = 0000;
+               edev->attrs_muex[index] = &edev->d_attrs_muex[index].attr;
+       }
+       edev->attr_g_muex.name = muex_name;
+       edev->attr_g_muex.attrs = edev->attrs_muex;
+
+       return 0;
+}
+
+/**
+ * extcon_alloc_groups() - alloc the groups for extcon device
+ * @edev:      extcon device
+ *
+ * Returns 0 if success or error number if fail.
+ */
+static int extcon_alloc_groups(struct extcon_dev *edev)
+{
+       int index;
+
+       if (!edev)
+               return -EINVAL;
+
+       if (!edev->max_supported)
+               return 0;
+
+       edev->extcon_dev_type.groups = kcalloc(edev->max_supported + 2,
+                                         sizeof(*edev->extcon_dev_type.groups),
+                                         GFP_KERNEL);
+       if (!edev->extcon_dev_type.groups)
+               return -ENOMEM;
+
+       edev->extcon_dev_type.name = dev_name(&edev->dev);
+       edev->extcon_dev_type.release = dummy_sysfs_dev_release;
+
+       for (index = 0; index < edev->max_supported; index++)
+               edev->extcon_dev_type.groups[index] = &edev->cables[index].attr_g;
+
+       if (edev->mutually_exclusive)
+               edev->extcon_dev_type.groups[index] = &edev->attr_g_muex;
+
+       edev->dev.type = &edev->extcon_dev_type;
+
+       return 0;
+}
+
 /**
  * extcon_dev_register() - Register an new extcon device
  * @edev:      the extcon device to be registered
@@ -1085,19 +1246,16 @@ EXPORT_SYMBOL_GPL(extcon_dev_free);
  */
 int extcon_dev_register(struct extcon_dev *edev)
 {
-       int ret, index = 0;
-       static atomic_t edev_no = ATOMIC_INIT(-1);
+       int ret, index;
 
-       if (!extcon_class) {
-               ret = create_extcon_class();
-               if (ret < 0)
-                       return ret;
-       }
+       ret = create_extcon_class();
+       if (ret < 0)
+               return ret;
 
        if (!edev || !edev->supported_cable)
                return -EINVAL;
 
-       for (; edev->supported_cable[index] != EXTCON_NONE; index++);
+       for (index = 0; edev->supported_cable[index] != EXTCON_NONE; index++);
 
        edev->max_supported = index;
        if (index > SUPPORTED_CABLE_MAX) {
@@ -1115,124 +1273,26 @@ int extcon_dev_register(struct extcon_dev *edev)
                        "extcon device name is null\n");
                return -EINVAL;
        }
-       dev_set_name(&edev->dev, "extcon%lu",
-                       (unsigned long)atomic_inc_return(&edev_no));
-
-       if (edev->max_supported) {
-               char *str;
-               struct extcon_cable *cable;
-
-               edev->cables = kcalloc(edev->max_supported,
-                                      sizeof(struct extcon_cable),
-                                      GFP_KERNEL);
-               if (!edev->cables) {
-                       ret = -ENOMEM;
-                       goto err_sysfs_alloc;
-               }
-               for (index = 0; index < edev->max_supported; index++) {
-                       cable = &edev->cables[index];
-
-                       str = kasprintf(GFP_KERNEL, "cable.%d", index);
-                       if (!str) {
-                               for (index--; index >= 0; index--) {
-                                       cable = &edev->cables[index];
-                                       kfree(cable->attr_g.name);
-                               }
-                               ret = -ENOMEM;
-
-                               goto err_alloc_cables;
-                       }
-
-                       cable->edev = edev;
-                       cable->cable_index = index;
-                       cable->attrs[0] = &cable->attr_name.attr;
-                       cable->attrs[1] = &cable->attr_state.attr;
-                       cable->attrs[2] = NULL;
-                       cable->attr_g.name = str;
-                       cable->attr_g.attrs = cable->attrs;
-
-                       sysfs_attr_init(&cable->attr_name.attr);
-                       cable->attr_name.attr.name = "name";
-                       cable->attr_name.attr.mode = 0444;
-                       cable->attr_name.show = cable_name_show;
-
-                       sysfs_attr_init(&cable->attr_state.attr);
-                       cable->attr_state.attr.name = "state";
-                       cable->attr_state.attr.mode = 0444;
-                       cable->attr_state.show = cable_state_show;
-               }
-       }
 
-       if (edev->max_supported && edev->mutually_exclusive) {
-               char *name;
-
-               /* Count the size of mutually_exclusive array */
-               for (index = 0; edev->mutually_exclusive[index]; index++)
-                       ;
-
-               edev->attrs_muex = kcalloc(index + 1,
-                                          sizeof(struct attribute *),
-                                          GFP_KERNEL);
-               if (!edev->attrs_muex) {
-                       ret = -ENOMEM;
-                       goto err_muex;
-               }
-
-               edev->d_attrs_muex = kcalloc(index,
-                                            sizeof(struct device_attribute),
-                                            GFP_KERNEL);
-               if (!edev->d_attrs_muex) {
-                       ret = -ENOMEM;
-                       kfree(edev->attrs_muex);
-                       goto err_muex;
-               }
-
-               for (index = 0; edev->mutually_exclusive[index]; index++) {
-                       name = kasprintf(GFP_KERNEL, "0x%x",
-                                        edev->mutually_exclusive[index]);
-                       if (!name) {
-                               for (index--; index >= 0; index--) {
-                                       kfree(edev->d_attrs_muex[index].attr.
-                                             name);
-                               }
-                               kfree(edev->d_attrs_muex);
-                               kfree(edev->attrs_muex);
-                               ret = -ENOMEM;
-                               goto err_muex;
-                       }
-                       sysfs_attr_init(&edev->d_attrs_muex[index].attr);
-                       edev->d_attrs_muex[index].attr.name = name;
-                       edev->d_attrs_muex[index].attr.mode = 0000;
-                       edev->attrs_muex[index] = &edev->d_attrs_muex[index]
-                                                       .attr;
-               }
-               edev->attr_g_muex.name = muex_name;
-               edev->attr_g_muex.attrs = edev->attrs_muex;
+       ret = ida_alloc(&extcon_dev_ids, GFP_KERNEL);
+       if (ret < 0)
+               return ret;
 
-       }
+       edev->id = ret;
 
-       if (edev->max_supported) {
-               edev->extcon_dev_type.groups =
-                       kcalloc(edev->max_supported + 2,
-                               sizeof(struct attribute_group *),
-                               GFP_KERNEL);
-               if (!edev->extcon_dev_type.groups) {
-                       ret = -ENOMEM;
-                       goto err_alloc_groups;
-               }
+       dev_set_name(&edev->dev, "extcon%d", edev->id);
 
-               edev->extcon_dev_type.name = dev_name(&edev->dev);
-               edev->extcon_dev_type.release = dummy_sysfs_dev_release;
+       ret = extcon_alloc_cables(edev);
+       if (ret < 0)
+               goto err_alloc_cables;
 
-               for (index = 0; index < edev->max_supported; index++)
-                       edev->extcon_dev_type.groups[index] =
-                               &edev->cables[index].attr_g;
-               if (edev->mutually_exclusive)
-                       edev->extcon_dev_type.groups[index] =
-                               &edev->attr_g_muex;
+       ret = extcon_alloc_muex(edev);
+       if (ret < 0)
+               goto err_alloc_muex;
 
-               edev->dev.type = &edev->extcon_dev_type;
-       }
+       ret = extcon_alloc_groups(edev);
+       if (ret < 0)
+               goto err_alloc_groups;
 
        spin_lock_init(&edev->lock);
        if (edev->max_supported) {
@@ -1277,13 +1337,14 @@ err_alloc_groups:
                kfree(edev->d_attrs_muex);
                kfree(edev->attrs_muex);
        }
-err_muex:
+err_alloc_muex:
        for (index = 0; index < edev->max_supported; index++)
                kfree(edev->cables[index].attr_g.name);
-err_alloc_cables:
        if (edev->max_supported)
                kfree(edev->cables);
-err_sysfs_alloc:
+err_alloc_cables:
+       ida_free(&extcon_dev_ids, edev->id);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(extcon_dev_register);
@@ -1306,12 +1367,13 @@ void extcon_dev_unregister(struct extcon_dev *edev)
        list_del(&edev->entry);
        mutex_unlock(&extcon_dev_list_lock);
 
-       if (IS_ERR_OR_NULL(get_device(&edev->dev))) {
-               dev_err(&edev->dev, "Failed to unregister extcon_dev (%s)\n",
-                               dev_name(&edev->dev));
+       if (!get_device(&edev->dev)) {
+               dev_err(&edev->dev, "Failed to unregister extcon_dev\n");
                return;
        }
 
+       ida_free(&extcon_dev_ids, edev->id);
+
        device_unregister(&edev->dev);
 
        if (edev->mutually_exclusive && edev->max_supported) {
@@ -1349,7 +1411,7 @@ struct extcon_dev *extcon_find_edev_by_node(struct device_node *node)
 
        mutex_lock(&extcon_dev_list_lock);
        list_for_each_entry(edev, &extcon_dev_list, entry)
-               if (edev->dev.parent && edev->dev.parent->of_node == node)
+               if (edev->dev.parent && device_match_of_node(edev->dev.parent, node))
                        goto out;
        edev = ERR_PTR(-EPROBE_DEFER);
 out:
@@ -1367,21 +1429,17 @@ out:
  */
 struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
 {
-       struct device_node *node;
+       struct device_node *node, *np = dev_of_node(dev);
        struct extcon_dev *edev;
 
-       if (!dev)
-               return ERR_PTR(-EINVAL);
-
-       if (!dev->of_node) {
+       if (!np) {
                dev_dbg(dev, "device does not have a device node entry\n");
                return ERR_PTR(-EINVAL);
        }
 
-       node = of_parse_phandle(dev->of_node, "extcon", index);
+       node = of_parse_phandle(np, "extcon", index);
        if (!node) {
-               dev_dbg(dev, "failed to get phandle in %pOF node\n",
-                       dev->of_node);
+               dev_dbg(dev, "failed to get phandle in %pOF node\n", np);
                return ERR_PTR(-ENODEV);
        }
 
index 93b5e0306966d50bb1e582ff3bb5049a0ad6f8f4..94618268778603bf66a8330a26f536214cc35311 100644 (file)
  *                     are disabled.
  * @mutually_exclusive:        Array of mutually exclusive set of cables that cannot
  *                     be attached simultaneously. The array should be
- *                     ending with NULL or be NULL (no mutually exclusive
- *                     cables). For example, if it is { 0x7, 0x30, 0}, then,
+ *                     ending with 0 or be NULL (no mutually exclusive cables).
+ *                     For example, if it is {0x7, 0x30, 0}, then,
  *                     {0, 1}, {0, 1, 2}, {0, 2}, {1, 2}, or {4, 5} cannot
  *                     be attached simulataneously. {0x7, 0} is equivalent to
  *                     {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there
  *                     can be no simultaneous connections.
  * @dev:               Device of this extcon.
+ * @id:                        Unique device ID of this extcon.
  * @state:             Attach/detach state of this extcon. Do not provide at
  *                     register-time.
  * @nh_all:            Notifier for the state change events for all supported
@@ -27,7 +28,7 @@
  * @nh:                        Notifier for the state change events from this extcon
  * @entry:             To support list of extcon devices so that users can
  *                     search for extcon devices based on the extcon name.
- * @lock:
+ * @lock:              Protects device state and serialises device registration
  * @max_supported:     Internal value to store the number of cables.
  * @extcon_dev_type:   Device_type struct to provide attribute_groups
  *                     customized for each extcon device.
@@ -46,6 +47,7 @@ struct extcon_dev {
 
        /* Internal data. Please do not set. */
        struct device dev;
+       unsigned int id;
        struct raw_notifier_head nh_all;
        struct raw_notifier_head *nh;
        struct list_head entry;
index af22be84034bba2cc310de835d045b788d40b00f..538bd677c254a9a148b5d2772d56f16559db4f07 100644 (file)
@@ -706,21 +706,22 @@ static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,
        int rcode;
 
        if (destination == IEEE1394_ALL_NODES) {
-               kfree(r);
-
-               return;
-       }
-
-       if (offset != dev->handler.offset)
+               // Although the response to the broadcast packet is not necessarily required, the
+               // fw_send_response() function should still be called to maintain the reference
+               // counting of the object. In the case, the call of function just releases the
+               // object as a result to decrease the reference counting.
+               rcode = RCODE_COMPLETE;
+       } else if (offset != dev->handler.offset) {
                rcode = RCODE_ADDRESS_ERROR;
-       else if (tcode != TCODE_WRITE_BLOCK_REQUEST)
+       } else if (tcode != TCODE_WRITE_BLOCK_REQUEST) {
                rcode = RCODE_TYPE_ERROR;
-       else if (fwnet_incoming_packet(dev, payload, length,
-                                      source, generation, false) != 0) {
+       else if (fwnet_incoming_packet(dev, payload, length,
+                                        source, generation, false) != 0) {
                dev_err(&dev->netdev->dev, "incoming packet failure\n");
                rcode = RCODE_CONFLICT_ERROR;
-       } else
+       } else {
                rcode = RCODE_COMPLETE;
+       }
 
        fw_send_response(card, r, rcode);
 }
index f29d77ecf72db613724dc175cdba1a001fc0ac60..2b8bfcd010f5fd34e59b3eacdec0677e6692f020 100644 (file)
@@ -15,6 +15,8 @@
 
 #include "common.h"
 
+static DEFINE_IDA(ffa_bus_id);
+
 static int ffa_device_match(struct device *dev, struct device_driver *drv)
 {
        const struct ffa_device_id *id_table;
@@ -53,7 +55,8 @@ static void ffa_device_remove(struct device *dev)
 {
        struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
 
-       ffa_drv->remove(to_ffa_dev(dev));
+       if (ffa_drv->remove)
+               ffa_drv->remove(to_ffa_dev(dev));
 }
 
 static int ffa_device_uevent(const struct device *dev, struct kobj_uevent_env *env)
@@ -130,6 +133,7 @@ static void ffa_release_device(struct device *dev)
 {
        struct ffa_device *ffa_dev = to_ffa_dev(dev);
 
+       ida_free(&ffa_bus_id, ffa_dev->id);
        kfree(ffa_dev);
 }
 
@@ -170,18 +174,24 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev)
 struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
                                       const struct ffa_ops *ops)
 {
-       int ret;
+       int id, ret;
        struct device *dev;
        struct ffa_device *ffa_dev;
 
+       id = ida_alloc_min(&ffa_bus_id, 1, GFP_KERNEL);
+       if (id < 0)
+               return NULL;
+
        ffa_dev = kzalloc(sizeof(*ffa_dev), GFP_KERNEL);
-       if (!ffa_dev)
+       if (!ffa_dev) {
+               ida_free(&ffa_bus_id, id);
                return NULL;
+       }
 
        dev = &ffa_dev->dev;
        dev->bus = &ffa_bus_type;
        dev->release = ffa_release_device;
-       dev_set_name(&ffa_dev->dev, "arm-ffa-%04x", vm_id);
+       dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id);
 
        ffa_dev->vm_id = vm_id;
        ffa_dev->ops = ops;
@@ -217,4 +227,5 @@ void arm_ffa_bus_exit(void)
 {
        ffa_devices_unregister();
        bus_unregister(&ffa_bus_type);
+       ida_destroy(&ffa_bus_id);
 }
index fa85c64d3dede7edcc6c35b3d9959b868405d7a2..e234091386671f7b508397fe6775e889ea7fc620 100644 (file)
@@ -193,7 +193,8 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
        int idx, count, flags = 0, sz, buf_sz;
        ffa_value_t partition_info;
 
-       if (!buffer || !num_partitions) /* Just get the count for now */
+       if (drv_info->version > FFA_VERSION_1_0 &&
+           (!buffer || !num_partitions)) /* Just get the count for now */
                flags = PARTITION_INFO_GET_RETURN_COUNT_ONLY;
 
        mutex_lock(&drv_info->rx_lock);
@@ -420,12 +421,17 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
                ep_mem_access->receiver = args->attrs[idx].receiver;
                ep_mem_access->attrs = args->attrs[idx].attrs;
                ep_mem_access->composite_off = COMPOSITE_OFFSET(args->nattrs);
+               ep_mem_access->flag = 0;
+               ep_mem_access->reserved = 0;
        }
+       mem_region->reserved_0 = 0;
+       mem_region->reserved_1 = 0;
        mem_region->ep_count = args->nattrs;
 
        composite = buffer + COMPOSITE_OFFSET(args->nattrs);
        composite->total_pg_cnt = ffa_get_num_pages_sg(args->sg);
        composite->addr_range_cnt = num_entries;
+       composite->reserved = 0;
 
        length = COMPOSITE_CONSTITUENTS_OFFSET(args->nattrs, num_entries);
        frag_len = COMPOSITE_CONSTITUENTS_OFFSET(args->nattrs, 0);
@@ -460,6 +466,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
 
                constituents->address = sg_phys(args->sg);
                constituents->pg_cnt = args->sg->length / FFA_PAGE_SIZE;
+               constituents->reserved = 0;
                constituents++;
                frag_len += sizeof(struct ffa_mem_region_addr_range);
        } while ((args->sg = sg_next(args->sg)));
index d40df099fd515276b87cdde144271c60954b46be..6971dcf72fb998425655865fd6ccf4e1ecb44976 100644 (file)
@@ -1066,7 +1066,7 @@ static int scmi_xfer_raw_worker_init(struct scmi_raw_mode_info *raw)
 
        raw->wait_wq = alloc_workqueue("scmi-raw-wait-wq-%d",
                                       WQ_UNBOUND | WQ_FREEZABLE |
-                                      WQ_HIGHPRI, WQ_SYSFS, raw->id);
+                                      WQ_HIGHPRI | WQ_SYSFS, 0, raw->id);
        if (!raw->wait_wq)
                return -ENOMEM;
 
index 03708ab64e56c45f5a7eb02b8e05e710b0e8785c..8d91997036e4c39731019e8082e80da3d733d4e3 100644 (file)
@@ -310,6 +310,7 @@ static const struct kobj_type dmi_system_event_log_ktype = {
        .default_groups = dmi_sysfs_sel_groups,
 };
 
+#ifdef CONFIG_HAS_IOPORT
 typedef u8 (*sel_io_reader)(const struct dmi_system_event_log *sel,
                            loff_t offset);
 
@@ -374,6 +375,7 @@ static ssize_t dmi_sel_raw_read_io(struct dmi_sysfs_entry *entry,
 
        return wrote;
 }
+#endif
 
 static ssize_t dmi_sel_raw_read_phys32(struct dmi_sysfs_entry *entry,
                                       const struct dmi_system_event_log *sel,
@@ -409,11 +411,13 @@ static ssize_t dmi_sel_raw_read_helper(struct dmi_sysfs_entry *entry,
        memcpy(&sel, dh, sizeof(sel));
 
        switch (sel.access_method) {
+#ifdef CONFIG_HAS_IOPORT
        case DMI_SEL_ACCESS_METHOD_IO8:
        case DMI_SEL_ACCESS_METHOD_IO2x8:
        case DMI_SEL_ACCESS_METHOD_IO16:
                return dmi_sel_raw_read_io(entry, &sel, state->buf,
                                           state->pos, state->count);
+#endif
        case DMI_SEL_ACCESS_METHOD_PHYS32:
                return dmi_sel_raw_read_phys32(entry, &sel, state->buf,
                                               state->pos, state->count);
index 89ef820f3b34483a55cd6f9b30043910922da75e..2c489627a8078945f26071644cc5e5390c2ee0d9 100644 (file)
@@ -32,7 +32,8 @@ zboot-size-len-$(CONFIG_KERNEL_GZIP)   := 0
 $(obj)/vmlinuz: $(obj)/vmlinux.bin FORCE
        $(call if_changed,$(zboot-method-y))
 
-OBJCOPYFLAGS_vmlinuz.o := -I binary -O $(EFI_ZBOOT_BFD_TARGET) $(EFI_ZBOOT_OBJCOPY_FLAGS) \
+# avoid eager evaluation to prevent references to non-existent build artifacts
+OBJCOPYFLAGS_vmlinuz.o = -I binary -O $(EFI_ZBOOT_BFD_TARGET) $(EFI_ZBOOT_OBJCOPY_FLAGS) \
                          --rename-section .data=.gzdata,load,alloc,readonly,contents
 $(obj)/vmlinuz.o: $(obj)/vmlinuz FORCE
        $(call if_changed,objcopy)
index 67d5a20802e0b7c6bff01a8da5c083f1768b6e58..54a2822cae7714584c668dd9e0650350e30922df 100644 (file)
@@ -1133,4 +1133,7 @@ const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
 void efi_remap_image(unsigned long image_base, unsigned alloc_size,
                     unsigned long code_size);
 
+asmlinkage efi_status_t __efiapi
+efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab);
+
 #endif
index 80f4e2d14e046210e6ac4e55c173b3aa6c9ed20e..2d674126160fe3c12873c47d9d886d4abcc0c3a2 100644 (file)
@@ -755,7 +755,7 @@ svc_create_memory_pool(struct platform_device *pdev,
        end = rounddown(sh_memory->addr + sh_memory->size, PAGE_SIZE);
        paddr = begin;
        size = end - begin;
-       va = memremap(paddr, size, MEMREMAP_WC);
+       va = devm_memremap(dev, paddr, size, MEMREMAP_WC);
        if (!va) {
                dev_err(dev, "fail to remap shared memory\n");
                return ERR_PTR(-EINVAL);
index 82c64cb9f5316c230fcb25b34936f96f92e215d1..74363ed7501f64ac95382094850756b5b02cda7e 100644 (file)
@@ -51,7 +51,8 @@ __init bool sysfb_parse_mode(const struct screen_info *si,
         *
         * It's not easily possible to fix this in struct screen_info,
         * as this could break UAPI. The best solution is to compute
-        * bits_per_pixel here and ignore lfb_depth. In the loop below,
+        * bits_per_pixel from the color bits, reserved bits and
+        * reported lfb_depth, whichever is highest.  In the loop below,
         * ignore simplefb formats with alpha bits, as EFI and VESA
         * don't specify alpha channels.
         */
@@ -60,6 +61,7 @@ __init bool sysfb_parse_mode(const struct screen_info *si,
                                          si->green_size + si->green_pos,
                                          si->blue_size + si->blue_pos),
                                     si->rsvd_size + si->rsvd_pos);
+               bits_per_pixel = max_t(u32, bits_per_pixel, si->lfb_depth);
        } else {
                bits_per_pixel = si->lfb_depth;
        }
index 99606b34975e93a6719d2ff565f275b32396e900..8528850af889265c16614bcac5219a41565db0da 100644 (file)
@@ -4,7 +4,7 @@
  *
  *  Copyright (C) 2014-2018 Xilinx, Inc.
  *
- *  Michal Simek <michal.simek@xilinx.com>
+ *  Michal Simek <michal.simek@amd.com>
  *  Davorin Mista <davorin.mista@aggios.com>
  *  Jolly Shah <jollys@xilinx.com>
  *  Rajan Vaja <rajanv@xilinx.com>
index 9929f8b433f50678f7b71dfd4ff0a459cd0a81af..e1515a93e9e99b1f2dd79d86d35722e83545960f 100644 (file)
@@ -4,7 +4,7 @@
  *
  *  Copyright (C) 2014-2018 Xilinx
  *
- *  Michal Simek <michal.simek@xilinx.com>
+ *  Michal Simek <michal.simek@amd.com>
  *  Davorin Mista <davorin.mista@aggios.com>
  *  Jolly Shah <jollys@xilinx.com>
  *  Rajan Vaja <rajanv@xilinx.com>
index a736db4a582574c315585996c2d54cc8fcf80cbb..60eb6bd8f9573f29325c2d668ad8f487bebe527a 100644 (file)
@@ -4,7 +4,7 @@
  *
  *  Copyright (C) 2014-2022 Xilinx, Inc.
  *
- *  Michal Simek <michal.simek@xilinx.com>
+ *  Michal Simek <michal.simek@amd.com>
  *  Davorin Mista <davorin.mista@aggios.com>
  *  Jolly Shah <jollys@xilinx.com>
  *  Rajan Vaja <rajanv@xilinx.com>
index 77ea04d4edbef52cbe272c500448924e5d1785d9..bcb5d34b3b820c7ba8e92011c2d6898384d76889 100644 (file)
@@ -265,7 +265,7 @@ static const struct hwmon_ops thermal_hwmon_ops = {
        .read = thermal_hwmon_read,
 };
 
-static const struct hwmon_channel_info *thermal_hwmon_info[] = {
+static const struct hwmon_channel_info * const thermal_hwmon_info[] = {
        HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_EMERGENCY |
                                 HWMON_T_MAX   | HWMON_T_MAX_ALARM |
                                 HWMON_T_CRIT  | HWMON_T_CRIT_ALARM),
@@ -465,7 +465,7 @@ static const struct hwmon_ops power_hwmon_ops = {
        .write = power_hwmon_write,
 };
 
-static const struct hwmon_channel_info *power_hwmon_info[] = {
+static const struct hwmon_channel_info * const power_hwmon_info[] = {
        HWMON_CHANNEL_INFO(power, HWMON_P_INPUT |
                                  HWMON_P_MAX   | HWMON_P_MAX_ALARM |
                                  HWMON_P_CRIT  | HWMON_P_CRIT_ALARM),
index ae0da361e6c6282448995155fa2aa6e8cd5f11be..f8214cae9b6eca7bdd7a49d24ee89bca3d6c7ccd 100644 (file)
@@ -493,15 +493,15 @@ static int zynq_fpga_ops_write_complete(struct fpga_manager *mgr,
        if (err)
                return err;
 
-       /* Release 'PR' control back to the ICAP */
-       zynq_fpga_write(priv, CTRL_OFFSET,
-               zynq_fpga_read(priv, CTRL_OFFSET) & ~CTRL_PCAP_PR_MASK);
-
        err = zynq_fpga_poll_timeout(priv, INT_STS_OFFSET, intr_status,
                                     intr_status & IXR_PCFG_DONE_MASK,
                                     INIT_POLL_DELAY,
                                     INIT_POLL_TIMEOUT);
 
+       /* Release 'PR' control back to the ICAP */
+       zynq_fpga_write(priv, CTRL_OFFSET,
+                       zynq_fpga_read(priv, CTRL_OFFSET) & ~CTRL_PCAP_PR_MASK);
+
        clk_disable(priv->clk);
 
        if (err)
index 5521f060d58e9df3c45ab9bef89295eb3efac6aa..f45c6a36551c75533a92d6c6bf5897162b9ee5e8 100644 (file)
@@ -897,7 +897,7 @@ config GPIO_F7188X
        help
          This option enables support for GPIOs found on Fintek Super-I/O
          chips F71869, F71869A, F71882FG, F71889F and F81866.
-         As well as Nuvoton Super-I/O chip NCT6116D.
+         As well as Nuvoton Super-I/O chip NCT6126D.
 
          To compile this driver as a module, choose M here: the module will
          be called f7188x-gpio.
index 9effa7769bef5bcdea5865b964f78f261da40dfe..f54ca5a1775ea2178004e747286660bcf83900d1 100644 (file)
@@ -48,7 +48,7 @@
 /*
  * Nuvoton devices.
  */
-#define SIO_NCT6116D_ID                0xD283  /* NCT6116D chipset ID */
+#define SIO_NCT6126D_ID                0xD283  /* NCT6126D chipset ID */
 
 #define SIO_LD_GPIO_NUVOTON    0x07    /* GPIO logical device */
 
@@ -62,7 +62,7 @@ enum chips {
        f81866,
        f81804,
        f81865,
-       nct6116d,
+       nct6126d,
 };
 
 static const char * const f7188x_names[] = {
@@ -74,7 +74,7 @@ static const char * const f7188x_names[] = {
        "f81866",
        "f81804",
        "f81865",
-       "nct6116d",
+       "nct6126d",
 };
 
 struct f7188x_sio {
@@ -187,8 +187,8 @@ static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
 /* Output mode register (0:open drain 1:push-pull). */
 #define f7188x_gpio_out_mode(base) ((base) + 3)
 
-#define f7188x_gpio_dir_invert(type)   ((type) == nct6116d)
-#define f7188x_gpio_data_single(type)  ((type) == nct6116d)
+#define f7188x_gpio_dir_invert(type)   ((type) == nct6126d)
+#define f7188x_gpio_data_single(type)  ((type) == nct6126d)
 
 static struct f7188x_gpio_bank f71869_gpio_bank[] = {
        F7188X_GPIO_BANK(0, 6, 0xF0, DRVNAME "-0"),
@@ -274,7 +274,7 @@ static struct f7188x_gpio_bank f81865_gpio_bank[] = {
        F7188X_GPIO_BANK(60, 5, 0x90, DRVNAME "-6"),
 };
 
-static struct f7188x_gpio_bank nct6116d_gpio_bank[] = {
+static struct f7188x_gpio_bank nct6126d_gpio_bank[] = {
        F7188X_GPIO_BANK(0, 8, 0xE0, DRVNAME "-0"),
        F7188X_GPIO_BANK(10, 8, 0xE4, DRVNAME "-1"),
        F7188X_GPIO_BANK(20, 8, 0xE8, DRVNAME "-2"),
@@ -282,7 +282,7 @@ static struct f7188x_gpio_bank nct6116d_gpio_bank[] = {
        F7188X_GPIO_BANK(40, 8, 0xF0, DRVNAME "-4"),
        F7188X_GPIO_BANK(50, 8, 0xF4, DRVNAME "-5"),
        F7188X_GPIO_BANK(60, 8, 0xF8, DRVNAME "-6"),
-       F7188X_GPIO_BANK(70, 1, 0xFC, DRVNAME "-7"),
+       F7188X_GPIO_BANK(70, 8, 0xFC, DRVNAME "-7"),
 };
 
 static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
@@ -490,9 +490,9 @@ static int f7188x_gpio_probe(struct platform_device *pdev)
                data->nr_bank = ARRAY_SIZE(f81865_gpio_bank);
                data->bank = f81865_gpio_bank;
                break;
-       case nct6116d:
-               data->nr_bank = ARRAY_SIZE(nct6116d_gpio_bank);
-               data->bank = nct6116d_gpio_bank;
+       case nct6126d:
+               data->nr_bank = ARRAY_SIZE(nct6126d_gpio_bank);
+               data->bank = nct6126d_gpio_bank;
                break;
        default:
                return -ENODEV;
@@ -559,9 +559,9 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio)
        case SIO_F81865_ID:
                sio->type = f81865;
                break;
-       case SIO_NCT6116D_ID:
+       case SIO_NCT6126D_ID:
                sio->device = SIO_LD_GPIO_NUVOTON;
-               sio->type = nct6116d;
+               sio->type = nct6126d;
                break;
        default:
                pr_info("Unsupported Fintek device 0x%04x\n", devid);
@@ -569,7 +569,7 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio)
        }
 
        /* double check manufacturer where possible */
-       if (sio->type != nct6116d) {
+       if (sio->type != nct6126d) {
                manid = superio_inw(addr, SIO_FINTEK_MANID);
                if (manid != SIO_FINTEK_ID) {
                        pr_debug("Not a Fintek device at 0x%08x\n", addr);
@@ -581,7 +581,7 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio)
        err = 0;
 
        pr_info("Found %s at %#x\n", f7188x_names[sio->type], (unsigned int)addr);
-       if (sio->type != nct6116d)
+       if (sio->type != nct6126d)
                pr_info("   revision %d\n", superio_inb(addr, SIO_FINTEK_DEVREV));
 
 err:
index e6a7049bef6417affd16c79982d3eeb7c4e6c255..b32063ac845a5073f67593c433f2fcc7694362c7 100644 (file)
@@ -369,7 +369,7 @@ static void gpio_mockup_debugfs_setup(struct device *dev,
                priv->offset = i;
                priv->desc = gpiochip_get_desc(gc, i);
 
-               debugfs_create_file(name, 0200, chip->dbg_dir, priv,
+               debugfs_create_file(name, 0600, chip->dbg_dir, priv,
                                    &gpio_mockup_debugfs_ops);
        }
 }
index 04fb05df805b016a08b8b70703ddcb7675795ff4..a7220e04a93e562dbc345705c36738a8464282f4 100644 (file)
@@ -209,6 +209,8 @@ static int gpiochip_find_base(int ngpio)
                        break;
                /* nope, check the space right after the chip */
                base = gdev->base + gdev->ngpio;
+               if (base < GPIO_DYNAMIC_BASE)
+                       base = GPIO_DYNAMIC_BASE;
        }
 
        if (gpio_is_valid(base)) {
index 981a9cfb63b5779f0ef51d56523335d188993c0f..5c7d40873ee208b212b5d95b5d69bc6f303c193a 100644 (file)
@@ -3757,6 +3757,12 @@ int amdgpu_device_init(struct amdgpu_device *adev,
                adev->have_atomics_support = ((struct amd_sriov_msg_pf2vf_info *)
                        adev->virt.fw_reserve.p_pf2vf)->pcie_atomic_ops_support_flags ==
                        (PCI_EXP_DEVCAP2_ATOMIC_COMP32 | PCI_EXP_DEVCAP2_ATOMIC_COMP64);
+       /* APUs w/ gfx9 onwards doesn't reply on PCIe atomics, rather it is a
+        * internal path natively support atomics, set have_atomics_support to true.
+        */
+       else if ((adev->flags & AMD_IS_APU) &&
+               (adev->ip_versions[GC_HWIP][0] > IP_VERSION(9, 0, 0)))
+               adev->have_atomics_support = true;
        else
                adev->have_atomics_support =
                        !pci_enable_atomic_ops_to_root(adev->pdev,
@@ -4506,7 +4512,11 @@ static int amdgpu_device_recover_vram(struct amdgpu_device *adev)
        dev_info(adev->dev, "recover vram bo from shadow start\n");
        mutex_lock(&adev->shadow_list_lock);
        list_for_each_entry(vmbo, &adev->shadow_list, shadow_list) {
-               shadow = &vmbo->bo;
+               /* If vm is compute context or adev is APU, shadow will be NULL */
+               if (!vmbo->shadow)
+                       continue;
+               shadow = vmbo->shadow;
+
                /* No need to recover an evicted BO */
                if (shadow->tbo.resource->mem_type != TTM_PL_TT ||
                    shadow->tbo.resource->start == AMDGPU_BO_INVALID_OFFSET ||
index f52d0ba91a770a4b437a1137aa88cf6a7113cf53..a7d250809da99e9e13c95c07e57bdb7da4283b08 100644 (file)
@@ -582,7 +582,8 @@ void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev)
                if (r)
                        amdgpu_fence_driver_force_completion(ring);
 
-               if (ring->fence_drv.irq_src)
+               if (!drm_dev_is_unplugged(adev_to_drm(adev)) &&
+                   ring->fence_drv.irq_src)
                        amdgpu_irq_put(adev, ring->fence_drv.irq_src,
                                       ring->fence_drv.irq_type);
 
index 9d3a0542c9967578b32f02de9060490236ec304f..f3f541ba0acaa0fdf6761ad80b0e5fe10b27a1a6 100644 (file)
@@ -687,9 +687,11 @@ int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *r
                if (r)
                        return r;
 
-               r = amdgpu_irq_get(adev, &adev->gfx.cp_ecc_error_irq, 0);
-               if (r)
-                       goto late_fini;
+               if (adev->gfx.cp_ecc_error_irq.funcs) {
+                       r = amdgpu_irq_get(adev, &adev->gfx.cp_ecc_error_irq, 0);
+                       if (r)
+                               goto late_fini;
+               }
        } else {
                amdgpu_ras_feature_enable_on_boot(adev, ras_block, 0);
        }
index 4e2531758866c6e370622152661efcddf218a31b..95b0f984acbfd8eecf062627b30c841e96e621af 100644 (file)
@@ -593,6 +593,8 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev)
        case IP_VERSION(9, 3, 0):
        /* GC 10.3.7 */
        case IP_VERSION(10, 3, 7):
+       /* GC 11.0.1 */
+       case IP_VERSION(11, 0, 1):
                if (amdgpu_tmz == 0) {
                        adev->gmc.tmz_enabled = false;
                        dev_info(adev->dev,
@@ -616,7 +618,6 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev)
        case IP_VERSION(10, 3, 1):
        /* YELLOW_CARP*/
        case IP_VERSION(10, 3, 3):
-       case IP_VERSION(11, 0, 1):
        case IP_VERSION(11, 0, 4):
                /* Don't enable it by default yet.
                 */
index b07c000fc8ba39ee60540312eb8c0e6ee439d8e0..4fa019c8aefc4ddf730fb69f8fa9b7185c9c2c9b 100644 (file)
@@ -241,6 +241,31 @@ int amdgpu_jpeg_process_poison_irq(struct amdgpu_device *adev,
        return 0;
 }
 
+int amdgpu_jpeg_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block)
+{
+       int r, i;
+
+       r = amdgpu_ras_block_late_init(adev, ras_block);
+       if (r)
+               return r;
+
+       if (amdgpu_ras_is_supported(adev, ras_block->block)) {
+               for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+                       if (adev->jpeg.harvest_config & (1 << i))
+                               continue;
+
+                       r = amdgpu_irq_get(adev, &adev->jpeg.inst[i].ras_poison_irq, 0);
+                       if (r)
+                               goto late_fini;
+               }
+       }
+       return 0;
+
+late_fini:
+       amdgpu_ras_block_late_fini(adev, ras_block);
+       return r;
+}
+
 int amdgpu_jpeg_ras_sw_init(struct amdgpu_device *adev)
 {
        int err;
@@ -262,7 +287,7 @@ int amdgpu_jpeg_ras_sw_init(struct amdgpu_device *adev)
        adev->jpeg.ras_if = &ras->ras_block.ras_comm;
 
        if (!ras->ras_block.ras_late_init)
-               ras->ras_block.ras_late_init = amdgpu_ras_block_late_init;
+               ras->ras_block.ras_late_init = amdgpu_jpeg_ras_late_init;
 
        return 0;
 }
index 0ca76f0f23e9c8a0b980050cfbf27afa7307ef34..1471a1ebb03449fd939cbd8aa6a6501fd9c9b9c3 100644 (file)
@@ -38,6 +38,7 @@ struct amdgpu_jpeg_reg{
 struct amdgpu_jpeg_inst {
        struct amdgpu_ring ring_dec;
        struct amdgpu_irq_src irq;
+       struct amdgpu_irq_src ras_poison_irq;
        struct amdgpu_jpeg_reg external;
 };
 
@@ -72,6 +73,8 @@ int amdgpu_jpeg_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout);
 int amdgpu_jpeg_process_poison_irq(struct amdgpu_device *adev,
                                struct amdgpu_irq_src *source,
                                struct amdgpu_iv_entry *entry);
+int amdgpu_jpeg_ras_late_init(struct amdgpu_device *adev,
+                               struct ras_common_if *ras_block);
 int amdgpu_jpeg_ras_sw_init(struct amdgpu_device *adev);
 
 #endif /*__AMDGPU_JPEG_H__*/
index e63fcc58e8e0622f90599733b862a3953f902622..2d94f1b63bd6c4463ceef185b7726c27ad250ec5 100644 (file)
@@ -1181,6 +1181,31 @@ int amdgpu_vcn_process_poison_irq(struct amdgpu_device *adev,
        return 0;
 }
 
+int amdgpu_vcn_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block)
+{
+       int r, i;
+
+       r = amdgpu_ras_block_late_init(adev, ras_block);
+       if (r)
+               return r;
+
+       if (amdgpu_ras_is_supported(adev, ras_block->block)) {
+               for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+                       if (adev->vcn.harvest_config & (1 << i))
+                               continue;
+
+                       r = amdgpu_irq_get(adev, &adev->vcn.inst[i].ras_poison_irq, 0);
+                       if (r)
+                               goto late_fini;
+               }
+       }
+       return 0;
+
+late_fini:
+       amdgpu_ras_block_late_fini(adev, ras_block);
+       return r;
+}
+
 int amdgpu_vcn_ras_sw_init(struct amdgpu_device *adev)
 {
        int err;
@@ -1202,7 +1227,7 @@ int amdgpu_vcn_ras_sw_init(struct amdgpu_device *adev)
        adev->vcn.ras_if = &ras->ras_block.ras_comm;
 
        if (!ras->ras_block.ras_late_init)
-               ras->ras_block.ras_late_init = amdgpu_ras_block_late_init;
+               ras->ras_block.ras_late_init = amdgpu_vcn_ras_late_init;
 
        return 0;
 }
index c730949ece7d9b27c62b483d1844ddb4aa6d0319..f1397ef66fd77edb31989d28e4a50f19f06fbecd 100644 (file)
@@ -234,6 +234,7 @@ struct amdgpu_vcn_inst {
        struct amdgpu_ring      ring_enc[AMDGPU_VCN_MAX_ENC_RINGS];
        atomic_t                sched_score;
        struct amdgpu_irq_src   irq;
+       struct amdgpu_irq_src   ras_poison_irq;
        struct amdgpu_vcn_reg   external;
        struct amdgpu_bo        *dpg_sram_bo;
        struct dpg_pause_state  pause_state;
@@ -400,6 +401,8 @@ void amdgpu_debugfs_vcn_fwlog_init(struct amdgpu_device *adev,
 int amdgpu_vcn_process_poison_irq(struct amdgpu_device *adev,
                        struct amdgpu_irq_src *source,
                        struct amdgpu_iv_entry *entry);
+int amdgpu_vcn_ras_late_init(struct amdgpu_device *adev,
+                       struct ras_common_if *ras_block);
 int amdgpu_vcn_ras_sw_init(struct amdgpu_device *adev);
 
 #endif
index f5b5ce1051a2864651245a776c7d8b7881dbfeb1..ab44c1391d526594974bf8fc631913d8c8f4bb6a 100644 (file)
@@ -6892,8 +6892,10 @@ static int gfx_v10_0_kiq_resume(struct amdgpu_device *adev)
                return r;
 
        r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
-       if (unlikely(r != 0))
+       if (unlikely(r != 0)) {
+               amdgpu_bo_unreserve(ring->mqd_obj);
                return r;
+       }
 
        gfx_v10_0_kiq_init_queue(ring);
        amdgpu_bo_kunmap(ring->mqd_obj);
@@ -8152,8 +8154,14 @@ static int gfx_v10_0_set_powergating_state(void *handle,
        case IP_VERSION(10, 3, 3):
        case IP_VERSION(10, 3, 6):
        case IP_VERSION(10, 3, 7):
+               if (!enable)
+                       amdgpu_gfx_off_ctrl(adev, false);
+
                gfx_v10_cntl_pg(adev, enable);
-               amdgpu_gfx_off_ctrl(adev, enable);
+
+               if (enable)
+                       amdgpu_gfx_off_ctrl(adev, true);
+
                break;
        default:
                break;
index a9da0486467acacd19705d0de757328d50140d18..c4940b6ea1c4ccd8b82a6df1d91fcf0fedacce47 100644 (file)
@@ -1315,13 +1315,6 @@ static int gfx_v11_0_sw_init(void *handle)
        if (r)
                return r;
 
-       /* ECC error */
-       r = amdgpu_irq_add_id(adev, SOC21_IH_CLIENTID_GRBM_CP,
-                                 GFX_11_0_0__SRCID__CP_ECC_ERROR,
-                                 &adev->gfx.cp_ecc_error_irq);
-       if (r)
-               return r;
-
        /* FED error */
        r = amdgpu_irq_add_id(adev, SOC21_IH_CLIENTID_GFX,
                                  GFX_11_0_0__SRCID__RLC_GC_FED_INTERRUPT,
@@ -4444,7 +4437,6 @@ static int gfx_v11_0_hw_fini(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        int r;
 
-       amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
        amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
        amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
 
@@ -4675,24 +4667,27 @@ static uint64_t gfx_v11_0_get_gpu_clock_counter(struct amdgpu_device *adev)
        uint64_t clock;
        uint64_t clock_counter_lo, clock_counter_hi_pre, clock_counter_hi_after;
 
-       amdgpu_gfx_off_ctrl(adev, false);
-       mutex_lock(&adev->gfx.gpu_clock_mutex);
        if (amdgpu_sriov_vf(adev)) {
+               amdgpu_gfx_off_ctrl(adev, false);
+               mutex_lock(&adev->gfx.gpu_clock_mutex);
                clock_counter_hi_pre = (uint64_t)RREG32_SOC15(GC, 0, regCP_MES_MTIME_HI);
                clock_counter_lo = (uint64_t)RREG32_SOC15(GC, 0, regCP_MES_MTIME_LO);
                clock_counter_hi_after = (uint64_t)RREG32_SOC15(GC, 0, regCP_MES_MTIME_HI);
                if (clock_counter_hi_pre != clock_counter_hi_after)
                        clock_counter_lo = (uint64_t)RREG32_SOC15(GC, 0, regCP_MES_MTIME_LO);
+               mutex_unlock(&adev->gfx.gpu_clock_mutex);
+               amdgpu_gfx_off_ctrl(adev, true);
        } else {
+               preempt_disable();
                clock_counter_hi_pre = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_UPPER);
                clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_LOWER);
                clock_counter_hi_after = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_UPPER);
                if (clock_counter_hi_pre != clock_counter_hi_after)
                        clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_LOWER);
+               preempt_enable();
        }
        clock = clock_counter_lo | (clock_counter_hi_after << 32ULL);
-       mutex_unlock(&adev->gfx.gpu_clock_mutex);
-       amdgpu_gfx_off_ctrl(adev, true);
+
        return clock;
 }
 
@@ -5158,8 +5153,14 @@ static int gfx_v11_0_set_powergating_state(void *handle,
                break;
        case IP_VERSION(11, 0, 1):
        case IP_VERSION(11, 0, 4):
+               if (!enable)
+                       amdgpu_gfx_off_ctrl(adev, false);
+
                gfx_v11_cntl_pg(adev, enable);
-               amdgpu_gfx_off_ctrl(adev, enable);
+
+               if (enable)
+                       amdgpu_gfx_off_ctrl(adev, true);
+
                break;
        default:
                break;
@@ -5897,36 +5898,6 @@ static void gfx_v11_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev
        }
 }
 
-#define CP_ME1_PIPE_INST_ADDR_INTERVAL  0x1
-#define SET_ECC_ME_PIPE_STATE(reg_addr, state) \
-       do { \
-               uint32_t tmp = RREG32_SOC15_IP(GC, reg_addr); \
-               tmp = REG_SET_FIELD(tmp, CP_ME1_PIPE0_INT_CNTL, CP_ECC_ERROR_INT_ENABLE, state); \
-               WREG32_SOC15_IP(GC, reg_addr, tmp); \
-       } while (0)
-
-static int gfx_v11_0_set_cp_ecc_error_state(struct amdgpu_device *adev,
-                                                       struct amdgpu_irq_src *source,
-                                                       unsigned type,
-                                                       enum amdgpu_interrupt_state state)
-{
-       uint32_t ecc_irq_state = 0;
-       uint32_t pipe0_int_cntl_addr = 0;
-       int i = 0;
-
-       ecc_irq_state = (state == AMDGPU_IRQ_STATE_ENABLE) ? 1 : 0;
-
-       pipe0_int_cntl_addr = SOC15_REG_OFFSET(GC, 0, regCP_ME1_PIPE0_INT_CNTL);
-
-       WREG32_FIELD15_PREREG(GC, 0, CP_INT_CNTL_RING0, CP_ECC_ERROR_INT_ENABLE, ecc_irq_state);
-
-       for (i = 0; i < adev->gfx.mec.num_pipe_per_mec; i++)
-               SET_ECC_ME_PIPE_STATE(pipe0_int_cntl_addr + i * CP_ME1_PIPE_INST_ADDR_INTERVAL,
-                                       ecc_irq_state);
-
-       return 0;
-}
-
 static int gfx_v11_0_set_eop_interrupt_state(struct amdgpu_device *adev,
                                            struct amdgpu_irq_src *src,
                                            unsigned type,
@@ -6341,11 +6312,6 @@ static const struct amdgpu_irq_src_funcs gfx_v11_0_priv_inst_irq_funcs = {
        .process = gfx_v11_0_priv_inst_irq,
 };
 
-static const struct amdgpu_irq_src_funcs gfx_v11_0_cp_ecc_error_irq_funcs = {
-       .set = gfx_v11_0_set_cp_ecc_error_state,
-       .process = amdgpu_gfx_cp_ecc_error_irq,
-};
-
 static const struct amdgpu_irq_src_funcs gfx_v11_0_rlc_gc_fed_irq_funcs = {
        .process = gfx_v11_0_rlc_gc_fed_irq,
 };
@@ -6361,9 +6327,6 @@ static void gfx_v11_0_set_irq_funcs(struct amdgpu_device *adev)
        adev->gfx.priv_inst_irq.num_types = 1;
        adev->gfx.priv_inst_irq.funcs = &gfx_v11_0_priv_inst_irq_funcs;
 
-       adev->gfx.cp_ecc_error_irq.num_types = 1; /* CP ECC error */
-       adev->gfx.cp_ecc_error_irq.funcs = &gfx_v11_0_cp_ecc_error_irq_funcs;
-
        adev->gfx.rlc_gc_fed_irq.num_types = 1; /* 0x80 FED error */
        adev->gfx.rlc_gc_fed_irq.funcs = &gfx_v11_0_rlc_gc_fed_irq_funcs;
 
index adbcd8127c82eca9f47394fb2e4b65b3812a8072..ce22f7b3041603294d8e9e9b76d133789558640d 100644 (file)
@@ -3617,8 +3617,10 @@ static int gfx_v9_0_kiq_resume(struct amdgpu_device *adev)
                return r;
 
        r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
-       if (unlikely(r != 0))
+       if (unlikely(r != 0)) {
+               amdgpu_bo_unreserve(ring->mqd_obj);
                return r;
+       }
 
        gfx_v9_0_kiq_init_queue(ring);
        amdgpu_bo_kunmap(ring->mqd_obj);
@@ -3764,7 +3766,8 @@ static int gfx_v9_0_hw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
+       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
+               amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
        amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
        amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
 
@@ -4002,30 +4005,25 @@ static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev)
                clock = clock_lo | (clock_hi << 32ULL);
                break;
        case IP_VERSION(9, 1, 0):
+       case IP_VERSION(9, 2, 2):
                preempt_disable();
-               clock_hi = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven);
-               clock_lo = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_LOWER_Raven);
-               hi_check = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven);
-               /* The PWR TSC clock frequency is 100MHz, which sets 32-bit carry over
-                * roughly every 42 seconds.
-                */
-               if (hi_check != clock_hi) {
+               if (adev->rev_id >= 0x8) {
+                       clock_hi = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven2);
+                       clock_lo = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_LOWER_Raven2);
+                       hi_check = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven2);
+               } else {
+                       clock_hi = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven);
                        clock_lo = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_LOWER_Raven);
-                       clock_hi = hi_check;
+                       hi_check = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven);
                }
-               preempt_enable();
-               clock = clock_lo | (clock_hi << 32ULL);
-               break;
-       case IP_VERSION(9, 2, 2):
-               preempt_disable();
-               clock_hi = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven2);
-               clock_lo = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_LOWER_Raven2);
-               hi_check = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven2);
                /* The PWR TSC clock frequency is 100MHz, which sets 32-bit carry over
-                * roughly every 42 seconds.
-                */
+               * roughly every 42 seconds.
+               */
                if (hi_check != clock_hi) {
-                       clock_lo = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_LOWER_Raven2);
+                       if (adev->rev_id >= 0x8)
+                               clock_lo = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_LOWER_Raven2);
+                       else
+                               clock_lo = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_LOWER_Raven);
                        clock_hi = hi_check;
                }
                preempt_enable();
index d95f9fe8f1c54ef351d36a567fd8a4572038b339..4116c112e8a01d00fee4306e737bf7a1cc92252e 100644 (file)
@@ -31,6 +31,8 @@
 #include "umc_v8_10.h"
 #include "athub/athub_3_0_0_sh_mask.h"
 #include "athub/athub_3_0_0_offset.h"
+#include "dcn/dcn_3_2_0_offset.h"
+#include "dcn/dcn_3_2_0_sh_mask.h"
 #include "oss/osssys_6_0_0_offset.h"
 #include "ivsrcid/vmc/irqsrcs_vmc_1_0.h"
 #include "navi10_enum.h"
@@ -546,7 +548,24 @@ static void gmc_v11_0_get_vm_pte(struct amdgpu_device *adev,
 
 static unsigned gmc_v11_0_get_vbios_fb_size(struct amdgpu_device *adev)
 {
-       return 0;
+       u32 d1vga_control = RREG32_SOC15(DCE, 0, regD1VGA_CONTROL);
+       unsigned size;
+
+       if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) {
+               size = AMDGPU_VBIOS_VGA_ALLOCATION;
+       } else {
+               u32 viewport;
+               u32 pitch;
+
+               viewport = RREG32_SOC15(DCE, 0, regHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION);
+               pitch = RREG32_SOC15(DCE, 0, regHUBPREQ0_DCSURF_SURFACE_PITCH);
+               size = (REG_GET_FIELD(viewport,
+                                       HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) *
+                               REG_GET_FIELD(pitch, HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH) *
+                               4);
+       }
+
+       return size;
 }
 
 static const struct amdgpu_gmc_funcs gmc_v11_0_gmc_funcs = {
index b040f51d9aa9d2847ea7f0c1023a15de8e0ed381..73e0dc5a10cd4a586aa6f4c35a2ddc7be56bb09f 100644 (file)
@@ -102,13 +102,13 @@ static int jpeg_v2_5_sw_init(void *handle)
 
                /* JPEG DJPEG POISON EVENT */
                r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i],
-                       VCN_2_6__SRCID_DJPEG0_POISON, &adev->jpeg.inst[i].irq);
+                       VCN_2_6__SRCID_DJPEG0_POISON, &adev->jpeg.inst[i].ras_poison_irq);
                if (r)
                        return r;
 
                /* JPEG EJPEG POISON EVENT */
                r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i],
-                       VCN_2_6__SRCID_EJPEG0_POISON, &adev->jpeg.inst[i].irq);
+                       VCN_2_6__SRCID_EJPEG0_POISON, &adev->jpeg.inst[i].ras_poison_irq);
                if (r)
                        return r;
        }
@@ -221,6 +221,9 @@ static int jpeg_v2_5_hw_fini(void *handle)
                if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
                      RREG32_SOC15(JPEG, i, mmUVD_JRBC_STATUS))
                        jpeg_v2_5_set_powergating_state(adev, AMD_PG_STATE_GATE);
+
+               if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__JPEG))
+                       amdgpu_irq_put(adev, &adev->jpeg.inst[i].ras_poison_irq, 0);
        }
 
        return 0;
@@ -569,6 +572,14 @@ static int jpeg_v2_5_set_interrupt_state(struct amdgpu_device *adev,
        return 0;
 }
 
+static int jpeg_v2_6_set_ras_interrupt_state(struct amdgpu_device *adev,
+                                       struct amdgpu_irq_src *source,
+                                       unsigned int type,
+                                       enum amdgpu_interrupt_state state)
+{
+       return 0;
+}
+
 static int jpeg_v2_5_process_interrupt(struct amdgpu_device *adev,
                                      struct amdgpu_irq_src *source,
                                      struct amdgpu_iv_entry *entry)
@@ -593,10 +604,6 @@ static int jpeg_v2_5_process_interrupt(struct amdgpu_device *adev,
        case VCN_2_0__SRCID__JPEG_DECODE:
                amdgpu_fence_process(&adev->jpeg.inst[ip_instance].ring_dec);
                break;
-       case VCN_2_6__SRCID_DJPEG0_POISON:
-       case VCN_2_6__SRCID_EJPEG0_POISON:
-               amdgpu_jpeg_process_poison_irq(adev, source, entry);
-               break;
        default:
                DRM_ERROR("Unhandled interrupt: %d %d\n",
                          entry->src_id, entry->src_data[0]);
@@ -725,6 +732,11 @@ static const struct amdgpu_irq_src_funcs jpeg_v2_5_irq_funcs = {
        .process = jpeg_v2_5_process_interrupt,
 };
 
+static const struct amdgpu_irq_src_funcs jpeg_v2_6_ras_irq_funcs = {
+       .set = jpeg_v2_6_set_ras_interrupt_state,
+       .process = amdgpu_jpeg_process_poison_irq,
+};
+
 static void jpeg_v2_5_set_irq_funcs(struct amdgpu_device *adev)
 {
        int i;
@@ -735,6 +747,9 @@ static void jpeg_v2_5_set_irq_funcs(struct amdgpu_device *adev)
 
                adev->jpeg.inst[i].irq.num_types = 1;
                adev->jpeg.inst[i].irq.funcs = &jpeg_v2_5_irq_funcs;
+
+               adev->jpeg.inst[i].ras_poison_irq.num_types = 1;
+               adev->jpeg.inst[i].ras_poison_irq.funcs = &jpeg_v2_6_ras_irq_funcs;
        }
 }
 
@@ -800,6 +815,7 @@ const struct amdgpu_ras_block_hw_ops jpeg_v2_6_ras_hw_ops = {
 static struct amdgpu_jpeg_ras jpeg_v2_6_ras = {
        .ras_block = {
                .hw_ops = &jpeg_v2_6_ras_hw_ops,
+               .ras_late_init = amdgpu_jpeg_ras_late_init,
        },
 };
 
index c55e09432e26279c80bd50df8434204e6f5439cf..1c2292cc5f2ce2cf3836902dd5beb7db9997ef18 100644 (file)
@@ -54,6 +54,7 @@ static int jpeg_v3_0_early_init(void *handle)
 
        switch (adev->ip_versions[UVD_HWIP][0]) {
        case IP_VERSION(3, 1, 1):
+       case IP_VERSION(3, 1, 2):
                break;
        default:
                harvest = RREG32_SOC15(JPEG, 0, mmCC_UVD_HARVESTING);
index 77e1e64aa1d1c7b7987d15aa5a771b553754a230..a3d83c9f2c9a3cca84e07aa65732c43ab8d2bfc2 100644 (file)
@@ -87,13 +87,13 @@ static int jpeg_v4_0_sw_init(void *handle)
 
        /* JPEG DJPEG POISON EVENT */
        r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
-                       VCN_4_0__SRCID_DJPEG0_POISON, &adev->jpeg.inst->irq);
+                       VCN_4_0__SRCID_DJPEG0_POISON, &adev->jpeg.inst->ras_poison_irq);
        if (r)
                return r;
 
        /* JPEG EJPEG POISON EVENT */
        r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
-                       VCN_4_0__SRCID_EJPEG0_POISON, &adev->jpeg.inst->irq);
+                       VCN_4_0__SRCID_EJPEG0_POISON, &adev->jpeg.inst->ras_poison_irq);
        if (r)
                return r;
 
@@ -202,7 +202,8 @@ static int jpeg_v4_0_hw_fini(void *handle)
                        RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS))
                        jpeg_v4_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
        }
-       amdgpu_irq_put(adev, &adev->jpeg.inst->irq, 0);
+       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__JPEG))
+               amdgpu_irq_put(adev, &adev->jpeg.inst->ras_poison_irq, 0);
 
        return 0;
 }
@@ -670,6 +671,14 @@ static int jpeg_v4_0_set_interrupt_state(struct amdgpu_device *adev,
        return 0;
 }
 
+static int jpeg_v4_0_set_ras_interrupt_state(struct amdgpu_device *adev,
+                                       struct amdgpu_irq_src *source,
+                                       unsigned int type,
+                                       enum amdgpu_interrupt_state state)
+{
+       return 0;
+}
+
 static int jpeg_v4_0_process_interrupt(struct amdgpu_device *adev,
                                      struct amdgpu_irq_src *source,
                                      struct amdgpu_iv_entry *entry)
@@ -680,10 +689,6 @@ static int jpeg_v4_0_process_interrupt(struct amdgpu_device *adev,
        case VCN_4_0__SRCID__JPEG_DECODE:
                amdgpu_fence_process(&adev->jpeg.inst->ring_dec);
                break;
-       case VCN_4_0__SRCID_DJPEG0_POISON:
-       case VCN_4_0__SRCID_EJPEG0_POISON:
-               amdgpu_jpeg_process_poison_irq(adev, source, entry);
-               break;
        default:
                DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n",
                          entry->src_id, entry->src_data[0]);
@@ -753,10 +758,18 @@ static const struct amdgpu_irq_src_funcs jpeg_v4_0_irq_funcs = {
        .process = jpeg_v4_0_process_interrupt,
 };
 
+static const struct amdgpu_irq_src_funcs jpeg_v4_0_ras_irq_funcs = {
+       .set = jpeg_v4_0_set_ras_interrupt_state,
+       .process = amdgpu_jpeg_process_poison_irq,
+};
+
 static void jpeg_v4_0_set_irq_funcs(struct amdgpu_device *adev)
 {
        adev->jpeg.inst->irq.num_types = 1;
        adev->jpeg.inst->irq.funcs = &jpeg_v4_0_irq_funcs;
+
+       adev->jpeg.inst->ras_poison_irq.num_types = 1;
+       adev->jpeg.inst->ras_poison_irq.funcs = &jpeg_v4_0_ras_irq_funcs;
 }
 
 const struct amdgpu_ip_block_version jpeg_v4_0_ip_block = {
@@ -811,6 +824,7 @@ const struct amdgpu_ras_block_hw_ops jpeg_v4_0_ras_hw_ops = {
 static struct amdgpu_jpeg_ras jpeg_v4_0_ras = {
        .ras_block = {
                .hw_ops = &jpeg_v4_0_ras_hw_ops,
+               .ras_late_init = amdgpu_jpeg_ras_late_init,
        },
 };
 
index 98c826f1f89b0c7252e171cc1c0cd8d885d0f4af..0fb6013441f07e32e9abc51465b6318fea4c5d9a 100644 (file)
@@ -98,6 +98,16 @@ static const struct amdgpu_video_codecs nv_video_codecs_decode =
 };
 
 /* Sienna Cichlid */
+static const struct amdgpu_video_codec_info sc_video_codecs_encode_array[] = {
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2160, 0)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 7680, 4352, 0)},
+};
+
+static const struct amdgpu_video_codecs sc_video_codecs_encode = {
+       .codec_count = ARRAY_SIZE(sc_video_codecs_encode_array),
+       .codec_array = sc_video_codecs_encode_array,
+};
+
 static const struct amdgpu_video_codec_info sc_video_codecs_decode_array_vcn0[] =
 {
        {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
@@ -136,8 +146,8 @@ static const struct amdgpu_video_codecs sc_video_codecs_decode_vcn1 =
 /* SRIOV Sienna Cichlid, not const since data is controlled by host */
 static struct amdgpu_video_codec_info sriov_sc_video_codecs_encode_array[] =
 {
-       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
-       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2160, 0)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 7680, 4352, 0)},
 };
 
 static struct amdgpu_video_codec_info sriov_sc_video_codecs_decode_array_vcn0[] =
@@ -237,12 +247,12 @@ static int nv_query_video_codecs(struct amdgpu_device *adev, bool encode,
                } else {
                        if (adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) {
                                if (encode)
-                                       *codecs = &nv_video_codecs_encode;
+                                       *codecs = &sc_video_codecs_encode;
                                else
                                        *codecs = &sc_video_codecs_decode_vcn1;
                        } else {
                                if (encode)
-                                       *codecs = &nv_video_codecs_encode;
+                                       *codecs = &sc_video_codecs_encode;
                                else
                                        *codecs = &sc_video_codecs_decode_vcn0;
                        }
@@ -251,14 +261,14 @@ static int nv_query_video_codecs(struct amdgpu_device *adev, bool encode,
        case IP_VERSION(3, 0, 16):
        case IP_VERSION(3, 0, 2):
                if (encode)
-                       *codecs = &nv_video_codecs_encode;
+                       *codecs = &sc_video_codecs_encode;
                else
                        *codecs = &sc_video_codecs_decode_vcn0;
                return 0;
        case IP_VERSION(3, 1, 1):
        case IP_VERSION(3, 1, 2):
                if (encode)
-                       *codecs = &nv_video_codecs_encode;
+                       *codecs = &sc_video_codecs_encode;
                else
                        *codecs = &yc_video_codecs_decode;
                return 0;
index e1b7fca096660a99387079c8fd73a99053de916b..5f10883da6a2388ef7f8b1354f5e3eddb0d970dd 100644 (file)
@@ -57,7 +57,13 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
        if (err)
                return err;
 
-       return psp_init_ta_microcode(psp, ucode_prefix);
+       err = psp_init_ta_microcode(psp, ucode_prefix);
+       if ((adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 1, 0)) &&
+               (adev->pdev->revision == 0xa1) &&
+               (psp->securedisplay_context.context.bin_desc.fw_version >= 0x27000008)) {
+               adev->psp.securedisplay_context.context.bin_desc.size_bytes = 0;
+       }
+       return err;
 }
 
 static int psp_v10_0_ring_create(struct psp_context *psp,
index b3cc04dd86536b6e7a87bf2f1d21a3a327f8cf84..9295ac7edd5650adf959e1240ada69bef3357032 100644 (file)
@@ -1917,9 +1917,11 @@ static int sdma_v4_0_hw_fini(void *handle)
                return 0;
        }
 
-       for (i = 0; i < adev->sdma.num_instances; i++) {
-               amdgpu_irq_put(adev, &adev->sdma.ecc_irq,
-                              AMDGPU_SDMA_IRQ_INSTANCE0 + i);
+       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__SDMA)) {
+               for (i = 0; i < adev->sdma.num_instances; i++) {
+                       amdgpu_irq_put(adev, &adev->sdma.ecc_irq,
+                                      AMDGPU_SDMA_IRQ_INSTANCE0 + i);
+               }
        }
 
        sdma_v4_0_ctx_switch_enable(adev, false);
index 744be2a0562362d366f52966abe667a61ff5f55f..d7716253651440186ce6c0c95df74361505209a2 100644 (file)
@@ -711,7 +711,7 @@ static int soc21_common_early_init(void *handle)
                        AMD_PG_SUPPORT_VCN_DPG |
                        AMD_PG_SUPPORT_GFX_PG |
                        AMD_PG_SUPPORT_JPEG;
-               adev->external_rev_id = adev->rev_id + 0x1;
+               adev->external_rev_id = adev->rev_id + 0x80;
                break;
 
        default:
index ab0b45d0ead18ae6f315a8b59be901247f05aefe..515681c88dcbca3b19c2e20d2dff4421a9cca9a1 100644 (file)
@@ -143,7 +143,7 @@ static int vcn_v2_5_sw_init(void *handle)
 
                /* VCN POISON TRAP */
                r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[j],
-                       VCN_2_6__SRCID_UVD_POISON, &adev->vcn.inst[j].irq);
+                       VCN_2_6__SRCID_UVD_POISON, &adev->vcn.inst[j].ras_poison_irq);
                if (r)
                        return r;
        }
@@ -354,6 +354,9 @@ static int vcn_v2_5_hw_fini(void *handle)
                    (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
                     RREG32_SOC15(VCN, i, mmUVD_STATUS)))
                        vcn_v2_5_set_powergating_state(adev, AMD_PG_STATE_GATE);
+
+               if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN))
+                       amdgpu_irq_put(adev, &adev->vcn.inst[i].ras_poison_irq, 0);
        }
 
        return 0;
@@ -1807,6 +1810,14 @@ static int vcn_v2_5_set_interrupt_state(struct amdgpu_device *adev,
        return 0;
 }
 
+static int vcn_v2_6_set_ras_interrupt_state(struct amdgpu_device *adev,
+                                       struct amdgpu_irq_src *source,
+                                       unsigned int type,
+                                       enum amdgpu_interrupt_state state)
+{
+       return 0;
+}
+
 static int vcn_v2_5_process_interrupt(struct amdgpu_device *adev,
                                      struct amdgpu_irq_src *source,
                                      struct amdgpu_iv_entry *entry)
@@ -1837,9 +1848,6 @@ static int vcn_v2_5_process_interrupt(struct amdgpu_device *adev,
        case VCN_2_0__SRCID__UVD_ENC_LOW_LATENCY:
                amdgpu_fence_process(&adev->vcn.inst[ip_instance].ring_enc[1]);
                break;
-       case VCN_2_6__SRCID_UVD_POISON:
-               amdgpu_vcn_process_poison_irq(adev, source, entry);
-               break;
        default:
                DRM_ERROR("Unhandled interrupt: %d %d\n",
                          entry->src_id, entry->src_data[0]);
@@ -1854,6 +1862,11 @@ static const struct amdgpu_irq_src_funcs vcn_v2_5_irq_funcs = {
        .process = vcn_v2_5_process_interrupt,
 };
 
+static const struct amdgpu_irq_src_funcs vcn_v2_6_ras_irq_funcs = {
+       .set = vcn_v2_6_set_ras_interrupt_state,
+       .process = amdgpu_vcn_process_poison_irq,
+};
+
 static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev)
 {
        int i;
@@ -1863,6 +1876,9 @@ static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev)
                        continue;
                adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
                adev->vcn.inst[i].irq.funcs = &vcn_v2_5_irq_funcs;
+
+               adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.num_enc_rings + 1;
+               adev->vcn.inst[i].ras_poison_irq.funcs = &vcn_v2_6_ras_irq_funcs;
        }
 }
 
@@ -1965,6 +1981,7 @@ const struct amdgpu_ras_block_hw_ops vcn_v2_6_ras_hw_ops = {
 static struct amdgpu_vcn_ras vcn_v2_6_ras = {
        .ras_block = {
                .hw_ops = &vcn_v2_6_ras_hw_ops,
+               .ras_late_init = amdgpu_vcn_ras_late_init,
        },
 };
 
index bf0674039598d3154776c682400d10dfd5db5f29..e5fd1e00914d0efbe301e9f439901cc71480811b 100644 (file)
@@ -139,7 +139,7 @@ static int vcn_v4_0_sw_init(void *handle)
 
                /* VCN POISON TRAP */
                r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[i],
-                               VCN_4_0__SRCID_UVD_POISON, &adev->vcn.inst[i].irq);
+                               VCN_4_0__SRCID_UVD_POISON, &adev->vcn.inst[i].ras_poison_irq);
                if (r)
                        return r;
 
@@ -305,8 +305,8 @@ static int vcn_v4_0_hw_fini(void *handle)
                         vcn_v4_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
                        }
                }
-
-               amdgpu_irq_put(adev, &adev->vcn.inst[i].irq, 0);
+               if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN))
+                       amdgpu_irq_put(adev, &adev->vcn.inst[i].ras_poison_irq, 0);
        }
 
        return 0;
@@ -1975,6 +1975,24 @@ static int vcn_v4_0_set_interrupt_state(struct amdgpu_device *adev, struct amdgp
        return 0;
 }
 
+/**
+ * vcn_v4_0_set_ras_interrupt_state - set VCN block RAS interrupt state
+ *
+ * @adev: amdgpu_device pointer
+ * @source: interrupt sources
+ * @type: interrupt types
+ * @state: interrupt states
+ *
+ * Set VCN block RAS interrupt state
+ */
+static int vcn_v4_0_set_ras_interrupt_state(struct amdgpu_device *adev,
+       struct amdgpu_irq_src *source,
+       unsigned int type,
+       enum amdgpu_interrupt_state state)
+{
+       return 0;
+}
+
 /**
  * vcn_v4_0_process_interrupt - process VCN block interrupt
  *
@@ -2007,9 +2025,6 @@ static int vcn_v4_0_process_interrupt(struct amdgpu_device *adev, struct amdgpu_
        case VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE:
                amdgpu_fence_process(&adev->vcn.inst[ip_instance].ring_enc[0]);
                break;
-       case VCN_4_0__SRCID_UVD_POISON:
-               amdgpu_vcn_process_poison_irq(adev, source, entry);
-               break;
        default:
                DRM_ERROR("Unhandled interrupt: %d %d\n",
                          entry->src_id, entry->src_data[0]);
@@ -2024,6 +2039,11 @@ static const struct amdgpu_irq_src_funcs vcn_v4_0_irq_funcs = {
        .process = vcn_v4_0_process_interrupt,
 };
 
+static const struct amdgpu_irq_src_funcs vcn_v4_0_ras_irq_funcs = {
+       .set = vcn_v4_0_set_ras_interrupt_state,
+       .process = amdgpu_vcn_process_poison_irq,
+};
+
 /**
  * vcn_v4_0_set_irq_funcs - set VCN block interrupt irq functions
  *
@@ -2041,6 +2061,9 @@ static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev)
 
                adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
                adev->vcn.inst[i].irq.funcs = &vcn_v4_0_irq_funcs;
+
+               adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.num_enc_rings + 1;
+               adev->vcn.inst[i].ras_poison_irq.funcs = &vcn_v4_0_ras_irq_funcs;
        }
 }
 
@@ -2114,6 +2137,7 @@ const struct amdgpu_ras_block_hw_ops vcn_v4_0_ras_hw_ops = {
 static struct amdgpu_vcn_ras vcn_v4_0_ras = {
        .ras_block = {
                .hw_ops = &vcn_v4_0_ras_hw_ops,
+               .ras_late_init = amdgpu_vcn_ras_late_init,
        },
 };
 
index 8b4b186c57f515fd541eaa15ce55e0b3ebf2dadb..d5cec03eaa8d3b0416ae211020269d0bce0c4e3d 100644 (file)
@@ -2479,20 +2479,25 @@ static void dm_gpureset_toggle_interrupts(struct amdgpu_device *adev,
                if (acrtc && state->stream_status[i].plane_count != 0) {
                        irq_source = IRQ_TYPE_PFLIP + acrtc->otg_inst;
                        rc = dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY;
-                       DRM_DEBUG_VBL("crtc %d - vupdate irq %sabling: r=%d\n",
-                                     acrtc->crtc_id, enable ? "en" : "dis", rc);
                        if (rc)
                                DRM_WARN("Failed to %s pflip interrupts\n",
                                         enable ? "enable" : "disable");
 
                        if (enable) {
-                               rc = amdgpu_dm_crtc_enable_vblank(&acrtc->base);
-                               if (rc)
-                                       DRM_WARN("Failed to enable vblank interrupts\n");
-                       } else {
-                               amdgpu_dm_crtc_disable_vblank(&acrtc->base);
-                       }
+                               if (amdgpu_dm_crtc_vrr_active(to_dm_crtc_state(acrtc->base.state)))
+                                       rc = amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, true);
+                       } else
+                               rc = amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, false);
 
+                       if (rc)
+                               DRM_WARN("Failed to %sable vupdate interrupt\n", enable ? "en" : "dis");
+
+                       irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst;
+                       /* During gpu-reset we disable and then enable vblank irq, so
+                        * don't use amdgpu_irq_get/put() to avoid refcount change.
+                        */
+                       if (!dc_interrupt_set(adev->dm.dc, irq_source, enable))
+                               DRM_WARN("Failed to %sable vblank interrupt\n", enable ? "en" : "dis");
                }
        }
 
@@ -2852,7 +2857,7 @@ static int dm_resume(void *handle)
                 * this is the case when traversing through already created
                 * MST connectors, should be skipped
                 */
-               if (aconnector->dc_link->type == dc_connection_mst_branch)
+               if (aconnector && aconnector->mst_root)
                        continue;
 
                mutex_lock(&aconnector->hpd_lock);
@@ -6737,7 +6742,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
        int clock, bpp = 0;
        bool is_y420 = false;
 
-       if (!aconnector->mst_output_port || !aconnector->dc_sink)
+       if (!aconnector->mst_output_port)
                return 0;
 
        mst_port = aconnector->mst_output_port;
index e3762e806617c11a724e34e3954ecbedfea49352..440fc0869a34ba631c84df42df35318ed37aeabb 100644 (file)
@@ -146,7 +146,6 @@ static void vblank_control_worker(struct work_struct *work)
 
 static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
 {
-       enum dc_irq_source irq_source;
        struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
        struct amdgpu_device *adev = drm_to_adev(crtc->dev);
        struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
@@ -169,18 +168,9 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
        if (rc)
                return rc;
 
-       if (amdgpu_in_reset(adev)) {
-               irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst;
-               /* During gpu-reset we disable and then enable vblank irq, so
-                * don't use amdgpu_irq_get/put() to avoid refcount change.
-                */
-               if (!dc_interrupt_set(adev->dm.dc, irq_source, enable))
-                       rc = -EBUSY;
-       } else {
-               rc = (enable)
-                       ? amdgpu_irq_get(adev, &adev->crtc_irq, acrtc->crtc_id)
-                       : amdgpu_irq_put(adev, &adev->crtc_irq, acrtc->crtc_id);
-       }
+       rc = (enable)
+               ? amdgpu_irq_get(adev, &adev->crtc_irq, acrtc->crtc_id)
+               : amdgpu_irq_put(adev, &adev->crtc_irq, acrtc->crtc_id);
 
        if (rc)
                return rc;
index 422fbf79da64fb95eda7627455870a0dbdb351cb..5403e9399a465c948c81e40f352dcb437751660d 100644 (file)
@@ -2113,15 +2113,6 @@ void dcn20_optimize_bandwidth(
        if (hubbub->funcs->program_compbuf_size)
                hubbub->funcs->program_compbuf_size(hubbub, context->bw_ctx.bw.dcn.compbuf_size_kb, true);
 
-       if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) {
-               dc_dmub_srv_p_state_delegate(dc,
-                       true, context);
-               context->bw_ctx.bw.dcn.clk.p_state_change_support = true;
-               dc->clk_mgr->clks.fw_based_mclk_switching = true;
-       } else {
-               dc->clk_mgr->clks.fw_based_mclk_switching = false;
-       }
-
        dc->clk_mgr->funcs->update_clocks(
                        dc->clk_mgr,
                        context,
index 8263a07f265f2157cb72afce81dcddb0e9af572f..32121db2851e665a587d7a7855cf9805f2be11a8 100644 (file)
@@ -983,36 +983,13 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc,
 }
 
 void dcn30_prepare_bandwidth(struct dc *dc,
-       struct dc_state *context)
+                            struct dc_state *context)
 {
-       bool p_state_change_support = context->bw_ctx.bw.dcn.clk.p_state_change_support;
-       /* Any transition into an FPO config should disable MCLK switching first to avoid
-        * driver and FW P-State synchronization issues.
-        */
-       if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || dc->clk_mgr->clks.fw_based_mclk_switching) {
-               dc->optimized_required = true;
-               context->bw_ctx.bw.dcn.clk.p_state_change_support = false;
-       }
-
        if (dc->clk_mgr->dc_mode_softmax_enabled)
                if (dc->clk_mgr->clks.dramclk_khz <= dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 &&
                                context->bw_ctx.bw.dcn.clk.dramclk_khz > dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000)
                        dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz);
 
        dcn20_prepare_bandwidth(dc, context);
-       /*
-        * enabled -> enabled: do not disable
-        * enabled -> disabled: disable
-        * disabled -> enabled: don't care
-        * disabled -> disabled: don't care
-        */
-       if (!context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching)
-               dc_dmub_srv_p_state_delegate(dc, false, context);
-
-       if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || dc->clk_mgr->clks.fw_based_mclk_switching) {
-               /* After disabling P-State, restore the original value to ensure we get the correct P-State
-                * on the next optimize. */
-               context->bw_ctx.bw.dcn.clk.p_state_change_support = p_state_change_support;
-       }
 }
 
index 40c488b26901b3cecbe2c08b28f62dbe9724860f..cc3fe9cac5b530f1afbf20889dab11714fae5fb9 100644 (file)
@@ -423,3 +423,68 @@ void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool
 
        PERF_TRACE();
 }
+static void apply_symclk_on_tx_off_wa(struct dc_link *link)
+{
+       /* There are use cases where SYMCLK is referenced by OTG. For instance
+        * for TMDS signal, OTG relies SYMCLK even if TX video output is off.
+        * However current link interface will power off PHY when disabling link
+        * output. This will turn off SYMCLK generated by PHY. The workaround is
+        * to identify such case where SYMCLK is still in use by OTG when we
+        * power off PHY. When this is detected, we will temporarily power PHY
+        * back on and move PHY's SYMCLK state to SYMCLK_ON_TX_OFF by calling
+        * program_pix_clk interface. When OTG is disabled, we will then power
+        * off PHY by calling disable link output again.
+        *
+        * In future dcn generations, we plan to rework transmitter control
+        * interface so that we could have an option to set SYMCLK ON TX OFF
+        * state in one step without this workaround
+        */
+
+       struct dc *dc = link->ctx->dc;
+       struct pipe_ctx *pipe_ctx = NULL;
+       uint8_t i;
+
+       if (link->phy_state.symclk_ref_cnts.otg > 0) {
+               for (i = 0; i < MAX_PIPES; i++) {
+                       pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
+                       if (pipe_ctx->stream && pipe_ctx->stream->link == link && pipe_ctx->top_pipe == NULL) {
+                               pipe_ctx->clock_source->funcs->program_pix_clk(
+                                               pipe_ctx->clock_source,
+                                               &pipe_ctx->stream_res.pix_clk_params,
+                                               dc->link_srv->dp_get_encoding_format(
+                                                               &pipe_ctx->link_config.dp_link_settings),
+                                               &pipe_ctx->pll_settings);
+                               link->phy_state.symclk_state = SYMCLK_ON_TX_OFF;
+                               break;
+                       }
+               }
+       }
+}
+
+void dcn314_disable_link_output(struct dc_link *link,
+               const struct link_resource *link_res,
+               enum signal_type signal)
+{
+       struct dc *dc = link->ctx->dc;
+       const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
+       struct dmcu *dmcu = dc->res_pool->dmcu;
+
+       if (signal == SIGNAL_TYPE_EDP &&
+                       link->dc->hwss.edp_backlight_control)
+               link->dc->hwss.edp_backlight_control(link, false);
+       else if (dmcu != NULL && dmcu->funcs->lock_phy)
+               dmcu->funcs->lock_phy(dmcu);
+
+       link_hwss->disable_link_output(link, link_res, signal);
+       link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
+       /*
+        * Add the logic to extract BOTH power up and power down sequences
+        * from enable/disable link output and only call edp panel control
+        * in enable_link_dp and disable_link_dp once.
+        */
+       if (dmcu != NULL && dmcu->funcs->lock_phy)
+               dmcu->funcs->unlock_phy(dmcu);
+       dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY);
+
+       apply_symclk_on_tx_off_wa(link);
+}
index c786d5e6a428ed983f95b09ee798efea95ff9cfa..6d0b62503caa6aeb3e6a8b2f22870fecd31cfcae 100644 (file)
@@ -45,4 +45,6 @@ void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool
 
 void dcn314_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool clock_on);
 
+void dcn314_disable_link_output(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal);
+
 #endif /* __DC_HWSS_DCN314_H__ */
index 5267e901a35c130ad4b050db6be1b4d19a323323..a588f46b166f4945315c55be21de9db01a150827 100644 (file)
@@ -105,7 +105,7 @@ static const struct hw_sequencer_funcs dcn314_funcs = {
        .enable_lvds_link_output = dce110_enable_lvds_link_output,
        .enable_tmds_link_output = dce110_enable_tmds_link_output,
        .enable_dp_link_output = dce110_enable_dp_link_output,
-       .disable_link_output = dce110_disable_link_output,
+       .disable_link_output = dcn314_disable_link_output,
        .z10_restore = dcn31_z10_restore,
        .z10_save_init = dcn31_z10_save_init,
        .set_disp_pattern_generator = dcn30_set_disp_pattern_generator,
index 13c7e7394b1c72e723af5b628fa2c96777a38e45..d75248b6cae997cbe359b8ea9ed551a3c7f0687d 100644 (file)
@@ -810,7 +810,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                                        v->SwathHeightY[k],
                                        v->SwathHeightC[k],
                                        TWait,
-                                       v->DRAMSpeedPerState[mode_lib->vba.VoltageLevel] <= MEM_STROBE_FREQ_MHZ ?
+                                       (v->DRAMSpeedPerState[mode_lib->vba.VoltageLevel] <= MEM_STROBE_FREQ_MHZ ||
+                                               v->DCFCLKPerState[mode_lib->vba.VoltageLevel] <= MIN_DCFCLK_FREQ_MHZ) ?
                                                        mode_lib->vba.ip.min_prefetch_in_strobe_us : 0,
                                        /* Output */
                                        &v->DSTXAfterScaler[k],
@@ -3310,7 +3311,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                                        v->swath_width_chroma_ub_this_state[k],
                                                        v->SwathHeightYThisState[k],
                                                        v->SwathHeightCThisState[k], v->TWait,
-                                                       v->DRAMSpeedPerState[i] <= MEM_STROBE_FREQ_MHZ ?
+                                                       (v->DRAMSpeedPerState[i] <= MEM_STROBE_FREQ_MHZ || v->DCFCLKState[i][j] <= MIN_DCFCLK_FREQ_MHZ) ?
                                                                        mode_lib->vba.ip.min_prefetch_in_strobe_us : 0,
 
                                                        /* Output */
index 500b3dd6052d9c147e1a05dcde3a1e1acfc74c2c..d98e36a9a09ccfba3267e18bf4bcc5e024b2307c 100644 (file)
@@ -53,6 +53,7 @@
 #define BPP_BLENDED_PIPE 0xffffffff
 
 #define MEM_STROBE_FREQ_MHZ 1600
+#define MIN_DCFCLK_FREQ_MHZ 200
 #define MEM_STROBE_MAX_DELIVERY_TIME_US 60.0
 
 struct display_mode_lib;
index d4b7da526f0a55eeb7736edb5f99a84826110126..e8b2fc4002a52d07dc91e7cee0c3250acd23dc51 100644 (file)
@@ -359,5 +359,8 @@ bool link_validate_dpia_bandwidth(const struct dc_stream_state *stream, const un
                link[i] = stream[i].link;
                bw_needed[i] = dc_bandwidth_in_kbps_from_timing(&stream[i].timing);
        }
+
+       ret = dpia_validate_usb4_bw(link, bw_needed, num_streams);
+
        return ret;
 }
index 300e156b924f41ca13838e8c18935d0e8546aaf7..078aaaa53162801e4e10f08dd8f66641ddc41c9b 100644 (file)
@@ -36,6 +36,8 @@
 #define amdgpu_dpm_enable_bapm(adev, e) \
                ((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e)))
 
+#define amdgpu_dpm_is_legacy_dpm(adev) ((adev)->powerplay.pp_handle == (adev))
+
 int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low)
 {
        const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
@@ -1460,15 +1462,24 @@ int amdgpu_dpm_get_smu_prv_buf_details(struct amdgpu_device *adev,
 
 int amdgpu_dpm_is_overdrive_supported(struct amdgpu_device *adev)
 {
-       struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
-       struct smu_context *smu = adev->powerplay.pp_handle;
+       if (is_support_sw_smu(adev)) {
+               struct smu_context *smu = adev->powerplay.pp_handle;
 
-       if ((is_support_sw_smu(adev) && smu->od_enabled) ||
-           (is_support_sw_smu(adev) && smu->is_apu) ||
-               (!is_support_sw_smu(adev) && hwmgr->od_enabled))
-               return true;
+               return (smu->od_enabled || smu->is_apu);
+       } else {
+               struct pp_hwmgr *hwmgr;
 
-       return false;
+               /*
+                * dpm on some legacy asics don't carry od_enabled member
+                * as its pp_handle is casted directly from adev.
+                */
+               if (amdgpu_dpm_is_legacy_dpm(adev))
+                       return false;
+
+               hwmgr = (struct pp_hwmgr *)adev->powerplay.pp_handle;
+
+               return hwmgr->od_enabled;
+       }
 }
 
 int amdgpu_dpm_set_pp_table(struct amdgpu_device *adev,
index 58c2246918fdabd1de4d9f91262c0ac20b2bc587..f4f40459f22b97e0cfc8b4fa7df6a7a911a21878 100644 (file)
@@ -871,13 +871,11 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev,
        }
        if (ret == -ENOENT) {
                size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf);
-               if (size > 0) {
-                       size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf + size);
-                       size += amdgpu_dpm_print_clock_levels(adev, OD_VDDC_CURVE, buf + size);
-                       size += amdgpu_dpm_print_clock_levels(adev, OD_VDDGFX_OFFSET, buf + size);
-                       size += amdgpu_dpm_print_clock_levels(adev, OD_RANGE, buf + size);
-                       size += amdgpu_dpm_print_clock_levels(adev, OD_CCLK, buf + size);
-               }
+               size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf + size);
+               size += amdgpu_dpm_print_clock_levels(adev, OD_VDDC_CURVE, buf + size);
+               size += amdgpu_dpm_print_clock_levels(adev, OD_VDDGFX_OFFSET, buf + size);
+               size += amdgpu_dpm_print_clock_levels(adev, OD_RANGE, buf + size);
+               size += amdgpu_dpm_print_clock_levels(adev, OD_CCLK, buf + size);
        }
 
        if (size == 0)
index d6d9e3b1b2c0e4511707680dbb1286d13188977a..02e69ccff3bac47cefb29b4369e196bd09dfae9d 100644 (file)
@@ -6925,23 +6925,6 @@ static int si_dpm_enable(struct amdgpu_device *adev)
        return 0;
 }
 
-static int si_set_temperature_range(struct amdgpu_device *adev)
-{
-       int ret;
-
-       ret = si_thermal_enable_alert(adev, false);
-       if (ret)
-               return ret;
-       ret = si_thermal_set_temperature_range(adev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
-       if (ret)
-               return ret;
-       ret = si_thermal_enable_alert(adev, true);
-       if (ret)
-               return ret;
-
-       return ret;
-}
-
 static void si_dpm_disable(struct amdgpu_device *adev)
 {
        struct rv7xx_power_info *pi = rv770_get_pi(adev);
@@ -7626,18 +7609,6 @@ static int si_dpm_process_interrupt(struct amdgpu_device *adev,
 
 static int si_dpm_late_init(void *handle)
 {
-       int ret;
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       if (!adev->pm.dpm_enabled)
-               return 0;
-
-       ret = si_set_temperature_range(adev);
-       if (ret)
-               return ret;
-#if 0 //TODO ?
-       si_dpm_powergate_uvd(adev, true);
-#endif
        return 0;
 }
 
index 5633c5797e85a4c7651301e06cd1c06eea90d6da..2ddf5198e5c4860f86db5ce824f35ae051fb6bed 100644 (file)
@@ -733,6 +733,24 @@ static int smu_late_init(void *handle)
                return ret;
        }
 
+       /*
+        * Explicitly notify PMFW the power mode the system in. Since
+        * the PMFW may boot the ASIC with a different mode.
+        * For those supporting ACDC switch via gpio, PMFW will
+        * handle the switch automatically. Driver involvement
+        * is unnecessary.
+        */
+       if (!smu->dc_controlled_by_gpio) {
+               ret = smu_set_power_source(smu,
+                                          adev->pm.ac_power ? SMU_POWER_SOURCE_AC :
+                                          SMU_POWER_SOURCE_DC);
+               if (ret) {
+                       dev_err(adev->dev, "Failed to switch to %s mode!\n",
+                               adev->pm.ac_power ? "AC" : "DC");
+                       return ret;
+               }
+       }
+
        if ((adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 1)) ||
            (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 3)))
                return 0;
index c4000518dc56d84da730a439eb192671d18f503f..275f708db63626183e2a45b14782a7b54ac12328 100644 (file)
@@ -3413,26 +3413,8 @@ static int navi10_post_smu_init(struct smu_context *smu)
                return 0;
 
        ret = navi10_run_umc_cdr_workaround(smu);
-       if (ret) {
+       if (ret)
                dev_err(adev->dev, "Failed to apply umc cdr workaround!\n");
-               return ret;
-       }
-
-       if (!smu->dc_controlled_by_gpio) {
-               /*
-                * For Navi1X, manually switch it to AC mode as PMFW
-                * may boot it with DC mode.
-                */
-               ret = smu_v11_0_set_power_source(smu,
-                                                adev->pm.ac_power ?
-                                                SMU_POWER_SOURCE_AC :
-                                                SMU_POWER_SOURCE_DC);
-               if (ret) {
-                       dev_err(adev->dev, "Failed to switch to %s mode!\n",
-                                       adev->pm.ac_power ? "AC" : "DC");
-                       return ret;
-               }
-       }
 
        return ret;
 }
index 7433dcaa16e046af9c311276c0a04f5f7214928d..067b4e0b026c0b9ce76391723bc45a6492b7afcb 100644 (file)
@@ -582,7 +582,7 @@ static int vangogh_print_legacy_clk_levels(struct smu_context *smu,
        DpmClocks_t *clk_table = smu->smu_table.clocks_table;
        SmuMetrics_legacy_t metrics;
        struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
-       int i, size = 0, ret = 0;
+       int i, idx, size = 0, ret = 0;
        uint32_t cur_value = 0, value = 0, count = 0;
        bool cur_value_match_level = false;
 
@@ -656,7 +656,8 @@ static int vangogh_print_legacy_clk_levels(struct smu_context *smu,
        case SMU_MCLK:
        case SMU_FCLK:
                for (i = 0; i < count; i++) {
-                       ret = vangogh_get_dpm_clk_limited(smu, clk_type, i, &value);
+                       idx = (clk_type == SMU_FCLK || clk_type == SMU_MCLK) ? (count - i - 1) : i;
+                       ret = vangogh_get_dpm_clk_limited(smu, clk_type, idx, &value);
                        if (ret)
                                return ret;
                        if (!value)
@@ -683,7 +684,7 @@ static int vangogh_print_clk_levels(struct smu_context *smu,
        DpmClocks_t *clk_table = smu->smu_table.clocks_table;
        SmuMetrics_t metrics;
        struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
-       int i, size = 0, ret = 0;
+       int i, idx, size = 0, ret = 0;
        uint32_t cur_value = 0, value = 0, count = 0;
        bool cur_value_match_level = false;
        uint32_t min, max;
@@ -765,7 +766,8 @@ static int vangogh_print_clk_levels(struct smu_context *smu,
        case SMU_MCLK:
        case SMU_FCLK:
                for (i = 0; i < count; i++) {
-                       ret = vangogh_get_dpm_clk_limited(smu, clk_type, i, &value);
+                       idx = (clk_type == SMU_FCLK || clk_type == SMU_MCLK) ? (count - i - 1) : i;
+                       ret = vangogh_get_dpm_clk_limited(smu, clk_type, idx, &value);
                        if (ret)
                                return ret;
                        if (!value)
index 5cdc07165480b5a3be51ec46c722699d34d52b84..8a8ba25c9ad7cc29437103b22d58555cd8afbe31 100644 (file)
@@ -494,7 +494,7 @@ static int renoir_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
 static int renoir_print_clk_levels(struct smu_context *smu,
                        enum smu_clk_type clk_type, char *buf)
 {
-       int i, size = 0, ret = 0;
+       int i, idx, size = 0, ret = 0;
        uint32_t cur_value = 0, value = 0, count = 0, min = 0, max = 0;
        SmuMetrics_t metrics;
        struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
@@ -594,7 +594,8 @@ static int renoir_print_clk_levels(struct smu_context *smu,
        case SMU_VCLK:
        case SMU_DCLK:
                for (i = 0; i < count; i++) {
-                       ret = renoir_get_dpm_clk_limited(smu, clk_type, i, &value);
+                       idx = (clk_type == SMU_FCLK || clk_type == SMU_MCLK) ? (count - i - 1) : i;
+                       ret = renoir_get_dpm_clk_limited(smu, clk_type, idx, &value);
                        if (ret)
                                return ret;
                        if (!value)
index 8fa9a36c38b64e5b0281561308c70a22887adb5c..6d9760eac16d8de73480ac9448390b3806a5f671 100644 (file)
@@ -478,7 +478,7 @@ static int smu_v13_0_4_get_dpm_level_count(struct smu_context *smu,
 static int smu_v13_0_4_print_clk_levels(struct smu_context *smu,
                                        enum smu_clk_type clk_type, char *buf)
 {
-       int i, size = 0, ret = 0;
+       int i, idx, size = 0, ret = 0;
        uint32_t cur_value = 0, value = 0, count = 0;
        uint32_t min, max;
 
@@ -512,7 +512,8 @@ static int smu_v13_0_4_print_clk_levels(struct smu_context *smu,
                        break;
 
                for (i = 0; i < count; i++) {
-                       ret = smu_v13_0_4_get_dpm_freq_by_index(smu, clk_type, i, &value);
+                       idx = (clk_type == SMU_FCLK || clk_type == SMU_MCLK) ? (count - i - 1) : i;
+                       ret = smu_v13_0_4_get_dpm_freq_by_index(smu, clk_type, idx, &value);
                        if (ret)
                                break;
 
index 66445964efbd1e5a94c7cfa3d2bbfca7b76e8c89..0081fa607e02e4d4b8578cf1b696855b97a871a6 100644 (file)
@@ -866,7 +866,7 @@ out:
 static int smu_v13_0_5_print_clk_levels(struct smu_context *smu,
                                enum smu_clk_type clk_type, char *buf)
 {
-       int i, size = 0, ret = 0;
+       int i, idx, size = 0, ret = 0;
        uint32_t cur_value = 0, value = 0, count = 0;
        uint32_t min = 0, max = 0;
 
@@ -898,7 +898,8 @@ static int smu_v13_0_5_print_clk_levels(struct smu_context *smu,
                        goto print_clk_out;
 
                for (i = 0; i < count; i++) {
-                       ret = smu_v13_0_5_get_dpm_freq_by_index(smu, clk_type, i, &value);
+                       idx = (clk_type == SMU_MCLK) ? (count - i - 1) : i;
+                       ret = smu_v13_0_5_get_dpm_freq_by_index(smu, clk_type, idx, &value);
                        if (ret)
                                goto print_clk_out;
 
index 3d9ff46706fb704855615f353165a353b43adf96..bba621615abf0948bf9ce4d0d560fd3d860b0354 100644 (file)
@@ -125,6 +125,7 @@ static struct cmn2asic_msg_mapping smu_v13_0_7_message_map[SMU_MSG_MAX_COUNT] =
        MSG_MAP(ArmD3,                          PPSMC_MSG_ArmD3,                       0),
        MSG_MAP(AllowGpo,                       PPSMC_MSG_SetGpoAllow,           0),
        MSG_MAP(GetPptLimit,                    PPSMC_MSG_GetPptLimit,                 0),
+       MSG_MAP(NotifyPowerSource,              PPSMC_MSG_NotifyPowerSource,           0),
 };
 
 static struct cmn2asic_mapping smu_v13_0_7_clk_map[SMU_CLK_COUNT] = {
@@ -1770,6 +1771,7 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
        .enable_mgpu_fan_boost = smu_v13_0_7_enable_mgpu_fan_boost,
        .get_power_limit = smu_v13_0_7_get_power_limit,
        .set_power_limit = smu_v13_0_set_power_limit,
+       .set_power_source = smu_v13_0_set_power_source,
        .get_power_profile_mode = smu_v13_0_7_get_power_profile_mode,
        .set_power_profile_mode = smu_v13_0_7_set_power_profile_mode,
        .set_tool_table_location = smu_v13_0_set_tool_table_location,
index 04e56b0b3033eaef681e9b3c9d2b14a18853cb3e..798f36cfcebd387c484590509b3a58642fa113b4 100644 (file)
@@ -1000,7 +1000,7 @@ out:
 static int yellow_carp_print_clk_levels(struct smu_context *smu,
                                enum smu_clk_type clk_type, char *buf)
 {
-       int i, size = 0, ret = 0;
+       int i, idx, size = 0, ret = 0;
        uint32_t cur_value = 0, value = 0, count = 0;
        uint32_t min, max;
 
@@ -1033,7 +1033,8 @@ static int yellow_carp_print_clk_levels(struct smu_context *smu,
                        goto print_clk_out;
 
                for (i = 0; i < count; i++) {
-                       ret = yellow_carp_get_dpm_freq_by_index(smu, clk_type, i, &value);
+                       idx = (clk_type == SMU_FCLK || clk_type == SMU_MCLK) ? (count - i - 1) : i;
+                       ret = yellow_carp_get_dpm_freq_by_index(smu, clk_type, idx, &value);
                        if (ret)
                                goto print_clk_out;
 
index 794ffd4a29c5ac47a724723312692b6514c39f55..f32ce29edba726a903d7b082f770ae896bfce3cc 100644 (file)
@@ -425,11 +425,12 @@ struct ast_device *ast_device_create(const struct drm_driver *drv,
                return ERR_PTR(-EIO);
 
        /*
-        * If we don't have IO space at all, use MMIO now and
-        * assume the chip has MMIO enabled by default (rev 0x20
-        * and higher).
+        * After AST2500, MMIO is enabled by default, and it should be adopted
+        * to be compatible with Arm.
         */
-       if (!(pci_resource_flags(pdev, 2) & IORESOURCE_IO)) {
+       if (pdev->revision >= 0x40) {
+               ast->ioregs = ast->regs + AST_IO_MM_OFFSET;
+       } else if (!(pci_resource_flags(pdev, 2) & IORESOURCE_IO)) {
                drm_info(dev, "platform has no IO space, trying MMIO\n");
                ast->ioregs = ast->regs + AST_IO_MM_OFFSET;
        }
index 64458982be40c46882195ce2f9f7fd2dfdde672c..6bb1b8b27d7a102b8ed634a5014980d666762816 100644 (file)
@@ -641,19 +641,27 @@ static void drm_fb_helper_damage(struct drm_fb_helper *helper, u32 x, u32 y,
 static void drm_fb_helper_memory_range_to_clip(struct fb_info *info, off_t off, size_t len,
                                               struct drm_rect *clip)
 {
+       u32 line_length = info->fix.line_length;
+       u32 fb_height = info->var.yres;
        off_t end = off + len;
        u32 x1 = 0;
-       u32 y1 = off / info->fix.line_length;
+       u32 y1 = off / line_length;
        u32 x2 = info->var.xres;
-       u32 y2 = DIV_ROUND_UP(end, info->fix.line_length);
+       u32 y2 = DIV_ROUND_UP(end, line_length);
+
+       /* Don't allow any of them beyond the bottom bound of display area */
+       if (y1 > fb_height)
+               y1 = fb_height;
+       if (y2 > fb_height)
+               y2 = fb_height;
 
        if ((y2 - y1) == 1) {
                /*
                 * We've only written to a single scanline. Try to reduce
                 * the number of horizontal pixels that need an update.
                 */
-               off_t bit_off = (off % info->fix.line_length) * 8;
-               off_t bit_end = (end % info->fix.line_length) * 8;
+               off_t bit_off = (off % line_length) * 8;
+               off_t bit_end = (end % line_length) * 8;
 
                x1 = bit_off / info->var.bits_per_pixel;
                x2 = DIV_ROUND_UP(bit_end, info->var.bits_per_pixel);
index 4cf214de50c4037ab659fda9097f2e6e34da7d06..c21c3f6230335f4a93a2c9cf0c4d2768138a72bb 100644 (file)
@@ -264,28 +264,10 @@ void drmm_kfree(struct drm_device *dev, void *data)
 }
 EXPORT_SYMBOL(drmm_kfree);
 
-static void drmm_mutex_release(struct drm_device *dev, void *res)
+void __drmm_mutex_release(struct drm_device *dev, void *res)
 {
        struct mutex *lock = res;
 
        mutex_destroy(lock);
 }
-
-/**
- * drmm_mutex_init - &drm_device-managed mutex_init()
- * @dev: DRM device
- * @lock: lock to be initialized
- *
- * Returns:
- * 0 on success, or a negative errno code otherwise.
- *
- * This is a &drm_device-managed version of mutex_init(). The initialized
- * lock is automatically destroyed on the final drm_dev_put().
- */
-int drmm_mutex_init(struct drm_device *dev, struct mutex *lock)
-{
-       mutex_init(lock);
-
-       return drmm_add_action_or_reset(dev, drmm_mutex_release, lock);
-}
-EXPORT_SYMBOL(drmm_mutex_init);
+EXPORT_SYMBOL(__drmm_mutex_release);
index 295382cd09b0baf389f907c9be3046599669770c..3fd6c733ff4e344f60bfcccf49bacc8d003ea1dc 100644 (file)
@@ -221,7 +221,7 @@ mipi_dsi_device_register_full(struct mipi_dsi_host *host,
                return dsi;
        }
 
-       dsi->dev.of_node = info->node;
+       device_set_node(&dsi->dev, of_fwnode_handle(info->node));
        dsi->channel = info->channel;
        strlcpy(dsi->name, info->type, sizeof(dsi->name));
 
index b1a38e6ce2f8fad28bbef491a02c29b7257beaa1..0cb646cb04ee1ae5028aa03439df18f06925760a 100644 (file)
@@ -179,7 +179,7 @@ static const struct dmi_system_id orientation_data[] = {
        }, {    /* AYA NEO AIR */
                .matches = {
                  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
-                 DMI_MATCH(DMI_BOARD_NAME, "AIR"),
+                 DMI_MATCH(DMI_PRODUCT_NAME, "AIR"),
                },
                .driver_data = (void *)&lcd1080x1920_leftside_up,
        }, {    /* AYA NEO NEXT */
index 74ea3c26deadcebabc7cae82b4e0d261269a2761..1a5ae781b56c60e41af91a5725e8cffa3e6f7b46 100644 (file)
@@ -34,11 +34,11 @@ static inline int exynos_g2d_exec_ioctl(struct drm_device *dev, void *data,
        return -ENODEV;
 }
 
-int g2d_open(struct drm_device *drm_dev, struct drm_file *file)
+static inline int g2d_open(struct drm_device *drm_dev, struct drm_file *file)
 {
        return 0;
 }
 
-void g2d_close(struct drm_device *drm_dev, struct drm_file *file)
+static inline void g2d_close(struct drm_device *drm_dev, struct drm_file *file)
 { }
 #endif
index 06a0ca157e89e44d66f6658aa0bbb7a22ca9fbe1..e4f4d2e3fdfebaf78f84edf73ebc861f4935d86d 100644 (file)
@@ -62,10 +62,11 @@ config DRM_I915_FORCE_PROBE
          This is the default value for the i915.force_probe module
          parameter. Using the module parameter overrides this option.
 
-         Force probe the i915 for Intel graphics devices that are
-         recognized but not properly supported by this kernel version. It is
-         recommended to upgrade to a kernel version with proper support as soon
-         as it is available.
+         Force probe the i915 driver for Intel graphics devices that are
+         recognized but not properly supported by this kernel version. Force
+         probing an unsupported device taints the kernel. It is recommended to
+         upgrade to a kernel version with proper support as soon as it is
+         available.
 
          It can also be used to block the probe of recognized and fully
          supported devices.
@@ -75,7 +76,8 @@ config DRM_I915_FORCE_PROBE
          Use "<pci-id>[,<pci-id>,...]" to force probe the i915 for listed
          devices. For example, "4500" or "4500,4571".
 
-         Use "*" to force probe the driver for all known devices.
+         Use "*" to force probe the driver for all known devices. Not
+         recommended.
 
          Use "!" right before the ID to block the probe of the device. For
          example, "4500,!4571" forces the probe of 4500 and blocks the probe of
index 40de9f0f171b479b6623e2a4197c2a75f08961f6..f33164b10292c5c9e37a191870b8ac7828a6a2bc 100644 (file)
@@ -1028,7 +1028,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
        int ret;
 
        if (old_obj) {
-               const struct intel_crtc_state *crtc_state =
+               const struct intel_crtc_state *new_crtc_state =
                        intel_atomic_get_new_crtc_state(state,
                                                        to_intel_crtc(old_plane_state->hw.crtc));
 
@@ -1043,7 +1043,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
                 * This should only fail upon a hung GPU, in which case we
                 * can safely continue.
                 */
-               if (intel_crtc_needs_modeset(crtc_state)) {
+               if (new_crtc_state && intel_crtc_needs_modeset(new_crtc_state)) {
                        ret = i915_sw_fence_await_reservation(&state->commit_ready,
                                                              old_obj->base.resv,
                                                              false, 0,
index 3c29792137a56d06e2c287b6c37a1e6671bfaf91..0aae9a1eb3d58438820d8a7daf940d7a9651c73b 100644 (file)
@@ -1851,9 +1851,17 @@ static void hsw_crtc_disable(struct intel_atomic_state *state,
 
        intel_disable_shared_dpll(old_crtc_state);
 
-       intel_encoders_post_pll_disable(state, crtc);
+       if (!intel_crtc_is_bigjoiner_slave(old_crtc_state)) {
+               struct intel_crtc *slave_crtc;
+
+               intel_encoders_post_pll_disable(state, crtc);
 
-       intel_dmc_disable_pipe(i915, crtc->pipe);
+               intel_dmc_disable_pipe(i915, crtc->pipe);
+
+               for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc,
+                                                intel_crtc_bigjoiner_slave_pipes(old_crtc_state))
+                       intel_dmc_disable_pipe(i915, slave_crtc->pipe);
+       }
 }
 
 static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state)
index f0bace9d98a18c16e5564f97506d540d786875d6..529ee22be872e7aea648d85aa54b0269095bb278 100644 (file)
@@ -1601,6 +1601,11 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
                pipe_config->dsc.slice_count =
                        drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd,
                                                        true);
+               if (!pipe_config->dsc.slice_count) {
+                       drm_dbg_kms(&dev_priv->drm, "Unsupported Slice Count %d\n",
+                                   pipe_config->dsc.slice_count);
+                       return -EINVAL;
+               }
        } else {
                u16 dsc_max_output_bpp = 0;
                u8 dsc_dp_slice_count;
index 650232c4892b183800fa86adbe518e964cc0c29b..b183efab04a1d4c06f0fc05a5e96f0ccb8eca7ca 100644 (file)
@@ -204,8 +204,6 @@ bool intel_hdcp2_capable(struct intel_connector *connector)
        struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
        struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
        struct intel_hdcp *hdcp = &connector->hdcp;
-       struct intel_gt *gt = dev_priv->media_gt;
-       struct intel_gsc_uc *gsc = &gt->uc.gsc;
        bool capable = false;
 
        /* I915 support for HDCP2.2 */
@@ -213,9 +211,13 @@ bool intel_hdcp2_capable(struct intel_connector *connector)
                return false;
 
        /* If MTL+ make sure gsc is loaded and proxy is setup */
-       if (intel_hdcp_gsc_cs_required(dev_priv))
-               if (!intel_uc_fw_is_running(&gsc->fw))
+       if (intel_hdcp_gsc_cs_required(dev_priv)) {
+               struct intel_gt *gt = dev_priv->media_gt;
+               struct intel_gsc_uc *gsc = gt ? &gt->uc.gsc : NULL;
+
+               if (!gsc || !intel_uc_fw_is_running(&gsc->fw))
                        return false;
+       }
 
        /* MEI/GSC interface is solid depending on which is used */
        mutex_lock(&dev_priv->display.hdcp.comp_mutex);
index cf49188db6a6e3a0193f143fdc710e00707f40da..e0e793167d61b5b3c22f9f627fc331aa269a2016 100644 (file)
        { FORCEWAKE_MT,             0,      0, "FORCEWAKE" }
 
 #define COMMON_GEN9BASE_GLOBAL \
-       { GEN8_FAULT_TLB_DATA0,     0,      0, "GEN8_FAULT_TLB_DATA0" }, \
-       { GEN8_FAULT_TLB_DATA1,     0,      0, "GEN8_FAULT_TLB_DATA1" }, \
        { ERROR_GEN6,               0,      0, "ERROR_GEN6" }, \
        { DONE_REG,                 0,      0, "DONE_REG" }, \
        { HSW_GTT_CACHE_EN,         0,      0, "HSW_GTT_CACHE_EN" }
 
+#define GEN9_GLOBAL \
+       { GEN8_FAULT_TLB_DATA0,     0,      0, "GEN8_FAULT_TLB_DATA0" }, \
+       { GEN8_FAULT_TLB_DATA1,     0,      0, "GEN8_FAULT_TLB_DATA1" }
+
 #define COMMON_GEN12BASE_GLOBAL \
        { GEN12_FAULT_TLB_DATA0,    0,      0, "GEN12_FAULT_TLB_DATA0" }, \
        { GEN12_FAULT_TLB_DATA1,    0,      0, "GEN12_FAULT_TLB_DATA1" }, \
@@ -142,6 +144,7 @@ static const struct __guc_mmio_reg_descr xe_lpd_gsc_inst_regs[] = {
 static const struct __guc_mmio_reg_descr default_global_regs[] = {
        COMMON_BASE_GLOBAL,
        COMMON_GEN9BASE_GLOBAL,
+       GEN9_GLOBAL,
 };
 
 static const struct __guc_mmio_reg_descr default_rc_class_regs[] = {
index 2a012da8ccfaa65be2d54c42f9f5fa964ea4014a..edcfb5fe20b242d6b327902a3ce785fcb8b9ef96 100644 (file)
@@ -1344,6 +1344,12 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                return -ENODEV;
        }
 
+       if (intel_info->require_force_probe) {
+               dev_info(&pdev->dev, "Force probing unsupported Device ID %04x, tainting kernel\n",
+                        pdev->device);
+               add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+       }
+
        /* Only bind to function 0 of the device. Early generations
         * used function 1 as a placeholder for multi-head. This causes
         * us confusion instead, especially on the systems where both
index 050b8ae7b8e70b7b58a9844fcf7c4ca5b53cc908..3035cba2c6a29e16999dc308d96510d42c3206ae 100644 (file)
@@ -877,12 +877,17 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
                        stream->oa_buffer.last_ctx_id = ctx_id;
                }
 
-               /*
-                * Clear out the report id and timestamp as a means to detect unlanded
-                * reports.
-                */
-               oa_report_id_clear(stream, report32);
-               oa_timestamp_clear(stream, report32);
+               if (is_power_of_2(report_size)) {
+                       /*
+                        * Clear out the report id and timestamp as a means
+                        * to detect unlanded reports.
+                        */
+                       oa_report_id_clear(stream, report32);
+                       oa_timestamp_clear(stream, report32);
+               } else {
+                       /* Zero out the entire report */
+                       memset(report32, 0, report_size);
+               }
        }
 
        if (start_offset != *offset) {
index 0f2dd26755df98e9052484a5fafd208b645eefa6..af3ce5a6a636ac7bceb83539b66cbfc0a66d45b4 100644 (file)
@@ -642,6 +642,11 @@ void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_
        if (funcs->pixpllc_atomic_update)
                funcs->pixpllc_atomic_update(crtc, old_state);
 
+       if (crtc_state->gamma_lut)
+               mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut->data);
+       else
+               mgag200_crtc_set_gamma_linear(mdev, format);
+
        mgag200_enable_display(mdev);
 
        if (funcs->enable_vidrst)
index 2b3ae84057dfe0fdc87ef73b40da378dd06979e3..bdcd554fc8a80d5c45ce34070ad9236523b507d1 100644 (file)
@@ -98,17 +98,17 @@ static const struct dpu_sspp_cfg msm8998_sspp[] = {
 
 static const struct dpu_lm_cfg msm8998_lm[] = {
        LM_BLK("lm_0", LM_0, 0x44000, MIXER_MSM8998_MASK,
-               &msm8998_lm_sblk, PINGPONG_0, LM_2, DSPP_0),
+               &msm8998_lm_sblk, PINGPONG_0, LM_1, DSPP_0),
        LM_BLK("lm_1", LM_1, 0x45000, MIXER_MSM8998_MASK,
-               &msm8998_lm_sblk, PINGPONG_1, LM_5, DSPP_1),
+               &msm8998_lm_sblk, PINGPONG_1, LM_0, DSPP_1),
        LM_BLK("lm_2", LM_2, 0x46000, MIXER_MSM8998_MASK,
-               &msm8998_lm_sblk, PINGPONG_2, LM_0, 0),
+               &msm8998_lm_sblk, PINGPONG_2, LM_5, 0),
        LM_BLK("lm_3", LM_3, 0x47000, MIXER_MSM8998_MASK,
                &msm8998_lm_sblk, PINGPONG_MAX, 0, 0),
        LM_BLK("lm_4", LM_4, 0x48000, MIXER_MSM8998_MASK,
                &msm8998_lm_sblk, PINGPONG_MAX, 0, 0),
        LM_BLK("lm_5", LM_5, 0x49000, MIXER_MSM8998_MASK,
-               &msm8998_lm_sblk, PINGPONG_3, LM_1, 0),
+               &msm8998_lm_sblk, PINGPONG_3, LM_2, 0),
 };
 
 static const struct dpu_pingpong_cfg msm8998_pp[] = {
@@ -134,10 +134,10 @@ static const struct dpu_dspp_cfg msm8998_dspp[] = {
 };
 
 static const struct dpu_intf_cfg msm8998_intf[] = {
-       INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
-       INTF_BLK("intf_1", INTF_1, 0x6a800, 0x280, INTF_DSI, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
-       INTF_BLK("intf_2", INTF_2, 0x6b000, 0x280, INTF_DSI, 1, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
-       INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_HDMI, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
+       INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
+       INTF_BLK("intf_1", INTF_1, 0x6a800, 0x280, INTF_DSI, 0, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
+       INTF_BLK("intf_2", INTF_2, 0x6b000, 0x280, INTF_DSI, 1, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
+       INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_HDMI, 0, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
 };
 
 static const struct dpu_perf_cfg msm8998_perf_data = {
index 282d410269ff62b55108794a0c8479e665c855e6..42b0e58624d0087c5760f710021c1758e46b3fdd 100644 (file)
@@ -128,10 +128,10 @@ static const struct dpu_dspp_cfg sm8150_dspp[] = {
 };
 
 static const struct dpu_pingpong_cfg sm8150_pp[] = {
-       PP_BLK_TE("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk_te,
+       PP_BLK("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)),
-       PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk_te,
+       PP_BLK("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)),
        PP_BLK("pingpong_2", PINGPONG_2, 0x71000, MERGE_3D_1, sdm845_pp_sblk,
index c57400265f288403f39b11d4f87fd489a248eca6..e3bdfe7b30f1f19552128e468f6d9ebf5d1fa5a2 100644 (file)
@@ -116,10 +116,10 @@ static const struct dpu_lm_cfg sc8180x_lm[] = {
 };
 
 static const struct dpu_pingpong_cfg sc8180x_pp[] = {
-       PP_BLK_TE("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk_te,
+       PP_BLK("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)),
-       PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk_te,
+       PP_BLK("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)),
        PP_BLK("pingpong_2", PINGPONG_2, 0x71000, MERGE_3D_1, sdm845_pp_sblk,
index 2c40229ea51594439a02acb7c16f04d05cfccb49..ed130582873c7037294dccdd6798fa66bc0948de 100644 (file)
@@ -129,10 +129,10 @@ static const struct dpu_dspp_cfg sm8250_dspp[] = {
 };
 
 static const struct dpu_pingpong_cfg sm8250_pp[] = {
-       PP_BLK_TE("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk_te,
+       PP_BLK("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)),
-       PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk_te,
+       PP_BLK("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)),
        PP_BLK("pingpong_2", PINGPONG_2, 0x71000, MERGE_3D_1, sdm845_pp_sblk,
index 8799ed7571190fb7a4726d72a04a31b6dcf26458..a46b11730a4d4a2c43a295ade916b75b158328a4 100644 (file)
@@ -80,8 +80,8 @@ static const struct dpu_dspp_cfg sc7180_dspp[] = {
 };
 
 static const struct dpu_pingpong_cfg sc7180_pp[] = {
-       PP_BLK_TE("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk_te, -1, -1),
-       PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800, 0, sdm845_pp_sblk_te, -1, -1),
+       PP_BLK("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk, -1, -1),
+       PP_BLK("pingpong_1", PINGPONG_1, 0x70800, 0, sdm845_pp_sblk, -1, -1),
 };
 
 static const struct dpu_intf_cfg sc7180_intf[] = {
index 6f04d8f85c9250ef65aa7b2bc3e628d497a0c275..988d820f7ef2e5e7059e368cdfed0777dcd516f8 100644 (file)
@@ -122,7 +122,6 @@ const struct dpu_mdss_cfg dpu_sm6115_cfg = {
        .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
                     BIT(MDP_SSPP_TOP0_INTR2) | \
                     BIT(MDP_SSPP_TOP0_HIST_INTR) | \
-                    BIT(MDP_INTF0_INTR) | \
                     BIT(MDP_INTF1_INTR),
 };
 
index 303492d62a5caaa38e39921289f35b672909a9c8..c9003dcc1a59b6221110b58bb9d4a0f930d30c0e 100644 (file)
@@ -112,7 +112,6 @@ const struct dpu_mdss_cfg dpu_qcm2290_cfg = {
        .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
                     BIT(MDP_SSPP_TOP0_INTR2) | \
                     BIT(MDP_SSPP_TOP0_HIST_INTR) | \
-                    BIT(MDP_INTF0_INTR) | \
                     BIT(MDP_INTF1_INTR),
 };
 
index ca107ca8de462482278c3799cf01b953504293ac..4f6a965bcd90b187a99146d74bdc9f3c4ca32dd6 100644 (file)
@@ -127,22 +127,22 @@ static const struct dpu_dspp_cfg sm8350_dspp[] = {
 };
 
 static const struct dpu_pingpong_cfg sm8350_pp[] = {
-       PP_BLK_TE("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sdm845_pp_sblk_te,
+       PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)),
-       PP_BLK_TE("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sdm845_pp_sblk_te,
+       PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)),
-       PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sdm845_pp_sblk,
+       PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)),
-       PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sdm845_pp_sblk,
+       PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)),
-       PP_BLK("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sdm845_pp_sblk,
+       PP_BLK_DITHER("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30),
                        -1),
-       PP_BLK("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sdm845_pp_sblk,
+       PP_BLK_DITHER("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
                        -1),
 };
index 5957de1859844f633cc414d3e9059ab3203f78be..6b2c7eae71d998ed1beb3238d4f15a64784b76bd 100644 (file)
@@ -87,10 +87,10 @@ static const struct dpu_dspp_cfg sc7280_dspp[] = {
 };
 
 static const struct dpu_pingpong_cfg sc7280_pp[] = {
-       PP_BLK("pingpong_0", PINGPONG_0, 0x69000, 0, sc7280_pp_sblk, -1, -1),
-       PP_BLK("pingpong_1", PINGPONG_1, 0x6a000, 0, sc7280_pp_sblk, -1, -1),
-       PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, -1, -1),
-       PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, -1, -1),
+       PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, 0, sc7280_pp_sblk, -1, -1),
+       PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, 0, sc7280_pp_sblk, -1, -1),
+       PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, -1, -1),
+       PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, -1, -1),
 };
 
 static const struct dpu_intf_cfg sc7280_intf[] = {
index 9aab110b8c44d67458eb507a0bea99b54ed73553..706d0f13b598e53772eafeb1b6a455c2ee488dff 100644 (file)
@@ -121,18 +121,18 @@ static const struct dpu_dspp_cfg sc8280xp_dspp[] = {
 };
 
 static const struct dpu_pingpong_cfg sc8280xp_pp[] = {
-       PP_BLK_TE("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sdm845_pp_sblk_te,
-                 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), -1),
-       PP_BLK_TE("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sdm845_pp_sblk_te,
-                 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), -1),
-       PP_BLK_TE("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sdm845_pp_sblk_te,
-                 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), -1),
-       PP_BLK_TE("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sdm845_pp_sblk_te,
-                 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), -1),
-       PP_BLK_TE("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sdm845_pp_sblk_te,
-                 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), -1),
-       PP_BLK_TE("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sdm845_pp_sblk_te,
-                 DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), -1),
+       PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sc7280_pp_sblk,
+                       DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), -1),
+       PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sc7280_pp_sblk,
+                       DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), -1),
+       PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sc7280_pp_sblk,
+                       DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), -1),
+       PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sc7280_pp_sblk,
+                       DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), -1),
+       PP_BLK_DITHER("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sc7280_pp_sblk,
+                       DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), -1),
+       PP_BLK_DITHER("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sc7280_pp_sblk,
+                       DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), -1),
 };
 
 static const struct dpu_merge_3d_cfg sc8280xp_merge_3d[] = {
index 02a259b6b4268e8ac521e7b5069b5e0f024a01f7..4ecb3df5cbc022e68ba9cfb127c8da829a6d9fdb 100644 (file)
@@ -128,28 +128,28 @@ static const struct dpu_dspp_cfg sm8450_dspp[] = {
 };
 /* FIXME: interrupts */
 static const struct dpu_pingpong_cfg sm8450_pp[] = {
-       PP_BLK_TE("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sdm845_pp_sblk_te,
+       PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)),
-       PP_BLK_TE("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sdm845_pp_sblk_te,
+       PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)),
-       PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sdm845_pp_sblk,
+       PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)),
-       PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sdm845_pp_sblk,
+       PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)),
-       PP_BLK("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sdm845_pp_sblk,
+       PP_BLK_DITHER("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30),
                        -1),
-       PP_BLK("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sdm845_pp_sblk,
+       PP_BLK_DITHER("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
                        -1),
-       PP_BLK("pingpong_6", PINGPONG_6, 0x65800, MERGE_3D_3, sdm845_pp_sblk,
+       PP_BLK_DITHER("pingpong_6", PINGPONG_6, 0x65800, MERGE_3D_3, sc7280_pp_sblk,
                        -1,
                        -1),
-       PP_BLK("pingpong_7", PINGPONG_7, 0x65c00, MERGE_3D_3, sdm845_pp_sblk,
+       PP_BLK_DITHER("pingpong_7", PINGPONG_7, 0x65c00, MERGE_3D_3, sc7280_pp_sblk,
                        -1,
                        -1),
 };
index 9e403034093fdc81cf04c90bce561afe14d3bca0..d0ab351b6a8b934226fded7bdcf9db3ee30ac80a 100644 (file)
@@ -132,28 +132,28 @@ static const struct dpu_dspp_cfg sm8550_dspp[] = {
                 &sm8150_dspp_sblk),
 };
 static const struct dpu_pingpong_cfg sm8550_pp[] = {
-       PP_BLK_DIPHER("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sc7280_pp_sblk,
+       PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
                        -1),
-       PP_BLK_DIPHER("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sc7280_pp_sblk,
+       PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
                        -1),
-       PP_BLK_DIPHER("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sc7280_pp_sblk,
+       PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
                        -1),
-       PP_BLK_DIPHER("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sc7280_pp_sblk,
+       PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
                        -1),
-       PP_BLK_DIPHER("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sc7280_pp_sblk,
+       PP_BLK_DITHER("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30),
                        -1),
-       PP_BLK_DIPHER("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sc7280_pp_sblk,
+       PP_BLK_DITHER("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sc7280_pp_sblk,
                        DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
                        -1),
-       PP_BLK_DIPHER("pingpong_6", PINGPONG_6, 0x66000, MERGE_3D_3, sc7280_pp_sblk,
+       PP_BLK_DITHER("pingpong_6", PINGPONG_6, 0x66000, MERGE_3D_3, sc7280_pp_sblk,
                        -1,
                        -1),
-       PP_BLK_DIPHER("pingpong_7", PINGPONG_7, 0x66400, MERGE_3D_3, sc7280_pp_sblk,
+       PP_BLK_DITHER("pingpong_7", PINGPONG_7, 0x66400, MERGE_3D_3, sc7280_pp_sblk,
                        -1,
                        -1),
 };
index 03f162af1a50bcaa996576f99dc6c3ac23bbc6d5..5d994bce696f9e76e6387aa1bf66bc8c6cbac298 100644 (file)
@@ -491,7 +491,7 @@ static const struct dpu_pingpong_sub_blks sc7280_pp_sblk = {
        .len = 0x20, .version = 0x20000},
 };
 
-#define PP_BLK_DIPHER(_name, _id, _base, _merge_3d, _sblk, _done, _rdptr) \
+#define PP_BLK_DITHER(_name, _id, _base, _merge_3d, _sblk, _done, _rdptr) \
        {\
        .name = _name, .id = _id, \
        .base = _base, .len = 0, \
@@ -587,12 +587,12 @@ static const u32 sdm845_nrt_pri_lvl[] = {3, 3, 3, 3, 3, 3, 3, 3};
 
 static const struct dpu_vbif_dynamic_ot_cfg msm8998_ot_rdwr_cfg[] = {
        {
-               .pps = 1088 * 1920 * 30,
+               .pps = 1920 * 1080 * 30,
                .ot_limit = 2,
        },
        {
-               .pps = 1088 * 1920 * 60,
-               .ot_limit = 6,
+               .pps = 1920 * 1080 * 60,
+               .ot_limit = 4,
        },
        {
                .pps = 3840 * 2160 * 30,
@@ -705,10 +705,7 @@ static const struct dpu_qos_lut_entry msm8998_qos_linear[] = {
        {.fl = 10, .lut = 0x1555b},
        {.fl = 11, .lut = 0x5555b},
        {.fl = 12, .lut = 0x15555b},
-       {.fl = 13, .lut = 0x55555b},
-       {.fl = 14, .lut = 0},
-       {.fl = 1,  .lut = 0x1b},
-       {.fl = 0,  .lut = 0}
+       {.fl = 0,  .lut = 0x55555b}
 };
 
 static const struct dpu_qos_lut_entry sdm845_qos_linear[] = {
@@ -730,9 +727,7 @@ static const struct dpu_qos_lut_entry msm8998_qos_macrotile[] = {
        {.fl = 10, .lut = 0x1aaff},
        {.fl = 11, .lut = 0x5aaff},
        {.fl = 12, .lut = 0x15aaff},
-       {.fl = 13, .lut = 0x55aaff},
-       {.fl = 1,  .lut = 0x1aaff},
-       {.fl = 0,  .lut = 0},
+       {.fl = 0,  .lut = 0x55aaff},
 };
 
 static const struct dpu_qos_lut_entry sc7180_qos_linear[] = {
index 53326f25e40ef10b22bb09da70b829d4defa0553..17f3e7e4f1941052ddebbc562bcea0ba5f7b91f4 100644 (file)
@@ -15,7 +15,7 @@
 
 /*
  * Register offsets in MDSS register file for the interrupt registers
- * w.r.t. to the MDP base
+ * w.r.t. the MDP base
  */
 #define MDP_SSPP_TOP0_OFF              0x0
 #define MDP_INTF_0_OFF                 0x6A000
 #define MDP_INTF_3_OFF                 0x6B800
 #define MDP_INTF_4_OFF                 0x6C000
 #define MDP_INTF_5_OFF                 0x6C800
+#define INTF_INTR_EN                   0x1c0
+#define INTF_INTR_STATUS               0x1c4
+#define INTF_INTR_CLEAR                        0x1c8
 #define MDP_AD4_0_OFF                  0x7C000
 #define MDP_AD4_1_OFF                  0x7D000
 #define MDP_AD4_INTR_EN_OFF            0x41c
 #define MDP_AD4_INTR_CLEAR_OFF         0x424
 #define MDP_AD4_INTR_STATUS_OFF                0x420
-#define MDP_INTF_0_OFF_REV_7xxx             0x34000
-#define MDP_INTF_1_OFF_REV_7xxx             0x35000
-#define MDP_INTF_2_OFF_REV_7xxx             0x36000
-#define MDP_INTF_3_OFF_REV_7xxx             0x37000
-#define MDP_INTF_4_OFF_REV_7xxx             0x38000
-#define MDP_INTF_5_OFF_REV_7xxx             0x39000
-#define MDP_INTF_6_OFF_REV_7xxx             0x3a000
-#define MDP_INTF_7_OFF_REV_7xxx             0x3b000
-#define MDP_INTF_8_OFF_REV_7xxx             0x3c000
+#define MDP_INTF_0_OFF_REV_7xxx                0x34000
+#define MDP_INTF_1_OFF_REV_7xxx                0x35000
+#define MDP_INTF_2_OFF_REV_7xxx                0x36000
+#define MDP_INTF_3_OFF_REV_7xxx                0x37000
+#define MDP_INTF_4_OFF_REV_7xxx                0x38000
+#define MDP_INTF_5_OFF_REV_7xxx                0x39000
+#define MDP_INTF_6_OFF_REV_7xxx                0x3a000
+#define MDP_INTF_7_OFF_REV_7xxx                0x3b000
+#define MDP_INTF_8_OFF_REV_7xxx                0x3c000
 
 /**
  * struct dpu_intr_reg - array of DPU register sets
index 84ee2efa9c664e04c89e3d898cd11914c99cc275..b9dddf576c029f0d136ce281eff897f7f041953b 100644 (file)
 #define   INTF_TPG_RGB_MAPPING          0x11C
 #define   INTF_PROG_FETCH_START         0x170
 #define   INTF_PROG_ROT_START           0x174
-
-#define   INTF_FRAME_LINE_COUNT_EN      0x0A8
-#define   INTF_FRAME_COUNT              0x0AC
-#define   INTF_LINE_COUNT               0x0B0
-
 #define   INTF_MUX                      0x25C
 #define   INTF_STATUS                   0x26C
 
index 2d28afdf860efc43709e1c648be6607763ef4603..a3e413d277175e360a96557197cb4ba3ab2a6bf7 100644 (file)
@@ -61,6 +61,7 @@ static const struct dpu_wb_cfg *_wb_offset(enum dpu_wb wb,
        for (i = 0; i < m->wb_count; i++) {
                if (wb == m->wb[i].id) {
                        b->blk_addr = addr + m->wb[i].base;
+                       b->log_mask = DPU_DBG_MASK_WB;
                        return &m->wb[i];
                }
        }
index feb9a729844a3c1488419e360382e48ac3f16e1b..5acd5683d25a4021950a80d341d732ac6d7fc856 100644 (file)
@@ -21,9 +21,6 @@
 #define HIST_INTR_EN                    0x01c
 #define HIST_INTR_STATUS                0x020
 #define HIST_INTR_CLEAR                 0x024
-#define INTF_INTR_EN                    0x1C0
-#define INTF_INTR_STATUS                0x1C4
-#define INTF_INTR_CLEAR                 0x1C8
 #define SPLIT_DISPLAY_EN                0x2F4
 #define SPLIT_DISPLAY_UPPER_PIPE_CTRL   0x2F8
 #define DSPP_IGC_COLOR0_RAM_LUTN        0x300
index 6666783e1468e33f3ddaefcfd51789de7588649f..1245c7aa49df844ce293207c6a74374eb0bee805 100644 (file)
@@ -593,6 +593,18 @@ static struct hdmi_codec_pdata codec_data = {
        .i2s = 1,
 };
 
+void dp_unregister_audio_driver(struct device *dev, struct dp_audio *dp_audio)
+{
+       struct dp_audio_private *audio_priv;
+
+       audio_priv = container_of(dp_audio, struct dp_audio_private, dp_audio);
+
+       if (audio_priv->audio_pdev) {
+               platform_device_unregister(audio_priv->audio_pdev);
+               audio_priv->audio_pdev = NULL;
+       }
+}
+
 int dp_register_audio_driver(struct device *dev,
                struct dp_audio *dp_audio)
 {
index 84e5f4a5d26badb0bfc8d5f8858681ab5e310ec1..4ab78880af8296efd50654967e297eccf83adc17 100644 (file)
@@ -53,6 +53,8 @@ struct dp_audio *dp_audio_get(struct platform_device *pdev,
 int dp_register_audio_driver(struct device *dev,
                struct dp_audio *dp_audio);
 
+void dp_unregister_audio_driver(struct device *dev, struct dp_audio *dp_audio);
+
 /**
  * dp_audio_put()
  *
index 3e13acdfa7e533825f5991ee8470a595d32d1327..99a38dbe51c0fff8cde094858b8d65699a6a9f30 100644 (file)
@@ -326,6 +326,7 @@ static void dp_display_unbind(struct device *dev, struct device *master,
        kthread_stop(dp->ev_tsk);
 
        dp_power_client_deinit(dp->power);
+       dp_unregister_audio_driver(dev, dp->audio);
        dp_aux_unregister(dp->aux);
        dp->drm_dev = NULL;
        dp->aux->drm_dev = NULL;
index d77fa9793c54dc7adb001f9e81dd12ecad891f2a..9c45d641b5212c11078ab38c13a519663d85e10a 100644 (file)
@@ -155,6 +155,8 @@ static bool can_do_async(struct drm_atomic_state *state,
        for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
                if (drm_atomic_crtc_needs_modeset(crtc_state))
                        return false;
+               if (!crtc_state->active)
+                       return false;
                if (++num_crtcs > 1)
                        return false;
                *async_crtc = crtc;
index db6c4e281d75d06dc169c0e48d7c112413db682e..cd39b9d8abdbeb96aad9495552f3f113aa3a008e 100644 (file)
@@ -219,7 +219,8 @@ static void put_pages(struct drm_gem_object *obj)
        }
 }
 
-static struct page **msm_gem_pin_pages_locked(struct drm_gem_object *obj)
+static struct page **msm_gem_pin_pages_locked(struct drm_gem_object *obj,
+                                             unsigned madv)
 {
        struct msm_drm_private *priv = obj->dev->dev_private;
        struct msm_gem_object *msm_obj = to_msm_bo(obj);
@@ -227,7 +228,9 @@ static struct page **msm_gem_pin_pages_locked(struct drm_gem_object *obj)
 
        msm_gem_assert_locked(obj);
 
-       if (GEM_WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED)) {
+       if (GEM_WARN_ON(msm_obj->madv > madv)) {
+               DRM_DEV_ERROR(obj->dev->dev, "Invalid madv state: %u vs %u\n",
+                       msm_obj->madv, madv);
                return ERR_PTR(-EBUSY);
        }
 
@@ -248,7 +251,7 @@ struct page **msm_gem_pin_pages(struct drm_gem_object *obj)
        struct page **p;
 
        msm_gem_lock(obj);
-       p = msm_gem_pin_pages_locked(obj);
+       p = msm_gem_pin_pages_locked(obj, MSM_MADV_WILLNEED);
        msm_gem_unlock(obj);
 
        return p;
@@ -473,10 +476,7 @@ int msm_gem_pin_vma_locked(struct drm_gem_object *obj, struct msm_gem_vma *vma)
 
        msm_gem_assert_locked(obj);
 
-       if (GEM_WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED))
-               return -EBUSY;
-
-       pages = msm_gem_pin_pages_locked(obj);
+       pages = msm_gem_pin_pages_locked(obj, MSM_MADV_WILLNEED);
        if (IS_ERR(pages))
                return PTR_ERR(pages);
 
@@ -699,13 +699,7 @@ static void *get_vaddr(struct drm_gem_object *obj, unsigned madv)
        if (obj->import_attach)
                return ERR_PTR(-ENODEV);
 
-       if (GEM_WARN_ON(msm_obj->madv > madv)) {
-               DRM_DEV_ERROR(obj->dev->dev, "Invalid madv state: %u vs %u\n",
-                       msm_obj->madv, madv);
-               return ERR_PTR(-EBUSY);
-       }
-
-       pages = msm_gem_pin_pages_locked(obj);
+       pages = msm_gem_pin_pages_locked(obj, madv);
        if (IS_ERR(pages))
                return ERR_CAST(pages);
 
index aff18c2f600ab2050d52cd05ba924d3b4ae68a20..9f5933c75e3df981177c9b38edcadab411b60d38 100644 (file)
@@ -722,7 +722,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
        struct msm_drm_private *priv = dev->dev_private;
        struct drm_msm_gem_submit *args = data;
        struct msm_file_private *ctx = file->driver_priv;
-       struct msm_gem_submit *submit;
+       struct msm_gem_submit *submit = NULL;
        struct msm_gpu *gpu = priv->gpu;
        struct msm_gpu_submitqueue *queue;
        struct msm_ringbuffer *ring;
@@ -769,13 +769,15 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
                out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
                if (out_fence_fd < 0) {
                        ret = out_fence_fd;
-                       return ret;
+                       goto out_post_unlock;
                }
        }
 
        submit = submit_create(dev, gpu, queue, args->nr_bos, args->nr_cmds);
-       if (IS_ERR(submit))
-               return PTR_ERR(submit);
+       if (IS_ERR(submit)) {
+               ret = PTR_ERR(submit);
+               goto out_post_unlock;
+       }
 
        trace_msm_gpu_submit(pid_nr(submit->pid), ring->id, submit->ident,
                args->nr_bos, args->nr_cmds);
@@ -962,11 +964,20 @@ out:
        if (has_ww_ticket)
                ww_acquire_fini(&submit->ticket);
 out_unlock:
-       if (ret && (out_fence_fd >= 0))
-               put_unused_fd(out_fence_fd);
        mutex_unlock(&queue->lock);
 out_post_unlock:
-       msm_gem_submit_put(submit);
+       if (ret && (out_fence_fd >= 0))
+               put_unused_fd(out_fence_fd);
+
+       if (!IS_ERR_OR_NULL(submit)) {
+               msm_gem_submit_put(submit);
+       } else {
+               /*
+                * If the submit hasn't yet taken ownership of the queue
+                * then we need to drop the reference ourself:
+                */
+               msm_submitqueue_put(queue);
+       }
        if (!IS_ERR_OR_NULL(post_deps)) {
                for (i = 0; i < args->nr_out_syncobjs; ++i) {
                        kfree(post_deps[i].chain);
index 418e1e06cddefd83b7cfd5aa57f2197de2f4f489..5cc8d358cc9759307a444cd62bce83c62b3dcdb7 100644 (file)
@@ -234,7 +234,12 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent)
        /* Get the pagetable configuration from the domain */
        if (adreno_smmu->cookie)
                ttbr1_cfg = adreno_smmu->get_ttbr1_cfg(adreno_smmu->cookie);
-       if (!ttbr1_cfg)
+
+       /*
+        * If you hit this WARN_ONCE() you are probably missing an entry in
+        * qcom_smmu_impl_of_match[] in arm-smmu-qcom.c
+        */
+       if (WARN_ONCE(!ttbr1_cfg, "No per-process page tables"))
                return ERR_PTR(-ENODEV);
 
        pagetable = kzalloc(sizeof(*pagetable), GFP_KERNEL);
@@ -410,7 +415,7 @@ struct msm_mmu *msm_iommu_gpu_new(struct device *dev, struct msm_gpu *gpu, unsig
        struct msm_mmu *mmu;
 
        mmu = msm_iommu_new(dev, quirks);
-       if (IS_ERR(mmu))
+       if (IS_ERR_OR_NULL(mmu))
                return mmu;
 
        iommu = to_msm_iommu(mmu);
index eb99d84eb84431104de11a49fa1d2b8058548b6f..16d4ad5023a3ead5861c56a0a1802a1713ea8da5 100644 (file)
@@ -2,6 +2,8 @@
 #ifndef __NVIF_IF0012_H__
 #define __NVIF_IF0012_H__
 
+#include <drm/display/drm_dp.h>
+
 union nvif_outp_args {
        struct nvif_outp_v0 {
                __u8 version;
@@ -63,7 +65,7 @@ union nvif_outp_acquire_args {
                                __u8 hda;
                                __u8 mst;
                                __u8 pad04[4];
-                               __u8 dpcd[16];
+                               __u8 dpcd[DP_RECEIVER_CAP_SIZE];
                        } dp;
                };
        } v0;
index b7631c1ab2420fcaf34af9157bd3bde383c2ba37..4e7f873f66e27fb46351731267a4c8e61a23c114 100644 (file)
@@ -3,6 +3,7 @@
 #define __NVKM_DISP_OUTP_H__
 #include "priv.h"
 
+#include <drm/display/drm_dp.h>
 #include <subdev/bios.h>
 #include <subdev/bios/dcb.h>
 #include <subdev/bios/dp.h>
@@ -42,7 +43,7 @@ struct nvkm_outp {
                        bool aux_pwr_pu;
                        u8 lttpr[6];
                        u8 lttprs;
-                       u8 dpcd[16];
+                       u8 dpcd[DP_RECEIVER_CAP_SIZE];
 
                        struct {
                                int dpcd; /* -1, or index into SUPPORTED_LINK_RATES table */
index 4f0ca709c85a402ea7cadb9eea7038b398977071..fc283a4a1522a6d4d0ea4a33be24fd918b774f7a 100644 (file)
@@ -146,7 +146,7 @@ nvkm_uoutp_mthd_release(struct nvkm_outp *outp, void *argv, u32 argc)
 }
 
 static int
-nvkm_uoutp_mthd_acquire_dp(struct nvkm_outp *outp, u8 dpcd[16],
+nvkm_uoutp_mthd_acquire_dp(struct nvkm_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE],
                           u8 link_nr, u8 link_bw, bool hda, bool mst)
 {
        int ret;
index 6afdf260a4e226492637fa1f27f5a6b33de95918..b9fe926a49e8bb42116ac382010829e333edbf8f 100644 (file)
@@ -53,7 +53,7 @@ pl111_mode_valid(struct drm_simple_display_pipe *pipe,
 {
        struct drm_device *drm = pipe->crtc.dev;
        struct pl111_drm_dev_private *priv = drm->dev_private;
-       u32 cpp = priv->variant->fb_bpp / 8;
+       u32 cpp = DIV_ROUND_UP(priv->variant->fb_depth, 8);
        u64 bw;
 
        /*
index 2a46b5bd857649eb811e5d27b122ca3515397d2e..d1fe756444ee52056da07b6189d39d6fa441cb8d 100644 (file)
@@ -114,7 +114,7 @@ struct drm_minor;
  *     extensions to the control register
  * @formats: array of supported pixel formats on this variant
  * @nformats: the length of the array of supported pixel formats
- * @fb_bpp: desired bits per pixel on the default framebuffer
+ * @fb_depth: desired depth per pixel on the default framebuffer
  */
 struct pl111_variant_data {
        const char *name;
@@ -126,7 +126,7 @@ struct pl111_variant_data {
        bool st_bitmux_control;
        const u32 *formats;
        unsigned int nformats;
-       unsigned int fb_bpp;
+       unsigned int fb_depth;
 };
 
 struct pl111_drm_dev_private {
index 4b2a9e9753f6da9cf1bbab087ff7533a6c0ac01b..43049c8028b21649c232cf33ddfe5681cac29644 100644 (file)
@@ -308,7 +308,7 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
        if (ret < 0)
                goto dev_put;
 
-       drm_fbdev_dma_setup(drm, priv->variant->fb_bpp);
+       drm_fbdev_dma_setup(drm, priv->variant->fb_depth);
 
        return 0;
 
@@ -351,7 +351,7 @@ static const struct pl111_variant_data pl110_variant = {
        .is_pl110 = true,
        .formats = pl110_pixel_formats,
        .nformats = ARRAY_SIZE(pl110_pixel_formats),
-       .fb_bpp = 16,
+       .fb_depth = 16,
 };
 
 /* RealView, Versatile Express etc use this modern variant */
@@ -376,7 +376,7 @@ static const struct pl111_variant_data pl111_variant = {
        .name = "PL111",
        .formats = pl111_pixel_formats,
        .nformats = ARRAY_SIZE(pl111_pixel_formats),
-       .fb_bpp = 32,
+       .fb_depth = 32,
 };
 
 static const u32 pl110_nomadik_pixel_formats[] = {
@@ -405,7 +405,7 @@ static const struct pl111_variant_data pl110_nomadik_variant = {
        .is_lcdc = true,
        .st_bitmux_control = true,
        .broken_vblank = true,
-       .fb_bpp = 16,
+       .fb_depth = 16,
 };
 
 static const struct amba_id pl111_id_table[] = {
index 1b436b75fd396f2bf71ab067a873873ccd484fd5..00c3ebd32359b975c553e1b275c7e3b64d727879 100644 (file)
@@ -316,7 +316,7 @@ static const struct pl111_variant_data pl110_integrator = {
        .broken_vblank = true,
        .formats = pl110_integrator_pixel_formats,
        .nformats = ARRAY_SIZE(pl110_integrator_pixel_formats),
-       .fb_bpp = 16,
+       .fb_depth = 16,
 };
 
 /*
@@ -330,7 +330,7 @@ static const struct pl111_variant_data pl110_impd1 = {
        .broken_vblank = true,
        .formats = pl110_integrator_pixel_formats,
        .nformats = ARRAY_SIZE(pl110_integrator_pixel_formats),
-       .fb_bpp = 16,
+       .fb_depth = 15,
 };
 
 /*
@@ -343,7 +343,7 @@ static const struct pl111_variant_data pl110_versatile = {
        .external_bgr = true,
        .formats = pl110_versatile_pixel_formats,
        .nformats = ARRAY_SIZE(pl110_versatile_pixel_formats),
-       .fb_bpp = 16,
+       .fb_depth = 16,
 };
 
 /*
@@ -355,7 +355,7 @@ static const struct pl111_variant_data pl111_realview = {
        .name = "PL111 RealView",
        .formats = pl111_realview_pixel_formats,
        .nformats = ARRAY_SIZE(pl111_realview_pixel_formats),
-       .fb_bpp = 16,
+       .fb_depth = 16,
 };
 
 /*
@@ -367,7 +367,7 @@ static const struct pl111_variant_data pl111_vexpress = {
        .name = "PL111 Versatile Express",
        .formats = pl111_realview_pixel_formats,
        .nformats = ARRAY_SIZE(pl111_realview_pixel_formats),
-       .fb_bpp = 16,
+       .fb_depth = 16,
        .broken_clockdivider = true,
 };
 
index 3377fbc71f65478b630085fccdbc786306f0157e..c4dda908666cfc4f9a312517698c7c0c7870af1f 100644 (file)
@@ -99,6 +99,16 @@ static void radeon_hotplug_work_func(struct work_struct *work)
 
 static void radeon_dp_work_func(struct work_struct *work)
 {
+       struct radeon_device *rdev = container_of(work, struct radeon_device,
+                                                 dp_work);
+       struct drm_device *dev = rdev->ddev;
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct drm_connector *connector;
+
+       mutex_lock(&mode_config->mutex);
+       list_for_each_entry(connector, &mode_config->connector_list, head)
+               radeon_connector_hotplug(connector);
+       mutex_unlock(&mode_config->mutex);
 }
 
 /**
index fcd5bd7e5e8e969fbdbdc7c9b93d1fa5b0f8cdd9..aea5a90ff98b98f8836417b46cbe628fc40aa680 100644 (file)
@@ -309,7 +309,7 @@ static void drm_sched_start_timeout(struct drm_gpu_scheduler *sched)
  */
 void drm_sched_fault(struct drm_gpu_scheduler *sched)
 {
-       if (sched->ready)
+       if (sched->timeout_wq)
                mod_delayed_work(sched->timeout_wq, &sched->work_tdr, 0);
 }
 EXPORT_SYMBOL(drm_sched_fault);
@@ -1141,9 +1141,6 @@ void drm_sched_fini(struct drm_gpu_scheduler *sched)
        for (i = DRM_SCHED_PRIORITY_COUNT - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) {
                struct drm_sched_rq *rq = &sched->sched_rq[i];
 
-               if (!rq)
-                       continue;
-
                spin_lock(&rq->lock);
                list_for_each_entry(s_entity, &rq->entities, list)
                        /*
index 7ae5f27df54dd6731b1dcef653a6153323cdbfc2..c6bdb9c4ef3e004cf27fba53b6f5e0eccbe21b55 100644 (file)
@@ -586,6 +586,8 @@ static const struct hid_device_id hammer_devices[] = {
                     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_EEL) },
        { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
                     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) },
+       { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+                    USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_JEWEL) },
        { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
                     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MAGNEMITE) },
        { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
index d79e946acdcbed9fe7afe132ada5366b0a784dbb..5d29abac2300e40c75b0b6eedb803969cac1a84a 100644 (file)
 #define USB_DEVICE_ID_GOOGLE_MOONBALL  0x5044
 #define USB_DEVICE_ID_GOOGLE_DON       0x5050
 #define USB_DEVICE_ID_GOOGLE_EEL       0x5057
+#define USB_DEVICE_ID_GOOGLE_JEWEL     0x5061
 
 #define USB_VENDOR_ID_GOTOP            0x08f2
 #define USB_DEVICE_ID_SUPER_Q2         0x007f
index 0fcfd85fea0feff39a650348d31380daa0f26706..2246044b163930fc936f5ced963e196814ecee90 100644 (file)
@@ -314,6 +314,7 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp,
                        dbg_hid("%s:timeout waiting for response\n", __func__);
                        memset(response, 0, sizeof(struct hidpp_report));
                        ret = -ETIMEDOUT;
+                       goto exit;
                }
 
                if (response->report_id == REPORT_ID_HIDPP_SHORT &&
index 8214896adadaddcb17ebccfc644d2c0f8ad496f3..76e5353aca0c7440253d407ceacd41513e18158a 100644 (file)
@@ -2224,7 +2224,9 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)
                } else if (strstr(product_name, "Wacom") ||
                           strstr(product_name, "wacom") ||
                           strstr(product_name, "WACOM")) {
-                       strscpy(name, product_name, sizeof(name));
+                       if (strscpy(name, product_name, sizeof(name)) < 0) {
+                               hid_warn(wacom->hdev, "String overflow while assembling device name");
+                       }
                } else {
                        snprintf(name, sizeof(name), "Wacom %s", product_name);
                }
@@ -2242,7 +2244,9 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)
                if (name[strlen(name)-1] == ' ')
                        name[strlen(name)-1] = '\0';
        } else {
-               strscpy(name, features->name, sizeof(name));
+               if (strscpy(name, features->name, sizeof(name)) < 0) {
+                       hid_warn(wacom->hdev, "String overflow while assembling device name");
+               }
        }
 
        snprintf(wacom_wac->name, sizeof(wacom_wac->name), "%s%s",
@@ -2410,8 +2414,13 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
                goto fail_quirks;
        }
 
-       if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR)
+       if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) {
                error = hid_hw_open(hdev);
+               if (error) {
+                       hid_err(hdev, "hw open failed\n");
+                       goto fail_quirks;
+               }
+       }
 
        wacom_set_shared_values(wacom_wac);
        devres_close_group(&hdev->dev, wacom);
@@ -2500,8 +2509,10 @@ static void wacom_wireless_work(struct work_struct *work)
                                goto fail;
                }
 
-               strscpy(wacom_wac->name, wacom_wac1->name,
-                       sizeof(wacom_wac->name));
+               if (strscpy(wacom_wac->name, wacom_wac1->name,
+                       sizeof(wacom_wac->name)) < 0) {
+                       hid_warn(wacom->hdev, "String overflow while assembling device name");
+               }
        }
 
        return;
index dc0f7d9a992c10977a5bc3bcaf100cb5c548129b..2ccf838371343da1628bec555896caba7843d2eb 100644 (file)
@@ -831,7 +831,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
        /* Enter report */
        if ((data[1] & 0xfc) == 0xc0) {
                /* serial number of the tool */
-               wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
+               wacom->serial[idx] = ((__u64)(data[3] & 0x0f) << 28) +
                        (data[4] << 20) + (data[5] << 12) +
                        (data[6] << 4) + (data[7] >> 4);
 
index ba2f6a4f8c167f9676775f165e8a01a9d3aa88cb..7b177b9fbb0972ced9e40cbd61d3ba2f88d911e9 100644 (file)
@@ -507,6 +507,7 @@ static const struct pci_device_id k10temp_id_table[] = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M50H_DF_F3) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M60H_DF_F3) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M70H_DF_F3) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M78H_DF_F3) },
        { PCI_VDEVICE(HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) },
        {}
 };
index 711f451b69469404cc4a0835c266e9854860e3be..89e8ed214ea4967620c20ad1c1a1e39f9d068400 100644 (file)
@@ -402,6 +402,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
                trace_id = coresight_trace_id_get_cpu_id(cpu);
                if (!IS_VALID_CS_TRACE_ID(trace_id)) {
                        cpumask_clear_cpu(cpu, mask);
+                       coresight_release_path(path);
                        continue;
                }
 
index 918d461fcf4a68637cea80d6079ebb2e0f8eccb3..eaa296ced167893770a3695a1e9b8fb24098d861 100644 (file)
@@ -942,7 +942,7 @@ tmc_etr_buf_insert_barrier_packet(struct etr_buf *etr_buf, u64 offset)
 
        len = tmc_etr_buf_get_data(etr_buf, offset,
                                   CORESIGHT_BARRIER_PKT_SIZE, &bufp);
-       if (WARN_ON(len < CORESIGHT_BARRIER_PKT_SIZE))
+       if (WARN_ON(len < 0 || len < CORESIGHT_BARRIER_PKT_SIZE))
                return -EINVAL;
        coresight_insert_barrier_packet(bufp);
        return offset + CORESIGHT_BARRIER_PKT_SIZE;
index 99cc7fc294882bcb4426756d9279372625b490e8..524327ea3663159da417b1a9381930e81843e8b2 100644 (file)
@@ -85,7 +85,7 @@ static struct i2c_driver adxl313_i2c_driver = {
                .name   = "adxl313_i2c",
                .of_match_table = adxl313_of_match,
        },
-       .probe_new      = adxl313_i2c_probe,
+       .probe          = adxl313_i2c_probe,
        .id_table       = adxl313_i2c_id,
 };
 
index 098cd83f95b219463f581ce71827abac74fddaa7..e47d12f19602c28b8076a0e75f10d6ea6a51563f 100644 (file)
@@ -56,7 +56,7 @@ static struct i2c_driver adxl345_i2c_driver = {
                .of_match_table = adxl345_of_match,
                .acpi_match_table = adxl345_acpi_match,
        },
-       .probe_new      = adxl345_i2c_probe,
+       .probe          = adxl345_i2c_probe,
        .id_table       = adxl345_i2c_id,
 };
 module_i2c_driver(adxl345_i2c_driver);
index 6cde5ccac06b8597366032731f5424db5b0106ce..d5beea61479d9b0cb2e1f12daac54a3315c17878 100644 (file)
@@ -68,7 +68,7 @@ static struct i2c_driver adxl355_i2c_driver = {
                .name   = "adxl355_i2c",
                .of_match_table = adxl355_of_match,
        },
-       .probe_new      = adxl355_i2c_probe,
+       .probe          = adxl355_i2c_probe,
        .id_table       = adxl355_i2c_id,
 };
 module_i2c_driver(adxl355_i2c_driver);
index 070aad724abd41ea25a665efc3e48fc3b2891e62..b595fe94f3a321b2d8fc986d64d29dbc4f024ccc 100644 (file)
@@ -77,7 +77,7 @@ static struct i2c_driver adxl367_i2c_driver = {
                .name = "adxl367_i2c",
                .of_match_table = adxl367_of_match,
        },
-       .probe_new = adxl367_i2c_probe,
+       .probe = adxl367_i2c_probe,
        .id_table = adxl367_i2c_id,
 };
 
index e5f310ea65fff3565eae9caa90364b2521983515..d0690417fd36f2cd037b5c62acfd17bdb320a20e 100644 (file)
@@ -58,7 +58,7 @@ static struct i2c_driver adxl372_i2c_driver = {
                .name = "adxl372_i2c",
                .of_match_table = adxl372_of_match,
        },
-       .probe_new = adxl372_i2c_probe,
+       .probe = adxl372_i2c_probe,
        .id_table = adxl372_i2c_id,
 };
 
index eb697eeb4301ba8dba1ddd48d09c0364483c7371..e8ab0d249351da35903b6c0fd2ba9a6507046369 100644 (file)
@@ -1134,7 +1134,7 @@ static struct i2c_driver bma180_driver = {
                .pm     = pm_sleep_ptr(&bma180_pm_ops),
                .of_match_table = bma180_of_match,
        },
-       .probe_new      = bma180_probe,
+       .probe          = bma180_probe,
        .remove         = bma180_remove,
        .id_table       = bma180_ids,
 };
index a68b845f5b4f25dfe2a733260b681891bd86200c..e90e2f01550ad375b5b0e781982b3ecbf595dce8 100644 (file)
@@ -868,8 +868,7 @@ static int bma400_init(struct bma400_data *data)
                                             ARRAY_SIZE(regulator_names),
                                             regulator_names);
        if (ret)
-               return dev_err_probe(data->dev, ret, "Failed to get regulators: %d\n",
-                                    ret);
+               return dev_err_probe(data->dev, ret, "Failed to get regulators\n");
 
        /* Try to read chip_id register. It must return 0x90. */
        ret = regmap_read(data->regmap, BMA400_CHIP_ID_REG, &val);
index 688b06dae669b1ab12f18f84467f0629f3acf7dc..adf4e3fd2e1dff5a2055b36b8600519c2a5d7988 100644 (file)
@@ -44,7 +44,7 @@ static struct i2c_driver bma400_i2c_driver = {
                .name = "bma400",
                .of_match_table = bma400_of_i2c_match,
        },
-       .probe_new = bma400_i2c_probe,
+       .probe = bma400_i2c_probe,
        .id_table = bma400_i2c_ids,
 };
 
index 509cab2bd6947249ca95d30ec2c00529fe75c6a2..ee1ba134ad4237269ea39411563580ca2d1163c5 100644 (file)
@@ -269,7 +269,7 @@ static struct i2c_driver bmc150_accel_driver = {
                .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match),
                .pm     = &bmc150_accel_pm_ops,
        },
-       .probe_new      = bmc150_accel_probe,
+       .probe          = bmc150_accel_probe,
        .remove         = bmc150_accel_remove,
        .id_table       = bmc150_accel_id,
 };
index 38a7d811610e786496ee9d704a6d3efa3c1c619a..2f27a5ded94ceb8358b2e1f3c79b7e7280861091 100644 (file)
@@ -184,7 +184,7 @@ static struct i2c_driver da280_driver = {
                .acpi_match_table = ACPI_PTR(da280_acpi_match),
                .pm = pm_sleep_ptr(&da280_pm_ops),
        },
-       .probe_new      = da280_probe,
+       .probe          = da280_probe,
        .id_table       = da280_i2c_id,
 };
 
index 080335fa2ad655ccc339b226a3cd4d94afa8f55e..8f919920ced5d825be71d58cd55a2c2fee00ff43 100644 (file)
@@ -278,7 +278,7 @@ static struct i2c_driver da311_driver = {
                .name = "da311",
                .pm = pm_sleep_ptr(&da311_pm_ops),
        },
-       .probe_new      = da311_probe,
+       .probe          = da311_probe,
        .id_table       = da311_i2c_id,
 };
 
index 7390509aaac0531308c9a917902df13b0498ef3b..2e719d60fff8a89ef461f3119c25dd79544b08bd 100644 (file)
@@ -217,7 +217,7 @@ static const struct of_device_id dmard06_of_match[] = {
 MODULE_DEVICE_TABLE(of, dmard06_of_match);
 
 static struct i2c_driver dmard06_driver = {
-       .probe_new = dmard06_probe,
+       .probe = dmard06_probe,
        .id_table = dmard06_id,
        .driver = {
                .name = DMARD06_DRV_NAME,
index 4b7a537f617d51f69387ae21fbdf4ee90fd9fe1f..fa98623de579b946c570473a19f2b405d3609285 100644 (file)
@@ -135,7 +135,7 @@ static struct i2c_driver dmard09_driver = {
        .driver = {
                .name = DMARD09_DRV_NAME
        },
-       .probe_new = dmard09_probe,
+       .probe = dmard09_probe,
        .id_table = dmard09_id,
 };
 
index 07e68aed8a13c7cb2a360743e6f71bdde7f41baa..7745b6ffd1ad567fe5c3ffa50d25d34eec322b1e 100644 (file)
@@ -241,7 +241,7 @@ static struct i2c_driver dmard10_driver = {
                .name = "dmard10",
                .pm = pm_sleep_ptr(&dmard10_pm_ops),
        },
-       .probe_new      = dmard10_probe,
+       .probe          = dmard10_probe,
        .id_table       = dmard10_i2c_id,
 };
 
index 0d672b1469e8d1798bfe739f81394432a2ad1ef2..be8a15cb945fdf9c007eac135347e2af3c7b7b09 100644 (file)
@@ -724,8 +724,7 @@ static const struct iio_event_spec fxls8962af_event[] = {
                .sign = 's', \
                .realbits = 12, \
                .storagebits = 16, \
-               .shift = 4, \
-               .endianness = IIO_BE, \
+               .endianness = IIO_LE, \
        }, \
        .event_spec = fxls8962af_event, \
        .num_event_specs = ARRAY_SIZE(fxls8962af_event), \
@@ -904,9 +903,10 @@ static int fxls8962af_fifo_transfer(struct fxls8962af_data *data,
        int total_length = samples * sample_length;
        int ret;
 
-       if (i2c_verify_client(dev))
+       if (i2c_verify_client(dev) &&
+           data->chip_info->chip_id == FXLS8962AF_DEVICE_ID)
                /*
-                * Due to errata bug:
+                * Due to errata bug (only applicable on fxls8962af):
                 * E3: FIFO burst read operation error using I2C interface
                 * We have to avoid burst reads on I2C..
                 */
index 22640eaebac739ad53fac7f98151d44227a775f5..160124673308307f11303ac484118be8a07f86b4 100644 (file)
@@ -47,7 +47,7 @@ static struct i2c_driver fxls8962af_driver = {
                   .of_match_table = fxls8962af_of_match,
                   .pm = pm_ptr(&fxls8962af_pm_ops),
                   },
-       .probe_new = fxls8962af_probe,
+       .probe = fxls8962af_probe,
        .id_table = fxls8962af_id,
 };
 module_i2c_driver(fxls8962af_driver);
index e6fd02d931b60f3b3a6aa6c1fee56f9ae055a7cb..b0ac78e85dada1d1daeaa345cc7e5ddc5ebb4d11 100644 (file)
@@ -40,8 +40,9 @@ static struct i2c_driver kx022a_i2c_driver = {
        .driver = {
                .name  = "kx022a-i2c",
                .of_match_table = kx022a_of_match,
+               .probe_type = PROBE_PREFER_ASYNCHRONOUS,
          },
-       .probe_new    = kx022a_i2c_probe,
+       .probe        = kx022a_i2c_probe,
 };
 module_i2c_driver(kx022a_i2c_driver);
 
index 9cd047f7b34678a6e754232e86501688d30b31d9..f45a46899a5f63d4d6a9021190d7a2b6091db3ec 100644 (file)
@@ -46,6 +46,7 @@ static struct spi_driver kx022a_spi_driver = {
        .driver = {
                .name   = "kx022a-spi",
                .of_match_table = kx022a_of_match,
+               .probe_type = PROBE_PREFER_ASYNCHRONOUS,
        },
        .probe = kx022a_spi_probe,
        .id_table = kx022a_id,
index f98393d746668f0ebbf3ba7d5d909adf25b1d680..4ea3c6718ed49dec8d0119b7d6cf5e66e63a05ab 100644 (file)
@@ -516,17 +516,6 @@ static int kx022a_read_raw(struct iio_dev *idev,
        return -EINVAL;
 };
 
-static int kx022a_validate_trigger(struct iio_dev *idev,
-                                  struct iio_trigger *trig)
-{
-       struct kx022a_data *data = iio_priv(idev);
-
-       if (data->trig != trig)
-               return -EINVAL;
-
-       return 0;
-}
-
 static int kx022a_set_watermark(struct iio_dev *idev, unsigned int val)
 {
        struct kx022a_data *data = iio_priv(idev);
@@ -725,7 +714,7 @@ static const struct iio_info kx022a_info = {
        .write_raw = &kx022a_write_raw,
        .read_avail = &kx022a_read_avail,
 
-       .validate_trigger       = kx022a_validate_trigger,
+       .validate_trigger       = iio_validate_own_trigger,
        .hwfifo_set_watermark   = kx022a_set_watermark,
        .hwfifo_flush_to_buffer = kx022a_fifo_flush,
 };
@@ -1048,7 +1037,7 @@ int kx022a_probe_internal(struct device *dev)
                data->ien_reg = KX022A_REG_INC4;
        } else {
                irq = fwnode_irq_get_byname(fwnode, "INT2");
-               if (irq <= 0)
+               if (irq < 0)
                        return dev_err_probe(dev, irq, "No suitable IRQ\n");
 
                data->inc_reg = KX022A_REG_INC5;
index 98da4bda22dfe0761d3d456147d354dd2b1921f8..894709286b0ccb22ff45cc0ac71729f28e06f487 100644 (file)
@@ -1732,7 +1732,7 @@ static struct i2c_driver kxcjk1013_driver = {
                .of_match_table = kxcjk1013_of_match,
                .pm     = &kxcjk1013_pm_ops,
        },
-       .probe_new      = kxcjk1013_probe,
+       .probe          = kxcjk1013_probe,
        .remove         = kxcjk1013_remove,
        .id_table       = kxcjk1013_id,
 };
index 6b3683ddce36d92dd2d09cd03fd22b3e91949bfd..3bc9ee1f9db3a9cce65bcb5b30eb3735b717f2b1 100644 (file)
@@ -54,7 +54,7 @@ static struct i2c_driver kxsd9_i2c_driver = {
                .of_match_table = kxsd9_of_match,
                .pm = pm_ptr(&kxsd9_dev_pm_ops),
        },
-       .probe_new      = kxsd9_i2c_probe,
+       .probe          = kxsd9_i2c_probe,
        .remove         = kxsd9_i2c_remove,
        .id_table       = kxsd9_i2c_id,
 };
index efc21871de42b7852526151675825071311408f6..6b87c2c9945ca9e68d2e543bee739c0ce1a4eaf7 100644 (file)
@@ -190,7 +190,7 @@ static struct i2c_driver mc3230_driver = {
                .name = "mc3230",
                .pm = pm_sleep_ptr(&mc3230_pm_ops),
        },
-       .probe_new      = mc3230_probe,
+       .probe          = mc3230_probe,
        .remove         = mc3230_remove,
        .id_table       = mc3230_i2c_id,
 };
index a3864dbe27613c20686c664db94891d003b94fe1..14f7850a22f043dde2c47484aec55a24e2f7441d 100644 (file)
@@ -46,7 +46,7 @@ static const struct of_device_id mma7455_of_match[] = {
 MODULE_DEVICE_TABLE(of, mma7455_of_match);
 
 static struct i2c_driver mma7455_i2c_driver = {
-       .probe_new = mma7455_i2c_probe,
+       .probe = mma7455_i2c_probe,
        .remove = mma7455_i2c_remove,
        .id_table = mma7455_i2c_ids,
        .driver = {
index b279ca4dcdc05637d2e7d74ef608bfc805c25b95..260cbceaa15189a625ff119580ea11894473713a 100644 (file)
@@ -266,7 +266,7 @@ static struct i2c_driver mma7660_driver = {
                .of_match_table = mma7660_of_match,
                .acpi_match_table = mma7660_acpi_id,
        },
-       .probe_new      = mma7660_probe,
+       .probe          = mma7660_probe,
        .remove         = mma7660_remove,
        .id_table       = mma7660_i2c_id,
 };
index ea14e3aaa30a03c0f7150e56964fdd2e40030bc8..6e7399e722214cff270dc408080a818f9b302afb 100644 (file)
@@ -1846,7 +1846,7 @@ static struct i2c_driver mma8452_driver = {
                .of_match_table = mma8452_dt_ids,
                .pm     = &mma8452_pm_ops,
        },
-       .probe_new = mma8452_probe,
+       .probe = mma8452_probe,
        .remove = mma8452_remove,
        .id_table = mma8452_id,
 };
index aa4f5842859ef863ea5769966b76642a76ef1402..d823f2edc6d425b6b775ea1f05fc65a27cccd387 100644 (file)
@@ -607,7 +607,7 @@ static struct i2c_driver mma9551_driver = {
                   .acpi_match_table = ACPI_PTR(mma9551_acpi_match),
                   .pm = pm_ptr(&mma9551_pm_ops),
                   },
-       .probe_new = mma9551_probe,
+       .probe = mma9551_probe,
        .remove = mma9551_remove,
        .id_table = mma9551_id,
 };
index 0af578ef9d3d0e5e218beef8586c4b58dc417b29..d01aba4aecba5204507562f8b84c6fb88f7afb41 100644 (file)
@@ -1246,7 +1246,7 @@ static struct i2c_driver mma9553_driver = {
                   .acpi_match_table = ACPI_PTR(mma9553_acpi_match),
                   .pm = pm_ptr(&mma9553_pm_ops),
                   },
-       .probe_new = mma9553_probe,
+       .probe = mma9553_probe,
        .remove = mma9553_remove,
        .id_table = mma9553_id,
 };
index 6690fa37da8fee5dbe90cbffc9b432fa89d3e161..6ddcc3c2f840915d7ed2fb447d3c1154874c1d69 100644 (file)
@@ -1294,7 +1294,7 @@ static struct i2c_driver msa311_driver = {
                .of_match_table = msa311_of_match,
                .pm = pm_ptr(&msa311_pm_ops),
        },
-       .probe_new      = msa311_probe,
+       .probe          = msa311_probe,
        .id_table       = msa311_i2c_id,
 };
 module_i2c_driver(msa311_driver);
index b146fc82738f6734eb45d8a18b939574094eeb7c..75d142bc14b4f2180e4ef0b027f842e74fe2f071 100644 (file)
@@ -488,7 +488,7 @@ static struct i2c_driver mxc4005_driver = {
                .name = MXC4005_DRV_NAME,
                .acpi_match_table = ACPI_PTR(mxc4005_acpi_match),
        },
-       .probe_new      = mxc4005_probe,
+       .probe          = mxc4005_probe,
        .id_table       = mxc4005_id,
 };
 
index aa2e660545f841bd8bae0a29c0a9e9dc8a4d8d73..33c2253561e6b2289465f87f517477b9121ca2dd 100644 (file)
@@ -183,7 +183,7 @@ static struct i2c_driver mxc6255_driver = {
                .name = MXC6255_DRV_NAME,
                .acpi_match_table = ACPI_PTR(mxc6255_acpi_match),
        },
-       .probe_new      = mxc6255_probe,
+       .probe          = mxc6255_probe,
        .id_table       = mxc6255_id,
 };
 
index 5f7d81b44b1d28ce2eab297ec16c459bb9feed33..d2104e14e2559d58616fe048a67c13703fac73f1 100644 (file)
@@ -1007,6 +1007,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
                .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = LSM9DS0_IMU_DEV_NAME,
+                       [1] = LSM303D_IMU_DEV_NAME,
                },
                .ch = (struct iio_chan_spec *)st_accel_16bit_channels,
                .odr = {
@@ -1291,12 +1292,12 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev)
 
        adev = ACPI_COMPANION(indio_dev->dev.parent);
        if (!adev)
-               return 0;
+               return -ENXIO;
 
        /* Read _ONT data, which should be a package of 6 integers. */
        status = acpi_evaluate_object(adev->handle, "_ONT", NULL, &buffer);
        if (status == AE_NOT_FOUND) {
-               return 0;
+               return -ENXIO;
        } else if (ACPI_FAILURE(status)) {
                dev_warn(&indio_dev->dev, "failed to execute _ONT: %d\n",
                         status);
index fb9e2d6f421034a210b5de34c559e5f5fa955110..71ee861b29808e9a1768c5d5d48afc8245973bfb 100644 (file)
@@ -206,7 +206,7 @@ static struct i2c_driver st_accel_driver = {
                .of_match_table = st_accel_of_match,
                .acpi_match_table = ACPI_PTR(st_accel_acpi_match),
        },
-       .probe_new = st_accel_i2c_probe,
+       .probe = st_accel_i2c_probe,
        .id_table = st_accel_id_table,
 };
 module_i2c_driver(st_accel_driver);
index 68f680db750513cac3ae4677a84e9bf8650b76c6..ef0ae76722538aefafb8cff199a0e19b51e7be99 100644 (file)
@@ -644,7 +644,7 @@ static struct i2c_driver stk8312_driver = {
                .name = STK8312_DRIVER_NAME,
                .pm = pm_sleep_ptr(&stk8312_pm_ops),
        },
-       .probe_new =        stk8312_probe,
+       .probe =        stk8312_probe,
        .remove =           stk8312_remove,
        .id_table =         stk8312_i2c_id,
 };
index 44f6e0fbdfcc6441394185837dcbf9a64786f7c5..3415ac1b449535fbf796f40463604f696ad1f2f0 100644 (file)
@@ -543,7 +543,7 @@ static struct i2c_driver stk8ba50_driver = {
                .pm = pm_sleep_ptr(&stk8ba50_pm_ops),
                .acpi_match_table = ACPI_PTR(stk8ba50_acpi_id),
        },
-       .probe_new =        stk8ba50_probe,
+       .probe =        stk8ba50_probe,
        .remove =           stk8ba50_remove,
        .id_table =         stk8ba50_i2c_id,
 };
index eb2b09ef5d5b7944fd47f2d54444f9b3867bc915..53098aca06eaff583a966d01163a501a55ee9e4d 100644 (file)
@@ -145,7 +145,7 @@ config AD7606
 
 config AD7606_IFACE_PARALLEL
        tristate "Analog Devices AD7606 ADC driver with parallel interface support"
-       depends on HAS_IOMEM
+       depends on HAS_IOPORT
        select AD7606
        help
          Say yes here to build parallel interface support for Analog Devices:
index 38394341fd6e7401a94662fd5524eb512ea402b4..5a5dd5e87ffc4481c9776d509d32c319ba83135a 100644 (file)
@@ -1817,6 +1817,11 @@ static const struct clk_ops ad4130_int_clk_ops = {
        .unprepare = ad4130_int_clk_unprepare,
 };
 
+static void ad4130_clk_del_provider(void *of_node)
+{
+       of_clk_del_provider(of_node);
+}
+
 static int ad4130_setup_int_clk(struct ad4130_state *st)
 {
        struct device *dev = &st->spi->dev;
@@ -1824,6 +1829,7 @@ static int ad4130_setup_int_clk(struct ad4130_state *st)
        struct clk_init_data init;
        const char *clk_name;
        struct clk *clk;
+       int ret;
 
        if (st->int_pin_sel == AD4130_INT_PIN_CLK ||
            st->mclk_sel != AD4130_MCLK_76_8KHZ)
@@ -1843,7 +1849,11 @@ static int ad4130_setup_int_clk(struct ad4130_state *st)
        if (IS_ERR(clk))
                return PTR_ERR(clk);
 
-       return of_clk_add_provider(of_node, of_clk_src_simple_get, clk);
+       ret = of_clk_add_provider(of_node, of_clk_src_simple_get, clk);
+       if (ret)
+               return ret;
+
+       return devm_add_action_or_reset(dev, ad4130_clk_del_provider, of_node);
 }
 
 static int ad4130_setup(struct iio_dev *indio_dev)
index 7d6709da1005fe2cbc6021318e79bc769af1f417..2f048527b7b786728f2099209a17497d97d9a233 100644 (file)
@@ -103,7 +103,7 @@ static struct i2c_driver ad7091r5_driver = {
                .name = "ad7091r5",
                .of_match_table = ad7091r5_dt_ids,
        },
-       .probe_new = ad7091r5_i2c_probe,
+       .probe = ad7091r5_i2c_probe,
        .id_table = ad7091r5_i2c_ids,
 };
 module_i2c_driver(ad7091r5_driver);
index 55a6ab5910160725415b004ab523f453c97b5337..8685e0b58a83854ce64c6fe6b38b82c519064223 100644 (file)
@@ -367,7 +367,7 @@ static int ad7192_of_clock_select(struct ad7192_state *st)
        clock_sel = AD7192_CLK_INT;
 
        /* use internal clock */
-       if (st->mclk) {
+       if (!st->mclk) {
                if (of_property_read_bool(np, "adi,int-clock-output-enable"))
                        clock_sel = AD7192_CLK_INT_CO;
        } else {
@@ -380,9 +380,9 @@ static int ad7192_of_clock_select(struct ad7192_state *st)
        return clock_sel;
 }
 
-static int ad7192_setup(struct ad7192_state *st, struct device_node *np)
+static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
 {
-       struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi);
+       struct ad7192_state *st = iio_priv(indio_dev);
        bool rej60_en, refin2_en;
        bool buf_en, bipolar, burnout_curr_en;
        unsigned long long scale_uv;
@@ -897,10 +897,6 @@ static const struct iio_info ad7195_info = {
        __AD719x_CHANNEL(_si, _channel1, -1, _address, NULL, IIO_VOLTAGE, \
                BIT(IIO_CHAN_INFO_SCALE), ad7192_calibsys_ext_info)
 
-#define AD719x_SHORTED_CHANNEL(_si, _channel1, _address) \
-       __AD719x_CHANNEL(_si, _channel1, -1, _address, "shorted", IIO_VOLTAGE, \
-               BIT(IIO_CHAN_INFO_SCALE), ad7192_calibsys_ext_info)
-
 #define AD719x_TEMP_CHANNEL(_si, _address) \
        __AD719x_CHANNEL(_si, 0, -1, _address, NULL, IIO_TEMP, 0, NULL)
 
@@ -908,7 +904,7 @@ static const struct iio_chan_spec ad7192_channels[] = {
        AD719x_DIFF_CHANNEL(0, 1, 2, AD7192_CH_AIN1P_AIN2M),
        AD719x_DIFF_CHANNEL(1, 3, 4, AD7192_CH_AIN3P_AIN4M),
        AD719x_TEMP_CHANNEL(2, AD7192_CH_TEMP),
-       AD719x_SHORTED_CHANNEL(3, 2, AD7192_CH_AIN2P_AIN2M),
+       AD719x_DIFF_CHANNEL(3, 2, 2, AD7192_CH_AIN2P_AIN2M),
        AD719x_CHANNEL(4, 1, AD7192_CH_AIN1),
        AD719x_CHANNEL(5, 2, AD7192_CH_AIN2),
        AD719x_CHANNEL(6, 3, AD7192_CH_AIN3),
@@ -922,7 +918,7 @@ static const struct iio_chan_spec ad7193_channels[] = {
        AD719x_DIFF_CHANNEL(2, 5, 6, AD7193_CH_AIN5P_AIN6M),
        AD719x_DIFF_CHANNEL(3, 7, 8, AD7193_CH_AIN7P_AIN8M),
        AD719x_TEMP_CHANNEL(4, AD7193_CH_TEMP),
-       AD719x_SHORTED_CHANNEL(5, 2, AD7193_CH_AIN2P_AIN2M),
+       AD719x_DIFF_CHANNEL(5, 2, 2, AD7193_CH_AIN2P_AIN2M),
        AD719x_CHANNEL(6, 1, AD7193_CH_AIN1),
        AD719x_CHANNEL(7, 2, AD7193_CH_AIN2),
        AD719x_CHANNEL(8, 3, AD7193_CH_AIN3),
@@ -1073,7 +1069,7 @@ static int ad7192_probe(struct spi_device *spi)
                }
        }
 
-       ret = ad7192_setup(st, spi->dev.of_node);
+       ret = ad7192_setup(indio_dev, spi->dev.of_node);
        if (ret)
                return ret;
 
index f9ee189925dec0a90c9ee576cc72172e3eb0974c..14d02b085d3bc81d2f846be30b58412d02bbaa06 100644 (file)
@@ -553,7 +553,7 @@ static struct i2c_driver ad7291_driver = {
                .name = KBUILD_MODNAME,
                .of_match_table = ad7291_of_match,
        },
-       .probe_new = ad7291_probe,
+       .probe = ad7291_probe,
        .id_table = ad7291_id,
 };
 module_i2c_driver(ad7291_driver);
index 8f0a3a35e727e84934855c783e4a1d22e6f0c98f..b757cc45c4decf8420a85a4615b6f2e2465ceef1 100644 (file)
@@ -968,7 +968,7 @@ static struct i2c_driver ad799x_driver = {
                .name = "ad799x",
                .pm = pm_sleep_ptr(&ad799x_pm_ops),
        },
-       .probe_new = ad799x_probe,
+       .probe = ad799x_probe,
        .remove = ad799x_remove,
        .id_table = ad799x_id,
 };
index d8570f620785af8d8b6dfb1a11ee3b63ef579526..7e21928707437baf9a2522f265d72194745205e6 100644 (file)
@@ -584,6 +584,10 @@ static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_de
        init_completion(&sigma_delta->completion);
 
        sigma_delta->irq_dis = true;
+
+       /* the IRQ core clears IRQ_DISABLE_UNLAZY flag when freeing an IRQ */
+       irq_set_status_flags(sigma_delta->spi->irq, IRQ_DISABLE_UNLAZY);
+
        ret = devm_request_irq(dev, sigma_delta->spi->irq,
                               ad_sd_data_rdy_trig_poll,
                               sigma_delta->info->irq_flags | IRQF_NO_AUTOEN,
index a775d2e4056718c0f4b83239617e71d26a14cb1d..dce9ec91e4a778db91f866b6adac6d606496b786 100644 (file)
@@ -236,8 +236,7 @@ static int imx93_adc_read_raw(struct iio_dev *indio_dev,
 {
        struct imx93_adc *adc = iio_priv(indio_dev);
        struct device *dev = adc->dev;
-       long ret;
-       u32 vref_uv;
+       int ret;
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
@@ -253,10 +252,10 @@ static int imx93_adc_read_raw(struct iio_dev *indio_dev,
                return IIO_VAL_INT;
 
        case IIO_CHAN_INFO_SCALE:
-               ret = vref_uv = regulator_get_voltage(adc->vref);
+               ret = regulator_get_voltage(adc->vref);
                if (ret < 0)
                        return ret;
-               *val = vref_uv / 1000;
+               *val = ret / 1000;
                *val2 = 12;
                return IIO_VAL_FRACTIONAL_LOG2;
 
index 38d9d7b2313ea1932b9897f75e23192f937eed08..213526c1592f1c1f3f168b2a68fc4f9b0e86cd2f 100644 (file)
@@ -1090,7 +1090,7 @@ static struct i2c_driver ina2xx_driver = {
                   .name = KBUILD_MODNAME,
                   .of_match_table = ina2xx_of_match,
        },
-       .probe_new = ina2xx_probe,
+       .probe = ina2xx_probe,
        .remove = ina2xx_remove,
        .id_table = ina2xx_id,
 };
index eeb2945829eb27207d436198fa817df761480893..97c417c3a4eb066cc8181df7b6ff916f10a7c541 100644 (file)
@@ -146,7 +146,7 @@ static struct i2c_driver ltc2471_i2c_driver = {
        .driver = {
                .name = "ltc2471",
        },
-       .probe_new = ltc2471_i2c_probe,
+       .probe = ltc2471_i2c_probe,
        .id_table = ltc2471_i2c_id,
 };
 
index 6a23427344ecd176515ccbd65125138271ecc073..859e4314cfa2d4714ac13175e0d468a60d45ddad 100644 (file)
@@ -133,7 +133,7 @@ static struct i2c_driver ltc2485_driver = {
        .driver = {
                .name = "ltc2485",
        },
-       .probe_new = ltc2485_probe,
+       .probe = ltc2485_probe,
        .id_table = ltc2485_id,
 };
 module_i2c_driver(ltc2485_driver);
index ec198c6f13d6bc9a1aaafedb590ff64feca4aa75..5bdd4072961158370798f2febc957215489abd78 100644 (file)
@@ -163,7 +163,7 @@ static struct i2c_driver ltc2497_driver = {
                .name = "ltc2497",
                .of_match_table = ltc2497_of_match,
        },
-       .probe_new = ltc2497_probe,
+       .probe = ltc2497_probe,
        .remove = ltc2497_remove,
        .id_table = ltc2497_id,
 };
index 73b783b430d72def9217f61b1cad9d40128b917f..b31581616ce34ea9af3a44a6284d052cb8bb8a88 100644 (file)
@@ -1718,7 +1718,7 @@ static struct i2c_driver max1363_driver = {
                .name = "max1363",
                .of_match_table = max1363_of_match,
        },
-       .probe_new = max1363_probe,
+       .probe = max1363_probe,
        .id_table = max1363_id,
 };
 module_i2c_driver(max1363_driver);
index cb7f4785423a2f2da8d6778b1c36fb7a7496bee1..76e517b7b1e4f3375ad570838e825f91839103d2 100644 (file)
@@ -556,7 +556,7 @@ static struct i2c_driver max9611_driver = {
                   .name = DRIVER_NAME,
                   .of_match_table = max9611_of_table,
        },
-       .probe_new = max9611_probe,
+       .probe = max9611_probe,
 };
 module_i2c_driver(max9611_driver);
 
index ada844c3f7eccd2c243e86c223f1fc0f65239e08..0778a8fb68665c3e47d8a41fccc057e84c35599a 100644 (file)
@@ -417,7 +417,7 @@ static struct i2c_driver mcp3422_driver = {
                .name = "mcp3422",
                .of_match_table = mcp3422_of_match,
        },
-       .probe_new = mcp3422_probe,
+       .probe = mcp3422_probe,
        .id_table = mcp3422_id,
 };
 module_i2c_driver(mcp3422_driver);
index 18937a262af6f8b2ae04180e479033bc84ede006..af6bfcc190752e9b674a5294004dcd6a35b51dd0 100644 (file)
@@ -72,7 +72,7 @@
        #define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK      GENMASK(20, 18)
        #define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK  GENMASK(17, 16)
        #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT            10
-       #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH            5
+       #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH            6
        #define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK           GENMASK(9, 8)
        #define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK               GENMASK(7, 0)
 
index bc62e5a9d50d11d42e6791065f2a3266d4dc2b06..0bc112135bca1e5922ae19a7bd591f555e863240 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <dt-bindings/iio/adc/mediatek,mt6370_adc.h>
 
+#define MT6370_REG_DEV_INFO            0x100
 #define MT6370_REG_CHG_CTRL3           0x113
 #define MT6370_REG_CHG_CTRL7           0x117
 #define MT6370_REG_CHG_ADC             0x121
@@ -27,6 +28,7 @@
 #define MT6370_ADC_START_MASK          BIT(0)
 #define MT6370_ADC_IN_SEL_MASK         GENMASK(7, 4)
 #define MT6370_AICR_ICHG_MASK          GENMASK(7, 2)
+#define MT6370_VENID_MASK              GENMASK(7, 4)
 
 #define MT6370_AICR_100_mA             0x0
 #define MT6370_AICR_150_mA             0x1
 #define ADC_CONV_TIME_MS               35
 #define ADC_CONV_POLLING_TIME_US       1000
 
+#define MT6370_VID_RT5081              0x8
+#define MT6370_VID_RT5081A             0xA
+#define MT6370_VID_MT6370              0xE
+
 struct mt6370_adc_data {
        struct device *dev;
        struct regmap *regmap;
@@ -55,6 +61,7 @@ struct mt6370_adc_data {
         * from being read at the same time.
         */
        struct mutex adc_lock;
+       unsigned int vid;
 };
 
 static int mt6370_adc_read_channel(struct mt6370_adc_data *priv, int chan,
@@ -98,6 +105,30 @@ adc_unlock:
        return ret;
 }
 
+static int mt6370_adc_get_ibus_scale(struct mt6370_adc_data *priv)
+{
+       switch (priv->vid) {
+       case MT6370_VID_RT5081:
+       case MT6370_VID_RT5081A:
+       case MT6370_VID_MT6370:
+               return 3350;
+       default:
+               return 3875;
+       }
+}
+
+static int mt6370_adc_get_ibat_scale(struct mt6370_adc_data *priv)
+{
+       switch (priv->vid) {
+       case MT6370_VID_RT5081:
+       case MT6370_VID_RT5081A:
+       case MT6370_VID_MT6370:
+               return 2680;
+       default:
+               return 3870;
+       }
+}
+
 static int mt6370_adc_read_scale(struct mt6370_adc_data *priv,
                                 int chan, int *val1, int *val2)
 {
@@ -123,7 +154,7 @@ static int mt6370_adc_read_scale(struct mt6370_adc_data *priv,
                case MT6370_AICR_250_mA:
                case MT6370_AICR_300_mA:
                case MT6370_AICR_350_mA:
-                       *val1 = 3350;
+                       *val1 = mt6370_adc_get_ibus_scale(priv);
                        break;
                default:
                        *val1 = 5000;
@@ -150,7 +181,7 @@ static int mt6370_adc_read_scale(struct mt6370_adc_data *priv,
                case MT6370_ICHG_600_mA:
                case MT6370_ICHG_700_mA:
                case MT6370_ICHG_800_mA:
-                       *val1 = 2680;
+                       *val1 = mt6370_adc_get_ibat_scale(priv);
                        break;
                default:
                        *val1 = 5000;
@@ -251,6 +282,20 @@ static const struct iio_chan_spec mt6370_adc_channels[] = {
        MT6370_ADC_CHAN(TEMP_JC, IIO_TEMP, 12, BIT(IIO_CHAN_INFO_OFFSET)),
 };
 
+static int mt6370_get_vendor_info(struct mt6370_adc_data *priv)
+{
+       unsigned int dev_info;
+       int ret;
+
+       ret = regmap_read(priv->regmap, MT6370_REG_DEV_INFO, &dev_info);
+       if (ret)
+               return ret;
+
+       priv->vid = FIELD_GET(MT6370_VENID_MASK, dev_info);
+
+       return 0;
+}
+
 static int mt6370_adc_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -272,6 +317,10 @@ static int mt6370_adc_probe(struct platform_device *pdev)
        priv->regmap = regmap;
        mutex_init(&priv->adc_lock);
 
+       ret = mt6370_get_vendor_info(priv);
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to get vid\n");
+
        ret = regmap_write(priv->regmap, MT6370_REG_CHG_ADC, 0);
        if (ret)
                return dev_err_probe(dev, ret, "Failed to reset ADC\n");
index bca79a93cbe43186fb8de002ab2f8a63bba54499..a50f39143d3ea3d7f23cf353081049b7069ca64b 100644 (file)
@@ -757,13 +757,13 @@ static int mxs_lradc_adc_probe(struct platform_device *pdev)
 
        ret = mxs_lradc_adc_trigger_init(iio);
        if (ret)
-               goto err_trig;
+               return ret;
 
        ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time,
                                         &mxs_lradc_adc_trigger_handler,
                                         &mxs_lradc_adc_buffer_ops);
        if (ret)
-               return ret;
+               goto err_trig;
 
        adc->vref_mv = mxs_lradc_adc_vref_mv[lradc->soc];
 
@@ -801,9 +801,9 @@ static int mxs_lradc_adc_probe(struct platform_device *pdev)
 
 err_dev:
        mxs_lradc_adc_hw_stop(adc);
-       mxs_lradc_adc_trigger_remove(iio);
-err_trig:
        iio_triggered_buffer_cleanup(iio);
+err_trig:
+       mxs_lradc_adc_trigger_remove(iio);
        return ret;
 }
 
@@ -814,8 +814,8 @@ static int mxs_lradc_adc_remove(struct platform_device *pdev)
 
        iio_device_unregister(iio);
        mxs_lradc_adc_hw_stop(adc);
-       mxs_lradc_adc_trigger_remove(iio);
        iio_triggered_buffer_cleanup(iio);
+       mxs_lradc_adc_trigger_remove(iio);
 
        return 0;
 }
index c1261ecd400c4167120c39ffa24260af28729e00..d9e1696df7ae453630e276aec39265563ccceb84 100644 (file)
@@ -544,7 +544,7 @@ static const struct of_device_id nau7802_dt_ids[] = {
 MODULE_DEVICE_TABLE(of, nau7802_dt_ids);
 
 static struct i2c_driver nau7802_driver = {
-       .probe_new = nau7802_probe,
+       .probe = nau7802_probe,
        .id_table = nau7802_i2c_id,
        .driver = {
                   .name = "nau7802",
index c1c439215aeb5fc5a20313572e2b7e6b2ec41716..27b2632c103766a0bf4f2aa38541cadf8377f11c 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/i2c.h>
 #include <linux/pm.h>
 #include <linux/mfd/palmas.h>
 #include <linux/completion.h>
@@ -547,7 +546,7 @@ static int palmas_gpadc_read_raw(struct iio_dev *indio_dev,
        int adc_chan = chan->channel;
        int ret = 0;
 
-       if (adc_chan > PALMAS_ADC_CH_MAX)
+       if (adc_chan >= PALMAS_ADC_CH_MAX)
                return -EINVAL;
 
        mutex_lock(&adc->lock);
@@ -595,7 +594,7 @@ static int palmas_gpadc_read_event_config(struct iio_dev *indio_dev,
        int adc_chan = chan->channel;
        int ret = 0;
 
-       if (adc_chan > PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH)
+       if (adc_chan >= PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH)
                return -EINVAL;
 
        mutex_lock(&adc->lock);
@@ -684,7 +683,7 @@ static int palmas_gpadc_write_event_config(struct iio_dev *indio_dev,
        int adc_chan = chan->channel;
        int ret;
 
-       if (adc_chan > PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH)
+       if (adc_chan >= PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH)
                return -EINVAL;
 
        mutex_lock(&adc->lock);
@@ -710,7 +709,7 @@ static int palmas_gpadc_read_event_value(struct iio_dev *indio_dev,
        int adc_chan = chan->channel;
        int ret;
 
-       if (adc_chan > PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH)
+       if (adc_chan >= PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH)
                return -EINVAL;
 
        mutex_lock(&adc->lock);
@@ -744,7 +743,7 @@ static int palmas_gpadc_write_event_value(struct iio_dev *indio_dev,
        int old;
        int ret;
 
-       if (adc_chan > PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH)
+       if (adc_chan >= PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH)
                return -EINVAL;
 
        mutex_lock(&adc->lock);
index c2d5e06f137a7e64f66a112b9cc47c5de2e6d309..0a4fd3a461138be882426e869dee17d4e31fb21f 100644 (file)
@@ -114,7 +114,7 @@ enum adc5_cal_val {
  *     that is an average of multiple measurements.
  * @scale_fn_type: Represents the scaling function to convert voltage
  *     physical units desired by the client for the channel.
- * @datasheet_name: Channel name used in device tree.
+ * @channel_name: Channel name used in device tree.
  */
 struct adc5_channel_prop {
        unsigned int            channel;
@@ -126,7 +126,7 @@ struct adc5_channel_prop {
        unsigned int            hw_settle_time;
        unsigned int            avg_samples;
        enum vadc_scale_fn_type scale_fn_type;
-       const char              *datasheet_name;
+       const char              *channel_name;
 };
 
 /**
@@ -657,8 +657,7 @@ static int adc5_get_fw_channel_data(struct adc5_chip *adc,
                chan = chan & ADC_CHANNEL_MASK;
        }
 
-       if (chan > ADC5_PARALLEL_ISENSE_VBAT_IDATA ||
-           !data->adc_chans[chan].datasheet_name) {
+       if (chan > ADC5_PARALLEL_ISENSE_VBAT_IDATA) {
                dev_err(dev, "%s invalid channel number %d\n", name, chan);
                return -EINVAL;
        }
@@ -669,9 +668,9 @@ static int adc5_get_fw_channel_data(struct adc5_chip *adc,
 
        ret = fwnode_property_read_string(fwnode, "label", &channel_name);
        if (ret)
-               channel_name = name;
+               channel_name = data->adc_chans[chan].datasheet_name;
 
-       prop->datasheet_name = channel_name;
+       prop->channel_name = channel_name;
 
        ret = fwnode_property_read_u32(fwnode, "qcom,decimation", &value);
        if (!ret) {
@@ -861,8 +860,8 @@ static int adc5_get_fw_data(struct adc5_chip *adc)
                adc_chan = &adc->data->adc_chans[prop.channel];
 
                iio_chan->channel = prop.channel;
-               iio_chan->datasheet_name = prop.datasheet_name;
-               iio_chan->extend_name = prop.datasheet_name;
+               iio_chan->datasheet_name = adc_chan->datasheet_name;
+               iio_chan->extend_name = prop.channel_name;
                iio_chan->info_mask_separate = adc_chan->info_mask;
                iio_chan->type = adc_chan->type;
                iio_chan->address = index;
index bcff0f62b70e05b388dd4b097f55366bbe7092dd..f5c6f1f27b2c7de16326c0465f6c3c7899abb746 100644 (file)
@@ -84,6 +84,7 @@
  *     that is an average of multiple measurements.
  * @scale_fn_type: Represents the scaling function to convert voltage
  *     physical units desired by the client for the channel.
+ * @channel_name: Channel name used in device tree.
  */
 struct vadc_channel_prop {
        unsigned int channel;
@@ -93,6 +94,7 @@ struct vadc_channel_prop {
        unsigned int hw_settle_time;
        unsigned int avg_samples;
        enum vadc_scale_fn_type scale_fn_type;
+       const char *channel_name;
 };
 
 /**
@@ -495,8 +497,18 @@ static int vadc_fwnode_xlate(struct iio_dev *indio_dev,
        return -EINVAL;
 }
 
+static int vadc_read_label(struct iio_dev *indio_dev,
+                          struct iio_chan_spec const *chan, char *label)
+{
+       struct vadc_priv *vadc = iio_priv(indio_dev);
+       const char *name = vadc->chan_props[chan->address].channel_name;
+
+       return sysfs_emit(label, "%s\n", name);
+}
+
 static const struct iio_info vadc_info = {
        .read_raw = vadc_read_raw,
+       .read_label = vadc_read_label,
        .fwnode_xlate = vadc_fwnode_xlate,
 };
 
@@ -652,7 +664,7 @@ static int vadc_get_fw_channel_data(struct device *dev,
                                    struct vadc_channel_prop *prop,
                                    struct fwnode_handle *fwnode)
 {
-       const char *name = fwnode_get_name(fwnode);
+       const char *name = fwnode_get_name(fwnode), *label;
        u32 chan, value, varr[2];
        int ret;
 
@@ -667,6 +679,11 @@ static int vadc_get_fw_channel_data(struct device *dev,
                return -EINVAL;
        }
 
+       ret = fwnode_property_read_string(fwnode, "label", &label);
+       if (ret)
+               label = vadc_chans[chan].datasheet_name;
+       prop->channel_name = label;
+
        /* the channel has DT description */
        prop->channel = chan;
 
index 79448c5ffc2ae2d4306026dd879e978a4f709214..4b011f7eddec3a61abb92bce55ffc50457db1d04 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 2014 ROCKCHIP, Inc.
  */
 
+#include <linux/bitfield.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
 #define SARADC_TIMEOUT                 msecs_to_jiffies(100)
 #define SARADC_MAX_CHANNELS            8
 
+/* v2 registers */
+#define SARADC2_CONV_CON               0x000
+#define SARADC_T_PD_SOC                        0x004
+#define SARADC_T_DAS_SOC               0x00c
+#define SARADC2_END_INT_EN             0x104
+#define SARADC2_ST_CON                 0x108
+#define SARADC2_STATUS                 0x10c
+#define SARADC2_END_INT_ST             0x110
+#define SARADC2_DATA_BASE              0x120
+
+#define SARADC2_EN_END_INT             BIT(0)
+#define SARADC2_START                  BIT(4)
+#define SARADC2_SINGLE_MODE            BIT(5)
+
+#define SARADC2_CONV_CHANNELS GENMASK(15, 0)
+
+struct rockchip_saradc;
+
 struct rockchip_saradc_data {
        const struct iio_chan_spec      *channels;
        int                             num_channels;
        unsigned long                   clk_rate;
+       void (*start)(struct rockchip_saradc *info, int chn);
+       int (*read)(struct rockchip_saradc *info);
+       void (*power_down)(struct rockchip_saradc *info);
 };
 
 struct rockchip_saradc {
@@ -60,27 +82,81 @@ struct rockchip_saradc {
        struct notifier_block nb;
 };
 
-static void rockchip_saradc_power_down(struct rockchip_saradc *info)
+static void rockchip_saradc_reset_controller(struct reset_control *reset);
+
+static void rockchip_saradc_start_v1(struct rockchip_saradc *info, int chn)
+{
+       /* 8 clock periods as delay between power up and start cmd */
+       writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC);
+       /* Select the channel to be used and trigger conversion */
+       writel(SARADC_CTRL_POWER_CTRL | (chn & SARADC_CTRL_CHN_MASK) |
+              SARADC_CTRL_IRQ_ENABLE, info->regs + SARADC_CTRL);
+}
+
+static void rockchip_saradc_start_v2(struct rockchip_saradc *info, int chn)
+{
+       int val;
+
+       if (info->reset)
+               rockchip_saradc_reset_controller(info->reset);
+
+       writel_relaxed(0xc, info->regs + SARADC_T_DAS_SOC);
+       writel_relaxed(0x20, info->regs + SARADC_T_PD_SOC);
+       val = FIELD_PREP(SARADC2_EN_END_INT, 1);
+       val |= val << 16;
+       writel_relaxed(val, info->regs + SARADC2_END_INT_EN);
+       val = FIELD_PREP(SARADC2_START, 1) |
+             FIELD_PREP(SARADC2_SINGLE_MODE, 1) |
+             FIELD_PREP(SARADC2_CONV_CHANNELS, chn);
+       val |= val << 16;
+       writel(val, info->regs + SARADC2_CONV_CON);
+}
+
+static void rockchip_saradc_start(struct rockchip_saradc *info, int chn)
+{
+       info->data->start(info, chn);
+}
+
+static int rockchip_saradc_read_v1(struct rockchip_saradc *info)
+{
+       return readl_relaxed(info->regs + SARADC_DATA);
+}
+
+static int rockchip_saradc_read_v2(struct rockchip_saradc *info)
+{
+       int offset;
+
+       /* Clear irq */
+       writel_relaxed(0x1, info->regs + SARADC2_END_INT_ST);
+
+       offset = SARADC2_DATA_BASE + info->last_chan->channel * 0x4;
+
+       return readl_relaxed(info->regs + offset);
+}
+
+static int rockchip_saradc_read(struct rockchip_saradc *info)
+{
+       return info->data->read(info);
+}
+
+static void rockchip_saradc_power_down_v1(struct rockchip_saradc *info)
 {
-       /* Clear irq & power down adc */
        writel_relaxed(0, info->regs + SARADC_CTRL);
 }
 
+static void rockchip_saradc_power_down(struct rockchip_saradc *info)
+{
+       if (info->data->power_down)
+               info->data->power_down(info);
+}
+
 static int rockchip_saradc_conversion(struct rockchip_saradc *info,
-                                  struct iio_chan_spec const *chan)
+                                     struct iio_chan_spec const *chan)
 {
        reinit_completion(&info->completion);
 
-       /* 8 clock periods as delay between power up and start cmd */
-       writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC);
-
        info->last_chan = chan;
-
-       /* Select the channel to be used and trigger conversion */
-       writel(SARADC_CTRL_POWER_CTRL
-                       | (chan->channel & SARADC_CTRL_CHN_MASK)
-                       | SARADC_CTRL_IRQ_ENABLE,
-                  info->regs + SARADC_CTRL);
+       rockchip_saradc_start(info, chan->channel);
 
        if (!wait_for_completion_timeout(&info->completion, SARADC_TIMEOUT))
                return -ETIMEDOUT;
@@ -123,7 +199,7 @@ static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id)
        struct rockchip_saradc *info = dev_id;
 
        /* Read value */
-       info->last_val = readl_relaxed(info->regs + SARADC_DATA);
+       info->last_val = rockchip_saradc_read(info);
        info->last_val &= GENMASK(info->last_chan->scan_type.realbits - 1, 0);
 
        rockchip_saradc_power_down(info);
@@ -163,6 +239,9 @@ static const struct rockchip_saradc_data saradc_data = {
        .channels = rockchip_saradc_iio_channels,
        .num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels),
        .clk_rate = 1000000,
+       .start = rockchip_saradc_start_v1,
+       .read = rockchip_saradc_read_v1,
+       .power_down = rockchip_saradc_power_down_v1,
 };
 
 static const struct iio_chan_spec rockchip_rk3066_tsadc_iio_channels[] = {
@@ -174,6 +253,9 @@ static const struct rockchip_saradc_data rk3066_tsadc_data = {
        .channels = rockchip_rk3066_tsadc_iio_channels,
        .num_channels = ARRAY_SIZE(rockchip_rk3066_tsadc_iio_channels),
        .clk_rate = 50000,
+       .start = rockchip_saradc_start_v1,
+       .read = rockchip_saradc_read_v1,
+       .power_down = rockchip_saradc_power_down_v1,
 };
 
 static const struct iio_chan_spec rockchip_rk3399_saradc_iio_channels[] = {
@@ -189,6 +271,9 @@ static const struct rockchip_saradc_data rk3399_saradc_data = {
        .channels = rockchip_rk3399_saradc_iio_channels,
        .num_channels = ARRAY_SIZE(rockchip_rk3399_saradc_iio_channels),
        .clk_rate = 1000000,
+       .start = rockchip_saradc_start_v1,
+       .read = rockchip_saradc_read_v1,
+       .power_down = rockchip_saradc_power_down_v1,
 };
 
 static const struct iio_chan_spec rockchip_rk3568_saradc_iio_channels[] = {
@@ -206,6 +291,28 @@ static const struct rockchip_saradc_data rk3568_saradc_data = {
        .channels = rockchip_rk3568_saradc_iio_channels,
        .num_channels = ARRAY_SIZE(rockchip_rk3568_saradc_iio_channels),
        .clk_rate = 1000000,
+       .start = rockchip_saradc_start_v1,
+       .read = rockchip_saradc_read_v1,
+       .power_down = rockchip_saradc_power_down_v1,
+};
+
+static const struct iio_chan_spec rockchip_rk3588_saradc_iio_channels[] = {
+       SARADC_CHANNEL(0, "adc0", 12),
+       SARADC_CHANNEL(1, "adc1", 12),
+       SARADC_CHANNEL(2, "adc2", 12),
+       SARADC_CHANNEL(3, "adc3", 12),
+       SARADC_CHANNEL(4, "adc4", 12),
+       SARADC_CHANNEL(5, "adc5", 12),
+       SARADC_CHANNEL(6, "adc6", 12),
+       SARADC_CHANNEL(7, "adc7", 12),
+};
+
+static const struct rockchip_saradc_data rk3588_saradc_data = {
+       .channels = rockchip_rk3588_saradc_iio_channels,
+       .num_channels = ARRAY_SIZE(rockchip_rk3588_saradc_iio_channels),
+       .clk_rate = 1000000,
+       .start = rockchip_saradc_start_v2,
+       .read = rockchip_saradc_read_v2,
 };
 
 static const struct of_device_id rockchip_saradc_match[] = {
@@ -221,6 +328,9 @@ static const struct of_device_id rockchip_saradc_match[] = {
        }, {
                .compatible = "rockchip,rk3568-saradc",
                .data = &rk3568_saradc_data,
+       }, {
+               .compatible = "rockchip,rk3588-saradc",
+               .data = &rk3588_saradc_data,
        },
        {},
 };
@@ -236,20 +346,6 @@ static void rockchip_saradc_reset_controller(struct reset_control *reset)
        reset_control_deassert(reset);
 }
 
-static void rockchip_saradc_clk_disable(void *data)
-{
-       struct rockchip_saradc *info = data;
-
-       clk_disable_unprepare(info->clk);
-}
-
-static void rockchip_saradc_pclk_disable(void *data)
-{
-       struct rockchip_saradc *info = data;
-
-       clk_disable_unprepare(info->pclk);
-}
-
 static void rockchip_saradc_regulator_disable(void *data)
 {
        struct rockchip_saradc *info = data;
@@ -298,8 +394,7 @@ out:
 }
 
 static int rockchip_saradc_volt_notify(struct notifier_block *nb,
-                                                  unsigned long event,
-                                                  void *data)
+                                      unsigned long event, void *data)
 {
        struct rockchip_saradc *info =
                        container_of(nb, struct rockchip_saradc, nb);
@@ -319,10 +414,10 @@ static void rockchip_saradc_regulator_unreg_notifier(void *data)
 
 static int rockchip_saradc_probe(struct platform_device *pdev)
 {
+       const struct rockchip_saradc_data *match_data;
        struct rockchip_saradc *info = NULL;
        struct device_node *np = pdev->dev.of_node;
        struct iio_dev *indio_dev = NULL;
-       const struct of_device_id *match;
        int ret;
        int irq;
 
@@ -330,25 +425,23 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
                return -ENODEV;
 
        indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
-       if (!indio_dev) {
-               dev_err(&pdev->dev, "failed allocating iio device\n");
-               return -ENOMEM;
-       }
+       if (!indio_dev)
+               return dev_err_probe(&pdev->dev, -ENOMEM,
+                                    "failed allocating iio device\n");
+
        info = iio_priv(indio_dev);
 
-       match = of_match_device(rockchip_saradc_match, &pdev->dev);
-       if (!match) {
-               dev_err(&pdev->dev, "failed to match device\n");
-               return -ENODEV;
-       }
+       match_data = of_device_get_match_data(&pdev->dev);
+       if (!match_data)
+               return dev_err_probe(&pdev->dev, -ENODEV,
+                                    "failed to match device\n");
 
-       info->data = match->data;
+       info->data = match_data;
 
        /* Sanity check for possible later IP variants with more channels */
-       if (info->data->num_channels > SARADC_MAX_CHANNELS) {
-               dev_err(&pdev->dev, "max channels exceeded");
-               return -EINVAL;
-       }
+       if (info->data->num_channels > SARADC_MAX_CHANNELS)
+               return dev_err_probe(&pdev->dev, -EINVAL,
+                                    "max channels exceeded");
 
        info->regs = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(info->regs))
@@ -383,16 +476,6 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
                return ret;
        }
 
-       info->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
-       if (IS_ERR(info->pclk))
-               return dev_err_probe(&pdev->dev, PTR_ERR(info->pclk),
-                                    "failed to get pclk\n");
-
-       info->clk = devm_clk_get(&pdev->dev, "saradc");
-       if (IS_ERR(info->clk))
-               return dev_err_probe(&pdev->dev, PTR_ERR(info->clk),
-                                    "failed to get adc clock\n");
-
        info->vref = devm_regulator_get(&pdev->dev, "vref");
        if (IS_ERR(info->vref))
                return dev_err_probe(&pdev->dev, PTR_ERR(info->vref),
@@ -406,23 +489,20 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
         * This may become user-configurable in the future.
         */
        ret = clk_set_rate(info->clk, info->data->clk_rate);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret);
-               return ret;
-       }
+       if (ret < 0)
+               return dev_err_probe(&pdev->dev, ret,
+                                    "failed to set adc clk rate\n");
 
        ret = regulator_enable(info->vref);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to enable vref regulator\n");
-               return ret;
-       }
+       if (ret < 0)
+               return dev_err_probe(&pdev->dev, ret,
+                                    "failed to enable vref regulator\n");
+
        ret = devm_add_action_or_reset(&pdev->dev,
                                       rockchip_saradc_regulator_disable, info);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to register devm action, %d\n",
-                       ret);
-               return ret;
-       }
+       if (ret)
+               return dev_err_probe(&pdev->dev, ret,
+                                    "failed to register devm action\n");
 
        ret = regulator_get_voltage(info->vref);
        if (ret < 0)
@@ -430,31 +510,15 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
 
        info->uv_vref = ret;
 
-       ret = clk_prepare_enable(info->pclk);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to enable pclk\n");
-               return ret;
-       }
-       ret = devm_add_action_or_reset(&pdev->dev,
-                                      rockchip_saradc_pclk_disable, info);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to register devm action, %d\n",
-                       ret);
-               return ret;
-       }
+       info->pclk = devm_clk_get_enabled(&pdev->dev, "apb_pclk");
+       if (IS_ERR(info->pclk))
+               return dev_err_probe(&pdev->dev, PTR_ERR(info->pclk),
+                                    "failed to get pclk\n");
 
-       ret = clk_prepare_enable(info->clk);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to enable converter clock\n");
-               return ret;
-       }
-       ret = devm_add_action_or_reset(&pdev->dev,
-                                      rockchip_saradc_clk_disable, info);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to register devm action, %d\n",
-                       ret);
-               return ret;
-       }
+       info->clk = devm_clk_get_enabled(&pdev->dev, "saradc");
+       if (IS_ERR(info->clk))
+               return dev_err_probe(&pdev->dev, PTR_ERR(info->clk),
+                                    "failed to get adc clock\n");
 
        platform_set_drvdata(pdev, indio_dev);
 
index c1b2e8dc9a26687c20ca565abe6a7e6600a1a5f3..ad4cea6839b271de330829e5bdfc1c3d86db7e6f 100644 (file)
@@ -652,7 +652,7 @@ static struct i2c_driver rtq6056_driver = {
                .of_match_table = rtq6056_device_match,
                .pm = pm_ptr(&rtq6056_pm_ops),
        },
-       .probe_new = rtq6056_probe,
+       .probe = rtq6056_probe,
 };
 module_i2c_driver(rtq6056_driver);
 
index 1aadb2ad2cabdf12130030d4bf8b341b0fb93c42..f7613efb870d58796b0c06e994e7ef79e1349f6f 100644 (file)
@@ -1993,6 +1993,8 @@ static int stm32_adc_get_legacy_chan_count(struct iio_dev *indio_dev, struct stm
        const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
        int num_channels = 0, ret;
 
+       dev_dbg(&indio_dev->dev, "using legacy channel config\n");
+
        ret = device_property_count_u32(dev, "st,adc-channels");
        if (ret > adc_info->max_channels) {
                dev_err(&indio_dev->dev, "Bad st,adc-channels?\n");
@@ -2006,16 +2008,15 @@ static int stm32_adc_get_legacy_chan_count(struct iio_dev *indio_dev, struct stm
         * to get the *real* number of channels.
         */
        ret = device_property_count_u32(dev, "st,adc-diff-channels");
-       if (ret < 0)
-               return ret;
-
-       ret /= (int)(sizeof(struct stm32_adc_diff_channel) / sizeof(u32));
-       if (ret > adc_info->max_channels) {
-               dev_err(&indio_dev->dev, "Bad st,adc-diff-channels?\n");
-               return -EINVAL;
-       } else if (ret > 0) {
-               adc->num_diff = ret;
-               num_channels += ret;
+       if (ret > 0) {
+               ret /= (int)(sizeof(struct stm32_adc_diff_channel) / sizeof(u32));
+               if (ret > adc_info->max_channels) {
+                       dev_err(&indio_dev->dev, "Bad st,adc-diff-channels?\n");
+                       return -EINVAL;
+               } else if (ret > 0) {
+                       adc->num_diff = ret;
+                       num_channels += ret;
+               }
        }
 
        /* Optional sample time is provided either for each, or all channels */
@@ -2037,6 +2038,7 @@ static int stm32_adc_legacy_chan_init(struct iio_dev *indio_dev,
        struct stm32_adc_diff_channel diff[STM32_ADC_CH_MAX];
        struct device *dev = &indio_dev->dev;
        u32 num_diff = adc->num_diff;
+       int num_se = nchans - num_diff;
        int size = num_diff * sizeof(*diff) / sizeof(u32);
        int scan_index = 0, ret, i, c;
        u32 smp = 0, smps[STM32_ADC_CH_MAX], chans[STM32_ADC_CH_MAX];
@@ -2063,29 +2065,32 @@ static int stm32_adc_legacy_chan_init(struct iio_dev *indio_dev,
                        scan_index++;
                }
        }
-
-       ret = device_property_read_u32_array(dev, "st,adc-channels", chans,
-                                            nchans);
-       if (ret)
-               return ret;
-
-       for (c = 0; c < nchans; c++) {
-               if (chans[c] >= adc_info->max_channels) {
-                       dev_err(&indio_dev->dev, "Invalid channel %d\n",
-                               chans[c]);
-                       return -EINVAL;
+       if (num_se > 0) {
+               ret = device_property_read_u32_array(dev, "st,adc-channels", chans, num_se);
+               if (ret) {
+                       dev_err(&indio_dev->dev, "Failed to get st,adc-channels %d\n", ret);
+                       return ret;
                }
 
-               /* Channel can't be configured both as single-ended & diff */
-               for (i = 0; i < num_diff; i++) {
-                       if (chans[c] == diff[i].vinp) {
-                               dev_err(&indio_dev->dev, "channel %d misconfigured\n",  chans[c]);
+               for (c = 0; c < num_se; c++) {
+                       if (chans[c] >= adc_info->max_channels) {
+                               dev_err(&indio_dev->dev, "Invalid channel %d\n",
+                                       chans[c]);
                                return -EINVAL;
                        }
+
+                       /* Channel can't be configured both as single-ended & diff */
+                       for (i = 0; i < num_diff; i++) {
+                               if (chans[c] == diff[i].vinp) {
+                                       dev_err(&indio_dev->dev, "channel %d misconfigured\n",
+                                               chans[c]);
+                                       return -EINVAL;
+                               }
+                       }
+                       stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
+                                               chans[c], 0, scan_index, false);
+                       scan_index++;
                }
-               stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
-                                       chans[c], 0, scan_index, false);
-               scan_index++;
        }
 
        if (adc->nsmps > 0) {
@@ -2306,7 +2311,7 @@ static int stm32_adc_chan_fw_init(struct iio_dev *indio_dev, bool timestamping)
 
        if (legacy)
                ret = stm32_adc_legacy_chan_init(indio_dev, adc, channels,
-                                                num_channels);
+                                                timestamping ? num_channels - 1 : num_channels);
        else
                ret = stm32_adc_generic_chan_init(indio_dev, adc, channels);
        if (ret < 0)
index c663dc59d45901b2c5cd55cf172b00c6ce6e0619..50c450e7a55fd1f0f5b1f0568674c245eefc99fc 100644 (file)
@@ -235,7 +235,7 @@ static struct i2c_driver adc081c_driver = {
                .of_match_table = adc081c_of_match,
                .acpi_match_table = adc081c_acpi_match,
        },
-       .probe_new = adc081c_probe,
+       .probe = adc081c_probe,
        .id_table = adc081c_id,
 };
 module_i2c_driver(adc081c_driver);
index 56af5e148802252c785cf1c626a3e570a467016d..075c75a875449e7c47b149f8a820c9fd4d2df973 100644 (file)
@@ -1195,7 +1195,7 @@ static struct i2c_driver ads1015_driver = {
                .of_match_table = ads1015_of_match,
                .pm = &ads1015_pm_ops,
        },
-       .probe_new      = ads1015_probe,
+       .probe          = ads1015_probe,
        .remove         = ads1015_remove,
        .id_table       = ads1015_id,
 };
index 6b5aebb82455143765dec5725aacc00557f09428..1e46f07a9ca6a805ea65d51e636caa30bb59e3b1 100644 (file)
@@ -434,7 +434,7 @@ static struct i2c_driver ads1100_driver = {
                   .of_match_table = ads1100_of_match,
                   .pm = pm_ptr(&ads1100_pm_ops),
        },
-       .probe_new = ads1100_probe,
+       .probe = ads1100_probe,
        .id_table = ads1100_id,
 };
 
index b02abb0269662d15e2dad83022cbf5b525280f20..afdbd04778a87ebb2e7421f32c32ccacf8753c0d 100644 (file)
@@ -463,7 +463,7 @@ static struct i2c_driver ads7924_driver = {
                .name = "ads7924",
                .of_match_table = ads7924_of_match,
        },
-       .probe_new      = ads7924_probe,
+       .probe          = ads7924_probe,
        .id_table       = ads7924_id,
 };
 
index 07e9f6ae16a83dc612dafbb212a63e888c934fda..6b0e8218f1507ed2688484f33178d2df69648333 100644 (file)
@@ -1007,7 +1007,7 @@ static int ad74413r_read_raw(struct iio_dev *indio_dev,
 
                ret = ad74413r_get_single_adc_result(indio_dev, chan->channel,
                                                     val);
-               if (ret)
+               if (ret < 0)
                        return ret;
 
                ad74413r_adc_to_resistance_result(*val, val);
@@ -1317,13 +1317,14 @@ static int ad74413r_setup_gpios(struct ad74413r_state *st)
                }
 
                if (config->func == CH_FUNC_DIGITAL_INPUT_LOGIC ||
-                   config->func == CH_FUNC_DIGITAL_INPUT_LOOP_POWER)
+                   config->func == CH_FUNC_DIGITAL_INPUT_LOOP_POWER) {
                        st->comp_gpio_offsets[comp_gpio_i++] = i;
 
-               strength = config->drive_strength;
-               ret = ad74413r_set_comp_drive_strength(st, i, strength);
-               if (ret)
-                       return ret;
+                       strength = config->drive_strength;
+                       ret = ad74413r_set_comp_drive_strength(st, i, strength);
+                       if (ret)
+                               return ret;
+               }
 
                ret = ad74413r_set_gpo_config(st, i, gpo_config);
                if (ret)
index f2c2ea79a07f3defd1e0b607631e06d4531d6207..8d8c8ea94258fa0e543947e9b86a29e529b948ce 100644 (file)
@@ -281,7 +281,7 @@ static int ad8366_probe(struct spi_device *spi)
        indio_dev->info = &ad8366_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
-       ret = ad8366_write(indio_dev, 0 , 0);
+       ret = ad8366_write(indio_dev, 0, 0);
        if (ret < 0)
                goto error_disable_reg;
 
index 79aeb0aaea67d05e529755d2c29585d8ed8e392f..d656d2f1275540aae44b5da9c0004b5fa5e9a780 100644 (file)
@@ -647,7 +647,7 @@ static struct i2c_driver ad7150_driver = {
                .name = "ad7150",
                .of_match_table = ad7150_of_match,
        },
-       .probe_new = ad7150_probe,
+       .probe = ad7150_probe,
        .id_table = ad7150_id,
 };
 module_i2c_driver(ad7150_driver);
index a1db5469f2d1e81d786d7f28264dfa6851655829..d11bc3496dda29bbe46974f3207be2e6ade6717d 100644 (file)
@@ -809,7 +809,7 @@ static struct i2c_driver ad7746_driver = {
                .name = KBUILD_MODNAME,
                .of_match_table = ad7746_of_match,
        },
-       .probe_new = ad7746_probe,
+       .probe = ad7746_probe,
        .id_table = ad7746_id,
 };
 module_i2c_driver(ad7746_driver);
index 0a0fbcdd446922142627448c0aa2e21d3da7cc06..164facac5db615536c154214f63cdaf9d958dcff 100644 (file)
@@ -179,7 +179,7 @@ static struct i2c_driver ams_iaqcore_driver = {
                .name   = "ams-iaq-core",
                .of_match_table = ams_iaqcore_dt_ids,
        },
-       .probe_new = ams_iaqcore_probe,
+       .probe = ams_iaqcore_probe,
        .id_table = ams_iaqcore_id,
 };
 module_i2c_driver(ams_iaqcore_driver);
index 307c3488f4bdddaa78a460d7bcdf4614c9a95651..8fc926a2d33bbece6e967895d478c7ce0b569d2d 100644 (file)
@@ -238,7 +238,7 @@ static struct i2c_driver atlas_ezo_driver = {
                .name   = ATLAS_EZO_DRV_NAME,
                .of_match_table = atlas_ezo_dt_ids,
        },
-       .probe_new      = atlas_ezo_probe,
+       .probe          = atlas_ezo_probe,
        .id_table       = atlas_ezo_id,
 };
 module_i2c_driver(atlas_ezo_driver);
index 024657bc59e171e36673b484655fa2131e7ae649..fb15bb216019389d7887596f0212d9d4b90f222b 100644 (file)
@@ -767,7 +767,7 @@ static struct i2c_driver atlas_driver = {
                .of_match_table = atlas_dt_ids,
                .pm     = pm_ptr(&atlas_pm_ops),
        },
-       .probe_new      = atlas_probe,
+       .probe          = atlas_probe,
        .remove         = atlas_remove,
        .id_table       = atlas_id,
 };
index 61b12079858d21ec86f878388fb846d0d242ea63..1c7076cf91cafa613ae1c3a9bf2084618befee63 100644 (file)
@@ -52,7 +52,7 @@ static struct i2c_driver bme680_i2c_driver = {
                .name                   = "bme680_i2c",
                .of_match_table         = bme680_of_i2c_match,
        },
-       .probe_new = bme680_i2c_probe,
+       .probe = bme680_i2c_probe,
        .id_table = bme680_i2c_id,
 };
 module_i2c_driver(bme680_i2c_driver);
index 6ead80c089240cfddc7110efb1a1016546e85b12..87741f155c32b632cd44e2cc5e56a7ee529c592f 100644 (file)
@@ -567,7 +567,7 @@ static struct i2c_driver ccs811_driver = {
                .name = "ccs811",
                .of_match_table = ccs811_dt_ids,
        },
-       .probe_new = ccs811_probe,
+       .probe = ccs811_probe,
        .remove = ccs811_remove,
        .id_table = ccs811_id,
 };
index bae479a4721f3b4977f72da16d7cd31086ba90bb..bd3b01ded246e0b9f5a0cafcbe8c030b38e58b19 100644 (file)
@@ -130,7 +130,7 @@ static struct i2c_driver scd30_i2c_driver = {
                .of_match_table = scd30_i2c_of_match,
                .pm = pm_sleep_ptr(&scd30_pm_ops),
        },
-       .probe_new = scd30_i2c_probe,
+       .probe = scd30_i2c_probe,
 };
 module_i2c_driver(scd30_i2c_driver);
 
index f7ed9455b3c8fada9e5de7c2f35738092e581988..a4f22d926400c60a7984b2a91068ee346cb038c2 100644 (file)
@@ -690,7 +690,7 @@ static struct i2c_driver scd4x_i2c_driver = {
                .of_match_table = scd4x_dt_ids,
                .pm = pm_sleep_ptr(&scd4x_pm_ops),
        },
-       .probe_new = scd4x_probe,
+       .probe = scd4x_probe,
 };
 module_i2c_driver(scd4x_i2c_driver);
 
index 9d0c68485b63f2e2eb3a4d399a839c8a635be9e7..b509cff9ce3748aa34ffcbec4f8136dfa9749f69 100644 (file)
@@ -575,7 +575,7 @@ static struct i2c_driver sgp_driver = {
                .name = "sgp30",
                .of_match_table = sgp_dt_ids,
        },
-       .probe_new = sgp_probe,
+       .probe = sgp_probe,
        .remove = sgp_remove,
        .id_table = sgp_id,
 };
index c0ea0130090810267b62a07ca4421fdf7ea945e6..7f0de14a1956fe31da520554ae33f8ab7951a668 100644 (file)
@@ -368,7 +368,7 @@ static struct i2c_driver sgp40_driver = {
                .name = "sgp40",
                .of_match_table = sgp40_dt_ids,
        },
-       .probe_new = sgp40_probe,
+       .probe = sgp40_probe,
        .id_table = sgp40_id,
 };
 module_i2c_driver(sgp40_driver);
index 0cb5d9b65d625263cf362836892833a7355e8f17..5c31299813ecf92a8b9f498fa44b9366aa4d195f 100644 (file)
@@ -249,7 +249,7 @@ static struct i2c_driver sps30_i2c_driver = {
                .of_match_table = sps30_i2c_of_match,
        },
        .id_table = sps30_i2c_id,
-       .probe_new = sps30_i2c_probe,
+       .probe = sps30_i2c_probe,
 };
 module_i2c_driver(sps30_i2c_driver);
 
index 8440dc0c77cfe9bff06dfe4067c1310e85445c26..cdb8696a4e814ef3e4089c3e74abe437ca8ce7e9 100644 (file)
@@ -528,7 +528,7 @@ static struct i2c_driver sunrise_driver = {
                .name = DRIVER_NAME,
                .of_match_table = sunrise_of_match,
        },
-       .probe_new = sunrise_probe,
+       .probe = sunrise_probe,
 };
 module_i2c_driver(sunrise_driver);
 
index d4604f7ccd1e0e559f34db0beb6759e2d2837096..13555f4f401afc5f43f2db15ab1c40b2b148c94e 100644 (file)
@@ -402,7 +402,7 @@ static struct i2c_driver vz89x_driver = {
                .name   = "vz89x",
                .of_match_table = vz89x_dt_ids,
        },
-       .probe_new = vz89x_probe,
+       .probe = vz89x_probe,
        .id_table = vz89x_id,
 };
 module_i2c_driver(vz89x_driver);
index 6c74fea21736a426414689aabdb19422e5258356..addd97a788389cfb1305d41e872111534898c047 100644 (file)
@@ -17,7 +17,7 @@ obj-$(CONFIG_AD5592R_BASE) += ad5592r-base.o
 obj-$(CONFIG_AD5592R) += ad5592r.o
 obj-$(CONFIG_AD5593R) += ad5593r.o
 obj-$(CONFIG_AD5755) += ad5755.o
-obj-$(CONFIG_AD5755) += ad5758.o
+obj-$(CONFIG_AD5758) += ad5758.o
 obj-$(CONFIG_AD5761) += ad5761.o
 obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5766) += ad5766.o
index f01249c1ba93cfbc89bf470b07bd8b49109b0e22..7712dc6be608f3f07bfc47487e952d2a7ef585fc 100644 (file)
@@ -1056,7 +1056,7 @@ static struct i2c_driver ad5064_i2c_driver = {
        .driver = {
                   .name = "ad5064",
        },
-       .probe_new = ad5064_i2c_probe,
+       .probe = ad5064_i2c_probe,
        .id_table = ad5064_i2c_ids,
 };
 
index 64b4519f8f5e6d52a5b2387f44a59b653e17064d..2e3e33f92bc0afebe30c5cdbef177648a0bc969c 100644 (file)
@@ -589,7 +589,7 @@ static struct i2c_driver ad5380_i2c_driver = {
        .driver = {
                   .name = "ad5380",
        },
-       .probe_new = ad5380_i2c_probe,
+       .probe = ad5380_i2c_probe,
        .remove = ad5380_i2c_remove,
        .id_table = ad5380_i2c_ids,
 };
index aa3130b3345638e2d77056c942f7fe240e618140..8103d2cd13f66f3415d666436458fd1d1d1a0079 100644 (file)
@@ -595,7 +595,7 @@ static struct i2c_driver ad5446_i2c_driver = {
        .driver = {
                   .name = "ad5446",
        },
-       .probe_new = ad5446_i2c_probe,
+       .probe = ad5446_i2c_probe,
        .remove = ad5446_i2c_remove,
        .id_table = ad5446_i2c_ids,
 };
index d311567ab324a68db56bd80bb7f78ba716483c0e..fae5e5a0e72fca1a6cc5de37b4581d36c5c7e0d3 100644 (file)
@@ -138,7 +138,7 @@ static struct i2c_driver ad5593r_driver = {
                .of_match_table = ad5593r_of_match,
                .acpi_match_table = ad5593r_acpi_match,
        },
-       .probe_new = ad5593r_i2c_probe,
+       .probe = ad5593r_i2c_probe,
        .remove = ad5593r_i2c_remove,
        .id_table = ad5593r_i2c_ids,
 };
index 8a95f027801850ba3cdb8fbe17015078087d064c..81541f755a3e1bb34a5c5621a803e3fb6e3c3a17 100644 (file)
@@ -115,7 +115,7 @@ static struct i2c_driver ad5686_i2c_driver = {
                .name = "ad5696",
                .of_match_table = ad5686_of_match,
        },
-       .probe_new = ad5686_i2c_probe,
+       .probe = ad5686_i2c_probe,
        .remove = ad5686_i2c_remove,
        .id_table = ad5686_i2c_id,
 };
index a16a6a934d9d97b987028e2ba12788b68c44a7e4..e89e4c0546531f186563da3c5e312e1811e8a79a 100644 (file)
@@ -312,7 +312,7 @@ static struct i2c_driver ds4424_driver = {
                .of_match_table = ds4424_of_match,
                .pm     = pm_sleep_ptr(&ds4424_pm_ops),
        },
-       .probe_new      = ds4424_probe,
+       .probe          = ds4424_probe,
        .remove         = ds4424_remove,
        .id_table       = ds4424_id,
 };
index b692459b0f231599e31470a77bba096a2022f971..ae53baccec91493d15107aea9dbadddd5c31edd9 100644 (file)
@@ -238,7 +238,7 @@ static struct i2c_driver m62332_driver = {
                .name   = "m62332",
                .pm     = pm_sleep_ptr(&m62332_pm_ops),
        },
-       .probe_new      = m62332_probe,
+       .probe          = m62332_probe,
        .remove         = m62332_remove,
        .id_table       = m62332_id,
 };
index 25967c39365d2bbd841b49da4d230e888b61bbd7..685980184d3c82ed16728ace493ed3cf545bd7a7 100644 (file)
@@ -203,7 +203,7 @@ static struct i2c_driver max517_driver = {
                .name   = MAX517_DRV_NAME,
                .pm     = pm_sleep_ptr(&max517_pm_ops),
        },
-       .probe_new      = max517_probe,
+       .probe          = max517_probe,
        .id_table       = max517_id,
 };
 module_i2c_driver(max517_driver);
index 23da345b9250cf7570bf752c0795ccbcac785de3..18ba3eaaad7564ebb043d9984dbf5c8302ab8353 100644 (file)
@@ -377,7 +377,7 @@ static struct i2c_driver max5821_driver = {
                .of_match_table = max5821_of_match,
                .pm     = pm_sleep_ptr(&max5821_pm_ops),
        },
-       .probe_new      = max5821_probe,
+       .probe          = max5821_probe,
        .id_table       = max5821_id,
 };
 module_i2c_driver(max5821_driver);
index 46bf758760f85bbd9500da020c3740fef1529e11..f4a3124d29f21a4b73067070a6afafd05ec114ac 100644 (file)
@@ -47,12 +47,18 @@ static int mcp4725_suspend(struct device *dev)
        struct mcp4725_data *data = iio_priv(i2c_get_clientdata(
                to_i2c_client(dev)));
        u8 outbuf[2];
+       int ret;
 
        outbuf[0] = (data->powerdown_mode + 1) << 4;
        outbuf[1] = 0;
        data->powerdown = true;
 
-       return i2c_master_send(data->client, outbuf, 2);
+       ret = i2c_master_send(data->client, outbuf, 2);
+       if (ret < 0)
+               return ret;
+       else if (ret != 2)
+               return -EIO;
+       return 0;
 }
 
 static int mcp4725_resume(struct device *dev)
@@ -60,13 +66,19 @@ static int mcp4725_resume(struct device *dev)
        struct mcp4725_data *data = iio_priv(i2c_get_clientdata(
                to_i2c_client(dev)));
        u8 outbuf[2];
+       int ret;
 
        /* restore previous DAC value */
        outbuf[0] = (data->dac_value >> 8) & 0xf;
        outbuf[1] = data->dac_value & 0xff;
        data->powerdown = false;
 
-       return i2c_master_send(data->client, outbuf, 2);
+       ret = i2c_master_send(data->client, outbuf, 2);
+       if (ret < 0)
+               return ret;
+       else if (ret != 2)
+               return -EIO;
+       return 0;
 }
 static DEFINE_SIMPLE_DEV_PM_OPS(mcp4725_pm_ops, mcp4725_suspend,
                                mcp4725_resume);
@@ -524,7 +536,7 @@ static struct i2c_driver mcp4725_driver = {
                .of_match_table = mcp4725_of_match,
                .pm     = pm_sleep_ptr(&mcp4725_pm_ops),
        },
-       .probe_new      = mcp4725_probe,
+       .probe          = mcp4725_probe,
        .remove         = mcp4725_remove,
        .id_table       = mcp4725_id,
 };
index 40191947fea321aa2ffe54aead757e9ac9110475..bab11b9adc25252feb4ad22def830dd8111b3aa2 100644 (file)
@@ -426,7 +426,7 @@ static struct i2c_driver dac5571_driver = {
                   .name = "ti-dac5571",
                   .of_match_table = dac5571_of_id,
        },
-       .probe_new = dac5571_probe,
+       .probe = dac5571_probe,
        .remove   = dac5571_remove,
        .id_table = dac5571_id,
 };
index 2b019ee5b2eb5ed1a27f7022698662150002a59d..2f9675596138b2663fd00a8c844183ea4c4cd710 100644 (file)
@@ -70,7 +70,7 @@ static struct i2c_driver bmg160_i2c_driver = {
                .of_match_table = bmg160_of_match,
                .pm     = &bmg160_pm_ops,
        },
-       .probe_new      = bmg160_i2c_probe,
+       .probe          = bmg160_i2c_probe,
        .remove         = bmg160_i2c_remove,
        .id_table       = bmg160_i2c_id,
 };
index 9e2d0f34a672ea0a473b91cd1270bbbea3f31070..ee7f21b718e2db57752581bd71210f70297f747a 100644 (file)
@@ -56,7 +56,7 @@ static struct i2c_driver fxas21002c_i2c_driver = {
                .pm = pm_ptr(&fxas21002c_pm_ops),
                .of_match_table = fxas21002c_i2c_of_match,
        },
-       .probe_new      = fxas21002c_i2c_probe,
+       .probe          = fxas21002c_i2c_probe,
        .remove         = fxas21002c_i2c_remove,
        .id_table       = fxas21002c_i2c_id,
 };
index ceacd863d3eaaf23be14418e72fc5c164363c1be..53fb92f0ac7ef909551a73fc400dfc88a51ca13c 100644 (file)
@@ -405,7 +405,7 @@ static struct i2c_driver itg3200_driver = {
                .pm     = pm_sleep_ptr(&itg3200_pm_ops),
        },
        .id_table       = itg3200_id,
-       .probe_new      = itg3200_probe,
+       .probe          = itg3200_probe,
        .remove         = itg3200_remove,
 };
 
index 2116798226bf28b6440540eef7c42442b756a84b..52b6feed26379a78bfab3af3180b4cec19c936ea 100644 (file)
@@ -108,7 +108,7 @@ static const struct of_device_id mpu3050_i2c_of_match[] = {
 MODULE_DEVICE_TABLE(of, mpu3050_i2c_of_match);
 
 static struct i2c_driver mpu3050_i2c_driver = {
-       .probe_new = mpu3050_i2c_probe,
+       .probe = mpu3050_i2c_probe,
        .remove = mpu3050_i2c_remove,
        .id_table = mpu3050_i2c_id,
        .driver = {
index 797a1c6a0402063f8124b8f79d00fe69b165d71f..5a10a3556ab054fd3871f2636c595ef6f0c98dfc 100644 (file)
@@ -111,7 +111,7 @@ static struct i2c_driver st_gyro_driver = {
                .name = "st-gyro-i2c",
                .of_match_table = st_gyro_of_match,
        },
-       .probe_new = st_gyro_i2c_probe,
+       .probe = st_gyro_i2c_probe,
        .id_table = st_gyro_id_table,
 };
 module_i2c_driver(st_gyro_driver);
index 21a6378b70524930e038ca0eea0bc1570b14587c..ede1e82013118c24c005ec4fa7a33c88f373525d 100644 (file)
@@ -609,7 +609,7 @@ static struct i2c_driver afe4404_i2c_driver = {
                .of_match_table = afe4404_of_match,
                .pm = pm_sleep_ptr(&afe4404_pm_ops),
        },
-       .probe_new = afe4404_probe,
+       .probe = afe4404_probe,
        .remove = afe4404_remove,
        .id_table = afe4404_ids,
 };
index a80fa9852c220fe995c0515be9b0e45ae97aa7bc..6236b4d9613786201d797749a4df99c8787a8345 100644 (file)
@@ -499,7 +499,7 @@ static struct i2c_driver max30100_driver = {
                .name   = MAX30100_DRV_NAME,
                .of_match_table = max30100_dt_ids,
        },
-       .probe_new      = max30100_probe,
+       .probe          = max30100_probe,
        .remove         = max30100_remove,
        .id_table       = max30100_id,
 };
index 7edcf9e05687bf8475eb2a989c187a523c594942..37e619827e8a11711230d93aa5950d979cb96c99 100644 (file)
@@ -631,7 +631,7 @@ static struct i2c_driver max30102_driver = {
                .name   = MAX30102_DRV_NAME,
                .of_match_table = max30102_dt_ids,
        },
-       .probe_new      = max30102_probe,
+       .probe          = max30102_probe,
        .remove         = max30102_remove,
        .id_table       = max30102_id,
 };
index f246516bd45eab7b886fd7893c7f0574aba1ded7..37a35d1153d5023f049d9efbe85c6216eff36a1c 100644 (file)
@@ -262,7 +262,7 @@ static struct i2c_driver am2315_driver = {
        .driver = {
                .name = "am2315",
        },
-       .probe_new =        am2315_probe,
+       .probe =        am2315_probe,
        .id_table =         am2315_i2c_id,
 };
 
index 49a950d739e44301c431b3a47fc554a948d388f5..202014da2785c74a9bbaa1ec89544c802f507fb1 100644 (file)
@@ -428,7 +428,7 @@ static struct i2c_driver hdc100x_driver = {
                .of_match_table = hdc100x_dt_ids,
                .acpi_match_table = hdc100x_acpi_match,
        },
-       .probe_new = hdc100x_probe,
+       .probe = hdc100x_probe,
        .id_table = hdc100x_id,
 };
 module_i2c_driver(hdc100x_driver);
index c8fddd612e060a77d79a85bab1c19cdd562e07e8..f5867659e00fcea0f866191dbd7f234da88f4ab8 100644 (file)
@@ -338,7 +338,7 @@ static struct i2c_driver hdc2010_driver = {
                .name   = "hdc2010",
                .of_match_table = hdc2010_dt_ids,
        },
-       .probe_new = hdc2010_probe,
+       .probe = hdc2010_probe,
        .remove = hdc2010_remove,
        .id_table = hdc2010_id,
 };
index d81869423cf031564a07d095e20339b68bbaf918..30f2068ea156675cac8e976cff982263bc2c623c 100644 (file)
@@ -65,7 +65,7 @@ static struct i2c_driver hts221_driver = {
                .of_match_table = hts221_i2c_of_match,
                .acpi_match_table = ACPI_PTR(hts221_acpi_match),
        },
-       .probe_new = hts221_i2c_probe,
+       .probe = hts221_i2c_probe,
        .id_table = hts221_i2c_id_table,
 };
 module_i2c_driver(hts221_driver);
index 8411a9f3e828aaca3cb2cbdc9ddbc083a76c2b4d..39e886075299ea4648cc1e140fbe019e7823719e 100644 (file)
@@ -244,7 +244,7 @@ static const struct of_device_id htu21_of_match[] = {
 MODULE_DEVICE_TABLE(of, htu21_of_match);
 
 static struct i2c_driver htu21_driver = {
-       .probe_new = htu21_probe,
+       .probe = htu21_probe,
        .id_table = htu21_id,
        .driver = {
                   .name = "htu21",
index fa1faf168c8d9e00304cf0e7d878ee429b186e94..ebfb79bc9edc5ae8822324601dabb2728f92b091 100644 (file)
@@ -173,7 +173,7 @@ static struct i2c_driver si7005_driver = {
        .driver = {
                .name   = "si7005",
        },
-       .probe_new = si7005_probe,
+       .probe = si7005_probe,
        .id_table = si7005_id,
 };
 module_i2c_driver(si7005_driver);
index 3e50592e8e68bee1b1343422a4db19bb2674e9a7..fb10066493288829a15c3b83fb254ed6b6bd9bab 100644 (file)
@@ -155,7 +155,7 @@ static struct i2c_driver si7020_driver = {
                .name = "si7020",
                .of_match_table = si7020_dt_ids,
        },
-       .probe_new      = si7020_probe,
+       .probe          = si7020_probe,
        .id_table       = si7020_id,
 };
 
index 2ca907d396a01579e724c11fc633af6d7a6b1125..81652c08e6441c4472b847c40a4d42e64a5d668e 100644 (file)
@@ -60,7 +60,7 @@ static struct i2c_driver bmi160_i2c_driver = {
                .acpi_match_table       = bmi160_acpi_match,
                .of_match_table         = bmi160_of_match,
        },
-       .probe_new      = bmi160_i2c_probe,
+       .probe          = bmi160_i2c_probe,
        .id_table       = bmi160_i2c_id,
 };
 module_i2c_driver(bmi160_i2c_driver);
index c1bbc0fe34f9bdd467c2506f46d3957699e6da29..6ecd750c6b7640b9e68b33fd5f848e603d0df669 100644 (file)
@@ -46,7 +46,7 @@ static struct i2c_driver bno055_driver = {
                .name = "bno055-i2c",
                .of_match_table = bno055_i2c_of_match,
        },
-       .probe_new = bno055_i2c_probe,
+       .probe = bno055_i2c_probe,
        .id_table = bno055_i2c_id,
 };
 module_i2c_driver(bno055_driver);
index a74a15fda8cbb5975d650e565c7ddb893fb00ab3..2ace306d0f9ab81b5124d451b0f3f2257874f1a6 100644 (file)
@@ -60,7 +60,7 @@ static struct i2c_driver fxos8700_i2c_driver = {
                .acpi_match_table       = ACPI_PTR(fxos8700_acpi_match),
                .of_match_table         = fxos8700_of_match,
        },
-       .probe_new      = fxos8700_i2c_probe,
+       .probe          = fxos8700_i2c_probe,
        .id_table       = fxos8700_i2c_id,
 };
 module_i2c_driver(fxos8700_i2c_driver);
index 99576b2c171f4d3d47f18de4704511ec69d1842e..32d7f836423036851b33493ded7e12007eadb47d 100644 (file)
@@ -275,9 +275,14 @@ static int inv_icm42600_buffer_preenable(struct iio_dev *indio_dev)
 {
        struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
        struct device *dev = regmap_get_device(st->map);
+       struct inv_icm42600_timestamp *ts = iio_priv(indio_dev);
 
        pm_runtime_get_sync(dev);
 
+       mutex_lock(&st->lock);
+       inv_icm42600_timestamp_reset(ts);
+       mutex_unlock(&st->lock);
+
        return 0;
 }
 
@@ -375,7 +380,6 @@ static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev)
        struct device *dev = regmap_get_device(st->map);
        unsigned int sensor;
        unsigned int *watermark;
-       struct inv_icm42600_timestamp *ts;
        struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
        unsigned int sleep_temp = 0;
        unsigned int sleep_sensor = 0;
@@ -385,11 +389,9 @@ static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev)
        if (indio_dev == st->indio_gyro) {
                sensor = INV_ICM42600_SENSOR_GYRO;
                watermark = &st->fifo.watermark.gyro;
-               ts = iio_priv(st->indio_gyro);
        } else if (indio_dev == st->indio_accel) {
                sensor = INV_ICM42600_SENSOR_ACCEL;
                watermark = &st->fifo.watermark.accel;
-               ts = iio_priv(st->indio_accel);
        } else {
                return -EINVAL;
        }
@@ -417,8 +419,6 @@ static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev)
        if (!st->fifo.on)
                ret = inv_icm42600_set_temp_conf(st, false, &sleep_temp);
 
-       inv_icm42600_timestamp_reset(ts);
-
 out_unlock:
        mutex_unlock(&st->lock);
 
index eb2681ad375f224b3b0f07dfbbc49ba59abf1c8c..1af559403ba66d6cfebf4e392505f022b2892efa 100644 (file)
@@ -98,7 +98,7 @@ static struct i2c_driver inv_icm42600_driver = {
                .of_match_table = inv_icm42600_of_matches,
                .pm = pm_ptr(&inv_icm42600_pm_ops),
        },
-       .probe_new = inv_icm42600_probe,
+       .probe = inv_icm42600_probe,
 };
 module_i2c_driver(inv_icm42600_driver);
 
index 7f2dc41f807bbec946c5ac96bd9a02c5e28d0069..37cbf08acb3a17303b38986ce7dbe8c80e6720d0 100644 (file)
@@ -93,8 +93,8 @@ static bool inv_validate_period(uint32_t period, uint32_t mult)
                return false;
 }
 
-static bool inv_compute_chip_period(struct inv_icm42600_timestamp *ts,
-                                   uint32_t mult, uint32_t period)
+static bool inv_update_chip_period(struct inv_icm42600_timestamp *ts,
+                                  uint32_t mult, uint32_t period)
 {
        uint32_t new_chip_period;
 
@@ -104,10 +104,31 @@ static bool inv_compute_chip_period(struct inv_icm42600_timestamp *ts,
        /* update chip internal period estimation */
        new_chip_period = period / mult;
        inv_update_acc(&ts->chip_period, new_chip_period);
+       ts->period = ts->mult * ts->chip_period.val;
 
        return true;
 }
 
+static void inv_align_timestamp_it(struct inv_icm42600_timestamp *ts)
+{
+       int64_t delta, jitter;
+       int64_t adjust;
+
+       /* delta time between last sample and last interrupt */
+       delta = ts->it.lo - ts->timestamp;
+
+       /* adjust timestamp while respecting jitter */
+       jitter = div_s64((int64_t)ts->period * INV_ICM42600_TIMESTAMP_JITTER, 100);
+       if (delta > jitter)
+               adjust = jitter;
+       else if (delta < -jitter)
+               adjust = -jitter;
+       else
+               adjust = 0;
+
+       ts->timestamp += adjust;
+}
+
 void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts,
                                      uint32_t fifo_period, size_t fifo_nb,
                                      size_t sensor_nb, int64_t timestamp)
@@ -116,7 +137,6 @@ void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts,
        int64_t delta, interval;
        const uint32_t fifo_mult = fifo_period / INV_ICM42600_TIMESTAMP_PERIOD;
        uint32_t period = ts->period;
-       int32_t m;
        bool valid = false;
 
        if (fifo_nb == 0)
@@ -130,10 +150,7 @@ void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts,
        if (it->lo != 0) {
                /* compute period: delta time divided by number of samples */
                period = div_s64(delta, fifo_nb);
-               valid = inv_compute_chip_period(ts, fifo_mult, period);
-               /* update sensor period if chip internal period is updated */
-               if (valid)
-                       ts->period = ts->mult * ts->chip_period.val;
+               valid = inv_update_chip_period(ts, fifo_mult, period);
        }
 
        /* no previous data, compute theoritical value from interrupt */
@@ -145,22 +162,8 @@ void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts,
        }
 
        /* if interrupt interval is valid, sync with interrupt timestamp */
-       if (valid) {
-               /* compute measured fifo_period */
-               fifo_period = fifo_mult * ts->chip_period.val;
-               /* delta time between last sample and last interrupt */
-               delta = it->lo - ts->timestamp;
-               /* if there are multiple samples, go back to first one */
-               while (delta >= (fifo_period * 3 / 2))
-                       delta -= fifo_period;
-               /* compute maximal adjustment value */
-               m = INV_ICM42600_TIMESTAMP_MAX_PERIOD(ts->period) - ts->period;
-               if (delta > m)
-                       delta = m;
-               else if (delta < -m)
-                       delta = -m;
-               ts->timestamp += delta;
-       }
+       if (valid)
+               inv_align_timestamp_it(ts);
 }
 
 void inv_icm42600_timestamp_apply_odr(struct inv_icm42600_timestamp *ts,
index 3636b1bc90f1c2dcf3c899ab2776cf834b00a284..64dd73dcc4bab48fe611e819d5b706c9f5078a10 100644 (file)
@@ -16,7 +16,7 @@ config INV_MPU6050_I2C
        select REGMAP_I2C
        help
          This driver supports the Invensense MPU6050/9150,
-         MPU6500/6515/6880/9250/9255, ICM20608(D)/20609/20689, ICM20602/ICM20690
+         MPU6500/6515/6880/9250/9255, ICM20608(D)/20609/20689, ICM20600/20602/20690
          and IAM20680 motion tracking devices over I2C.
          This driver can be built as a module. The module will be called
          inv-mpu6050-i2c.
@@ -28,7 +28,7 @@ config INV_MPU6050_SPI
        select REGMAP_SPI
        help
          This driver supports the Invensense MPU6000,
-         MPU6500/6515/6880/9250/9255, ICM20608(D)/20609/20689, ICM20602/ICM20690
+         MPU6500/6515/6880/9250/9255, ICM20608(D)/20609/20689, ICM20600/20602/20690
          and IAM20680 motion tracking devices over SPI.
          This driver can be built as a module. The module will be called
          inv-mpu6050-spi.
index 8a129120b73dd1f7fd1016ea7e5fc762d0a136ce..592a6e60b4131e0d79d091121fd5a1f0793d19ad 100644 (file)
@@ -244,6 +244,15 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
                .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
        },
+       {
+               .whoami = INV_ICM20600_WHOAMI_VALUE,
+               .name = "ICM20600",
+               .reg = &reg_set_icm20602,
+               .config = &chip_config_6500,
+               .fifo_size = 1008,
+               .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
+               .startup_time = {INV_ICM20602_GYRO_STARTUP_TIME, INV_ICM20602_ACCEL_STARTUP_TIME},
+       },
        {
                .whoami = INV_ICM20602_WHOAMI_VALUE,
                .name = "ICM20602",
@@ -1597,6 +1606,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
                indio_dev->num_channels = ARRAY_SIZE(inv_mpu9250_channels);
                indio_dev->available_scan_masks = inv_mpu9x50_scan_masks;
                break;
+       case INV_ICM20600:
        case INV_ICM20602:
                indio_dev->channels = inv_mpu_channels;
                indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
index 2f2da4cb732156fc4e7874027464ca17f2e4b9e7..410ea39fd495a693aebd365647c3e47c38c5976a 100644 (file)
@@ -32,6 +32,7 @@ static bool inv_mpu_i2c_aux_bus(struct device *dev)
        case INV_ICM20608D:
        case INV_ICM20609:
        case INV_ICM20689:
+       case INV_ICM20600:
        case INV_ICM20602:
        case INV_IAM20680:
                /* no i2c auxiliary bus on the chip */
@@ -183,6 +184,7 @@ static const struct i2c_device_id inv_mpu_id[] = {
        {"icm20608d", INV_ICM20608D},
        {"icm20609", INV_ICM20609},
        {"icm20689", INV_ICM20689},
+       {"icm20600", INV_ICM20600},
        {"icm20602", INV_ICM20602},
        {"icm20690", INV_ICM20690},
        {"iam20680", INV_IAM20680},
@@ -236,6 +238,10 @@ static const struct of_device_id inv_of_match[] = {
                .compatible = "invensense,icm20689",
                .data = (void *)INV_ICM20689
        },
+       {
+               .compatible = "invensense,icm20600",
+               .data = (void *)INV_ICM20600
+       },
        {
                .compatible = "invensense,icm20602",
                .data = (void *)INV_ICM20602
@@ -259,7 +265,7 @@ static const struct acpi_device_id inv_acpi_match[] = {
 MODULE_DEVICE_TABLE(acpi, inv_acpi_match);
 
 static struct i2c_driver inv_mpu_driver = {
-       .probe_new      =       inv_mpu_probe,
+       .probe          =       inv_mpu_probe,
        .remove         =       inv_mpu_remove,
        .id_table       =       inv_mpu_id,
        .driver = {
index 94b54c501ec0a663c0a805a32201c379b018be0c..b4ab2c397d0fce92c9ed28f604d81b5fe8a9efb4 100644 (file)
@@ -79,6 +79,7 @@ enum inv_devices {
        INV_ICM20608D,
        INV_ICM20609,
        INV_ICM20689,
+       INV_ICM20600,
        INV_ICM20602,
        INV_ICM20690,
        INV_IAM20680,
@@ -398,6 +399,7 @@ struct inv_mpu6050_state {
 #define INV_ICM20608D_WHOAMI_VALUE             0xAE
 #define INV_ICM20609_WHOAMI_VALUE              0xA6
 #define INV_ICM20689_WHOAMI_VALUE              0x98
+#define INV_ICM20600_WHOAMI_VALUE              0x11
 #define INV_ICM20602_WHOAMI_VALUE              0x12
 #define INV_ICM20690_WHOAMI_VALUE              0x20
 #define INV_IAM20680_WHOAMI_VALUE              0xA9
index 89f46c2f213d8fb179075027cce6305ca6cc3dce..05451ca1580b637a66a30efe82fbd2a2b63e55d5 100644 (file)
@@ -76,6 +76,7 @@ static const struct spi_device_id inv_mpu_id[] = {
        {"icm20608d", INV_ICM20608D},
        {"icm20609", INV_ICM20609},
        {"icm20689", INV_ICM20689},
+       {"icm20600", INV_ICM20600},
        {"icm20602", INV_ICM20602},
        {"icm20690", INV_ICM20690},
        {"iam20680", INV_IAM20680},
@@ -125,6 +126,10 @@ static const struct of_device_id inv_of_match[] = {
                .compatible = "invensense,icm20689",
                .data = (void *)INV_ICM20689
        },
+       {
+               .compatible = "invensense,icm20600",
+               .data = (void *)INV_ICM20600
+       },
        {
                .compatible = "invensense,icm20602",
                .data = (void *)INV_ICM20602
index 53ba020fa5d00b59f854ca89abb84a297b414c2f..958167b31241e639002090941ed044580949bde2 100644 (file)
@@ -1517,7 +1517,7 @@ static struct i2c_driver kmx61_driver = {
                .acpi_match_table = ACPI_PTR(kmx61_acpi_match),
                .pm = pm_ptr(&kmx61_pm_ops),
        },
-       .probe_new      = kmx61_probe,
+       .probe          = kmx61_probe,
        .remove         = kmx61_remove,
        .id_table       = kmx61_id,
 };
index 020717f92363cd6294471efde0ae54f9f7236822..911444ec57c0166bda209709e11543f9c7b2980d 100644 (file)
@@ -179,7 +179,7 @@ static struct i2c_driver st_lsm6dsx_driver = {
                .of_match_table = st_lsm6dsx_i2c_of_match,
                .acpi_match_table = st_lsm6dsx_i2c_acpi_match,
        },
-       .probe_new = st_lsm6dsx_i2c_probe,
+       .probe = st_lsm6dsx_i2c_probe,
        .id_table = st_lsm6dsx_i2c_id_table,
 };
 module_i2c_driver(st_lsm6dsx_driver);
index d29558edee60414d96797821674f72cc3c5cdffb..7aef714b6ecb6fa48c5318f4d160c9b2eaa3fbb4 100644 (file)
@@ -10,7 +10,8 @@ config IIO_ST_LSM9DS0
 
        help
          Say yes here to build support for STMicroelectronics LSM9DS0 IMU
-         sensor. Supported devices: accelerometer/magnetometer of lsm9ds0.
+         sensor. Supported devices: accelerometer/magnetometer of lsm9ds0
+         and lsm303d.
 
          To compile this driver as a module, choose M here: the module
          will be called st_lsm9ds0.
index a90138d8b06a86e6cc09d6af8330846267a71d59..61d855083aa012e770dbb8107f6f5e2d5130e593 100644 (file)
 #include "st_lsm9ds0.h"
 
 static const struct of_device_id st_lsm9ds0_of_match[] = {
+       {
+               .compatible = "st,lsm303d-imu",
+               .data = LSM303D_IMU_DEV_NAME,
+       },
        {
                .compatible = "st,lsm9ds0-imu",
                .data = LSM9DS0_IMU_DEV_NAME,
@@ -27,11 +31,18 @@ static const struct of_device_id st_lsm9ds0_of_match[] = {
 MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match);
 
 static const struct i2c_device_id st_lsm9ds0_id_table[] = {
+       { LSM303D_IMU_DEV_NAME },
        { LSM9DS0_IMU_DEV_NAME },
        {}
 };
 MODULE_DEVICE_TABLE(i2c, st_lsm9ds0_id_table);
 
+static const struct acpi_device_id st_lsm9ds0_acpi_match[] = {
+       {"ACCL0001", (kernel_ulong_t)LSM303D_IMU_DEV_NAME},
+       { },
+};
+MODULE_DEVICE_TABLE(acpi, st_lsm9ds0_acpi_match);
+
 static const struct regmap_config st_lsm9ds0_regmap_config = {
        .reg_bits       = 8,
        .val_bits       = 8,
@@ -68,8 +79,9 @@ static struct i2c_driver st_lsm9ds0_driver = {
        .driver = {
                .name = "st-lsm9ds0-i2c",
                .of_match_table = st_lsm9ds0_of_match,
+               .acpi_match_table = st_lsm9ds0_acpi_match,
        },
-       .probe_new = st_lsm9ds0_i2c_probe,
+       .probe = st_lsm9ds0_i2c_probe,
        .id_table = st_lsm9ds0_id_table,
 };
 module_i2c_driver(st_lsm9ds0_driver);
index b743bf3546a7f960e88e0865060afa60631dd1be..8cc041d56cf76257105c4c114cb2bbbdca7860d8 100644 (file)
 #include "st_lsm9ds0.h"
 
 static const struct of_device_id st_lsm9ds0_of_match[] = {
+       {
+               .compatible = "st,lsm303d-imu",
+               .data = LSM303D_IMU_DEV_NAME,
+       },
        {
                .compatible = "st,lsm9ds0-imu",
                .data = LSM9DS0_IMU_DEV_NAME,
@@ -27,6 +31,7 @@ static const struct of_device_id st_lsm9ds0_of_match[] = {
 MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match);
 
 static const struct spi_device_id st_lsm9ds0_id_table[] = {
+       { LSM303D_IMU_DEV_NAME },
        { LSM9DS0_IMU_DEV_NAME },
        {}
 };
index a7a080bed1808f1f763bdb6dfff7c939c95a2bc8..176d31d9f9d807ed2b8d83ab706c085cf2e56590 100644 (file)
@@ -194,7 +194,7 @@ static ssize_t iio_buffer_write(struct file *filp, const char __user *buf,
        written = 0;
        add_wait_queue(&rb->pollq, &wait);
        do {
-               if (indio_dev->info == NULL)
+               if (!indio_dev->info)
                        return -ENODEV;
 
                if (!iio_buffer_space_available(rb)) {
@@ -210,7 +210,7 @@ static ssize_t iio_buffer_write(struct file *filp, const char __user *buf,
                        }
 
                        wait_woken(&wait, TASK_INTERRUPTIBLE,
-                                       MAX_SCHEDULE_TIMEOUT);
+                                  MAX_SCHEDULE_TIMEOUT);
                        continue;
                }
 
@@ -242,7 +242,7 @@ static __poll_t iio_buffer_poll(struct file *filp,
        struct iio_buffer *rb = ib->buffer;
        struct iio_dev *indio_dev = ib->indio_dev;
 
-       if (!indio_dev->info || rb == NULL)
+       if (!indio_dev->info || !rb)
                return 0;
 
        poll_wait(filp, &rb->pollq, wait);
@@ -407,9 +407,9 @@ static ssize_t iio_scan_el_show(struct device *dev,
 
 /* Note NULL used as error indicator as it doesn't make sense. */
 static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks,
-                                         unsigned int masklength,
-                                         const unsigned long *mask,
-                                         bool strict)
+                                               unsigned int masklength,
+                                               const unsigned long *mask,
+                                               bool strict)
 {
        if (bitmap_empty(mask, masklength))
                return NULL;
@@ -427,7 +427,7 @@ static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks,
 }
 
 static bool iio_validate_scan_mask(struct iio_dev *indio_dev,
-       const unsigned long *mask)
+                                  const unsigned long *mask)
 {
        if (!indio_dev->setup_ops->validate_scan_mask)
                return true;
@@ -446,7 +446,7 @@ static bool iio_validate_scan_mask(struct iio_dev *indio_dev,
  * individual buffers request is plausible.
  */
 static int iio_scan_mask_set(struct iio_dev *indio_dev,
-                     struct iio_buffer *buffer, int bit)
+                            struct iio_buffer *buffer, int bit)
 {
        const unsigned long *mask;
        unsigned long *trialmask;
@@ -539,7 +539,6 @@ error_ret:
        mutex_unlock(&iio_dev_opaque->mlock);
 
        return ret < 0 ? ret : len;
-
 }
 
 static ssize_t iio_scan_el_ts_show(struct device *dev,
@@ -706,7 +705,7 @@ static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev)
 }
 
 static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
-                               const unsigned long *mask, bool timestamp)
+                                 const unsigned long *mask, bool timestamp)
 {
        unsigned int bytes = 0;
        int length, i, largest = 0;
@@ -732,7 +731,7 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
 }
 
 static void iio_buffer_activate(struct iio_dev *indio_dev,
-       struct iio_buffer *buffer)
+                               struct iio_buffer *buffer)
 {
        struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
 
@@ -753,12 +752,12 @@ static void iio_buffer_deactivate_all(struct iio_dev *indio_dev)
        struct iio_buffer *buffer, *_buffer;
 
        list_for_each_entry_safe(buffer, _buffer,
-                       &iio_dev_opaque->buffer_list, buffer_list)
+                                &iio_dev_opaque->buffer_list, buffer_list)
                iio_buffer_deactivate(buffer);
 }
 
 static int iio_buffer_enable(struct iio_buffer *buffer,
-       struct iio_dev *indio_dev)
+                            struct iio_dev *indio_dev)
 {
        if (!buffer->access->enable)
                return 0;
@@ -766,7 +765,7 @@ static int iio_buffer_enable(struct iio_buffer *buffer,
 }
 
 static int iio_buffer_disable(struct iio_buffer *buffer,
-       struct iio_dev *indio_dev)
+                             struct iio_dev *indio_dev)
 {
        if (!buffer->access->disable)
                return 0;
@@ -774,7 +773,7 @@ static int iio_buffer_disable(struct iio_buffer *buffer,
 }
 
 static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
-       struct iio_buffer *buffer)
+                                             struct iio_buffer *buffer)
 {
        unsigned int bytes;
 
@@ -782,13 +781,13 @@ static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
                return;
 
        bytes = iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
-               buffer->scan_timestamp);
+                                      buffer->scan_timestamp);
 
        buffer->access->set_bytes_per_datum(buffer, bytes);
 }
 
 static int iio_buffer_request_update(struct iio_dev *indio_dev,
-       struct iio_buffer *buffer)
+                                    struct iio_buffer *buffer)
 {
        int ret;
 
@@ -797,7 +796,7 @@ static int iio_buffer_request_update(struct iio_dev *indio_dev,
                ret = buffer->access->request_update(buffer);
                if (ret) {
                        dev_dbg(&indio_dev->dev,
-                              "Buffer not started: buffer parameter update failed (%d)\n",
+                               "Buffer not started: buffer parameter update failed (%d)\n",
                                ret);
                        return ret;
                }
@@ -807,7 +806,7 @@ static int iio_buffer_request_update(struct iio_dev *indio_dev,
 }
 
 static void iio_free_scan_mask(struct iio_dev *indio_dev,
-       const unsigned long *mask)
+                              const unsigned long *mask)
 {
        /* If the mask is dynamically allocated free it, otherwise do nothing */
        if (!indio_dev->available_scan_masks)
@@ -823,8 +822,9 @@ struct iio_device_config {
 };
 
 static int iio_verify_update(struct iio_dev *indio_dev,
-       struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer,
-       struct iio_device_config *config)
+                            struct iio_buffer *insert_buffer,
+                            struct iio_buffer *remove_buffer,
+                            struct iio_device_config *config)
 {
        struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        unsigned long *compound_mask;
@@ -864,7 +864,7 @@ static int iio_verify_update(struct iio_dev *indio_dev,
        if (insert_buffer) {
                modes &= insert_buffer->access->modes;
                config->watermark = min(config->watermark,
-                       insert_buffer->watermark);
+                                       insert_buffer->watermark);
        }
 
        /* Definitely possible for devices to support both of these. */
@@ -890,7 +890,7 @@ static int iio_verify_update(struct iio_dev *indio_dev,
 
        /* What scan mask do we actually have? */
        compound_mask = bitmap_zalloc(indio_dev->masklength, GFP_KERNEL);
-       if (compound_mask == NULL)
+       if (!compound_mask)
                return -ENOMEM;
 
        scan_timestamp = false;
@@ -911,18 +911,18 @@ static int iio_verify_update(struct iio_dev *indio_dev,
 
        if (indio_dev->available_scan_masks) {
                scan_mask = iio_scan_mask_match(indio_dev->available_scan_masks,
-                                   indio_dev->masklength,
-                                   compound_mask,
-                                   strict_scanmask);
+                                               indio_dev->masklength,
+                                               compound_mask,
+                                               strict_scanmask);
                bitmap_free(compound_mask);
-               if (scan_mask == NULL)
+               if (!scan_mask)
                        return -EINVAL;
        } else {
                scan_mask = compound_mask;
        }
 
        config->scan_bytes = iio_compute_scan_bytes(indio_dev,
-                                   scan_mask, scan_timestamp);
+                                                   scan_mask, scan_timestamp);
        config->scan_mask = scan_mask;
        config->scan_timestamp = scan_timestamp;
 
@@ -954,16 +954,16 @@ static void iio_buffer_demux_free(struct iio_buffer *buffer)
 }
 
 static int iio_buffer_add_demux(struct iio_buffer *buffer,
-       struct iio_demux_table **p, unsigned int in_loc, unsigned int out_loc,
-       unsigned int length)
+                               struct iio_demux_table **p, unsigned int in_loc,
+                               unsigned int out_loc,
+                               unsigned int length)
 {
-
        if (*p && (*p)->from + (*p)->length == in_loc &&
-               (*p)->to + (*p)->length == out_loc) {
+           (*p)->to + (*p)->length == out_loc) {
                (*p)->length += length;
        } else {
                *p = kmalloc(sizeof(**p), GFP_KERNEL);
-               if (*p == NULL)
+               if (!(*p))
                        return -ENOMEM;
                (*p)->from = in_loc;
                (*p)->to = out_loc;
@@ -1027,7 +1027,7 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev,
                out_loc += length;
        }
        buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL);
-       if (buffer->demux_bounce == NULL) {
+       if (!buffer->demux_bounce) {
                ret = -ENOMEM;
                goto error_clear_mux_table;
        }
@@ -1060,7 +1060,7 @@ error_clear_mux_table:
 }
 
 static int iio_enable_buffers(struct iio_dev *indio_dev,
-       struct iio_device_config *config)
+                             struct iio_device_config *config)
 {
        struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        struct iio_buffer *buffer, *tmp = NULL;
@@ -1078,7 +1078,7 @@ static int iio_enable_buffers(struct iio_dev *indio_dev,
                ret = indio_dev->setup_ops->preenable(indio_dev);
                if (ret) {
                        dev_dbg(&indio_dev->dev,
-                              "Buffer not started: buffer preenable failed (%d)\n", ret);
+                               "Buffer not started: buffer preenable failed (%d)\n", ret);
                        goto err_undo_config;
                }
        }
@@ -1118,7 +1118,7 @@ static int iio_enable_buffers(struct iio_dev *indio_dev,
                ret = indio_dev->setup_ops->postenable(indio_dev);
                if (ret) {
                        dev_dbg(&indio_dev->dev,
-                              "Buffer not started: postenable failed (%d)\n", ret);
+                               "Buffer not started: postenable failed (%d)\n", ret);
                        goto err_detach_pollfunc;
                }
        }
@@ -1194,15 +1194,15 @@ static int iio_disable_buffers(struct iio_dev *indio_dev)
 }
 
 static int __iio_update_buffers(struct iio_dev *indio_dev,
-                      struct iio_buffer *insert_buffer,
-                      struct iio_buffer *remove_buffer)
+                               struct iio_buffer *insert_buffer,
+                               struct iio_buffer *remove_buffer)
 {
        struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        struct iio_device_config new_config;
        int ret;
 
        ret = iio_verify_update(indio_dev, insert_buffer, remove_buffer,
-               &new_config);
+                               &new_config);
        if (ret)
                return ret;
 
@@ -1258,7 +1258,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
                return 0;
 
        if (insert_buffer &&
-           (insert_buffer->direction == IIO_BUFFER_DIRECTION_OUT))
+           insert_buffer->direction == IIO_BUFFER_DIRECTION_OUT)
                return -EINVAL;
 
        mutex_lock(&iio_dev_opaque->info_exist_lock);
@@ -1275,7 +1275,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
                goto out_unlock;
        }
 
-       if (indio_dev->info == NULL) {
+       if (!indio_dev->info) {
                ret = -ENODEV;
                goto out_unlock;
        }
@@ -1615,7 +1615,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
 
        buffer_attrcount = 0;
        if (buffer->attrs) {
-               while (buffer->attrs[buffer_attrcount] != NULL)
+               while (buffer->attrs[buffer_attrcount])
                        buffer_attrcount++;
        }
        buffer_attrcount += ARRAY_SIZE(iio_buffer_attrs);
@@ -1643,7 +1643,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
                        }
 
                        ret = iio_buffer_add_channel_sysfs(indio_dev, buffer,
-                                                        &channels[i]);
+                                                          &channels[i]);
                        if (ret < 0)
                                goto error_cleanup_dynamic;
                        scan_el_attrcount += ret;
@@ -1651,10 +1651,10 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
                                iio_dev_opaque->scan_index_timestamp =
                                        channels[i].scan_index;
                }
-               if (indio_dev->masklength && buffer->scan_mask == NULL) {
+               if (indio_dev->masklength && !buffer->scan_mask) {
                        buffer->scan_mask = bitmap_zalloc(indio_dev->masklength,
                                                          GFP_KERNEL);
-                       if (buffer->scan_mask == NULL) {
+                       if (!buffer->scan_mask) {
                                ret = -ENOMEM;
                                goto error_cleanup_dynamic;
                        }
@@ -1771,7 +1771,7 @@ int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
                        goto error_unwind_sysfs_and_mask;
        }
 
-       sz = sizeof(*(iio_dev_opaque->buffer_ioctl_handler));
+       sz = sizeof(*iio_dev_opaque->buffer_ioctl_handler);
        iio_dev_opaque->buffer_ioctl_handler = kzalloc(sz, GFP_KERNEL);
        if (!iio_dev_opaque->buffer_ioctl_handler) {
                ret = -ENOMEM;
@@ -1820,14 +1820,14 @@ void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev)
  * a time.
  */
 bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev,
-       const unsigned long *mask)
+                                  const unsigned long *mask)
 {
        return bitmap_weight(mask, indio_dev->masklength) == 1;
 }
 EXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot);
 
 static const void *iio_demux(struct iio_buffer *buffer,
-                                const void *datain)
+                            const void *datain)
 {
        struct iio_demux_table *t;
 
index 8bb68975b2598a48682af26d798b0af9340de311..7653261d2dc2bf4cb916f9ca30b239261597a018 100644 (file)
@@ -337,6 +337,17 @@ free_gains:
        return ret;
 }
 
+static void iio_gts_us_to_int_micro(int *time_us, int *int_micro_times,
+                                   int num_times)
+{
+       int i;
+
+       for (i = 0; i < num_times; i++) {
+               int_micro_times[i * 2] = time_us[i] / 1000000;
+               int_micro_times[i * 2 + 1] = time_us[i] % 1000000;
+       }
+}
+
 /**
  * iio_gts_build_avail_time_table - build table of available integration times
  * @gts:       Gain time scale descriptor
@@ -351,7 +362,7 @@ free_gains:
  */
 static int iio_gts_build_avail_time_table(struct iio_gts *gts)
 {
-       int *times, i, j, idx = 0;
+       int *times, i, j, idx = 0, *int_micro_times;
 
        if (!gts->num_itime)
                return 0;
@@ -378,13 +389,24 @@ static int iio_gts_build_avail_time_table(struct iio_gts *gts)
                        }
                }
        }
-       gts->avail_time_tables = times;
-       /*
-        * This is just to survive a unlikely corner-case where times in the
-        * given time table were not unique. Else we could just trust the
-        * gts->num_itime.
-        */
-       gts->num_avail_time_tables = idx;
+
+       /* create a list of times formatted as list of IIO_VAL_INT_PLUS_MICRO */
+       int_micro_times = kcalloc(idx, sizeof(int) * 2, GFP_KERNEL);
+       if (int_micro_times) {
+               /*
+                * This is just to survive a unlikely corner-case where times in
+                * the given time table were not unique. Else we could just
+                * trust the gts->num_itime.
+                */
+               gts->num_avail_time_tables = idx;
+               iio_gts_us_to_int_micro(times, int_micro_times, idx);
+       }
+
+       gts->avail_time_tables = int_micro_times;
+       kfree(times);
+
+       if (!int_micro_times)
+               return -ENOMEM;
 
        return 0;
 }
@@ -683,8 +705,8 @@ int iio_gts_avail_times(struct iio_gts *gts,  const int **vals, int *type,
                return -EINVAL;
 
        *vals = gts->avail_time_tables;
-       *type = IIO_VAL_INT;
-       *length = gts->num_avail_time_tables;
+       *type = IIO_VAL_INT_PLUS_MICRO;
+       *length = gts->num_avail_time_tables * 2;
 
        return IIO_AVAIL_LIST;
 }
index 784dc1e00310b987174ddf59b8b7f1c0e4e1445f..f207e36b12cc9df59649da75fb3f120a0e604572 100644 (file)
@@ -322,7 +322,7 @@ int iio_trigger_attach_poll_func(struct iio_trigger *trig,
         * this is the case if the IIO device and the trigger device share the
         * same parent device.
         */
-       if (pf->indio_dev->dev.parent == trig->dev.parent)
+       if (iio_validate_own_trigger(pf->indio_dev, trig))
                trig->attached_own_device = true;
 
        return ret;
@@ -728,6 +728,26 @@ bool iio_trigger_using_own(struct iio_dev *indio_dev)
 }
 EXPORT_SYMBOL(iio_trigger_using_own);
 
+/**
+ * iio_validate_own_trigger - Check if a trigger and IIO device belong to
+ *  the same device
+ * @idev: the IIO device to check
+ * @trig: the IIO trigger to check
+ *
+ * This function can be used as the validate_trigger callback for triggers that
+ * can only be attached to their own device.
+ *
+ * Return: 0 if both the trigger and the IIO device belong to the same
+ * device, -EINVAL otherwise.
+ */
+int iio_validate_own_trigger(struct iio_dev *idev, struct iio_trigger *trig)
+{
+       if (idev->dev.parent != trig->dev.parent)
+               return -EINVAL;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(iio_validate_own_trigger);
+
 /**
  * iio_trigger_validate_own_device - Check if a trigger and IIO device belong to
  *  the same device
index 6fa31fcd71a17fff4b396d158dca91a6964159d0..45edba797e4c7e9dfd89e43a250ac5dddffa215c 100644 (file)
@@ -289,6 +289,20 @@ config JSA1212
          To compile this driver as a module, choose M here:
          the module will be called jsa1212.
 
+config ROHM_BU27008
+       tristate "ROHM BU27008 color (RGB+C/IR) sensor"
+       depends on I2C
+       select REGMAP_I2C
+       select IIO_GTS_HELPER
+       help
+         Enable support for the ROHM BU27008 color sensor.
+         The ROHM BU27008 is a sensor with 5 photodiodes (red, green,
+         blue, clear and IR) with four configurable channels. Red and
+         green being always available and two out of the rest three
+         (blue, clear, IR) can be selected to be simultaneously measured.
+         Typical application is adjusting LCD backlight of TVs,
+         mobile phones and tablet PCs.
+
 config ROHM_BU27034
        tristate "ROHM BU27034 ambient light sensor"
        depends on I2C
@@ -413,6 +427,17 @@ config OPT3001
          If built as a dynamically linked module, it will be called
          opt3001.
 
+config OPT4001
+       tristate "Texas Instruments OPT4001 Light Sensor"
+       depends on I2C
+       select REGMAP_I2C
+       help
+         If you say Y or M here, you get support for Texas Instruments
+         OPT4001 Ambient Light Sensor.
+
+         If built as a dynamically linked module, it will be called
+         opt4001.
+
 config PA12203001
        tristate "TXC PA12203001 light and proximity sensor"
        depends on I2C
index 985f6feaccd4fc3cea4d9146d6785ec818ab1540..c0db4c4c36ec9f1ed9aefeb02fb583b94e361874 100644 (file)
@@ -37,7 +37,9 @@ obj-$(CONFIG_MAX44000)                += max44000.o
 obj-$(CONFIG_MAX44009)         += max44009.o
 obj-$(CONFIG_NOA1305)          += noa1305.o
 obj-$(CONFIG_OPT3001)          += opt3001.o
+obj-$(CONFIG_OPT4001)          += opt4001.o
 obj-$(CONFIG_PA12203001)       += pa12203001.o
+obj-$(CONFIG_ROHM_BU27008)     += rohm-bu27008.o
 obj-$(CONFIG_ROHM_BU27034)     += rohm-bu27034.o
 obj-$(CONFIG_RPR0521)          += rpr0521.o
 obj-$(CONFIG_SI1133)           += si1133.o
index 210a90f44c5323d2cccb635fd38e5ceece6233ab..5fd775a20176dbc3debffd1e9b9f0538869c684e 100644 (file)
@@ -270,7 +270,7 @@ static struct i2c_driver adjd_s311_driver = {
        .driver = {
                .name   = ADJD_S311_DRV_NAME,
        },
-       .probe_new      = adjd_s311_probe,
+       .probe          = adjd_s311_probe,
        .id_table       = adjd_s311_id,
 };
 module_i2c_driver(adjd_s311_driver);
index 606075350d01c559ea5ceee132855b5f2d5db05d..aa4a6c78f0aa86476fd0d26120e80542b6113f18 100644 (file)
@@ -837,7 +837,7 @@ static struct i2c_driver adux1020_driver = {
                .name   = ADUX1020_DRV_NAME,
                .of_match_table = adux1020_of_match,
        },
-       .probe_new      = adux1020_probe,
+       .probe          = adux1020_probe,
        .id_table       = adux1020_id,
 };
 module_i2c_driver(adux1020_driver);
index 69cc723e2ac4ad6b9b36d50f0f8d1f1f5493b093..8f0119f392b7051ce07abc746d7fdaf2e56c082f 100644 (file)
@@ -229,7 +229,7 @@ static struct i2c_driver al3010_driver = {
                .of_match_table = al3010_of_match,
                .pm = pm_sleep_ptr(&al3010_pm_ops),
        },
-       .probe_new      = al3010_probe,
+       .probe          = al3010_probe,
        .id_table       = al3010_id,
 };
 module_i2c_driver(al3010_driver);
index 9ff28bbf34bbed0d8d6ec71b1f63b2d25a008178..d5957d85c27866e1997c7372425f0f75e80b0951 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/mod_devicetable.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -247,13 +248,20 @@ static const struct of_device_id al3320a_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, al3320a_of_match);
 
+static const struct acpi_device_id al3320a_acpi_match[] = {
+       {"CALS0001"},
+       { },
+};
+MODULE_DEVICE_TABLE(acpi, al3320a_acpi_match);
+
 static struct i2c_driver al3320a_driver = {
        .driver = {
                .name = AL3320A_DRV_NAME,
                .of_match_table = al3320a_of_match,
                .pm = pm_sleep_ptr(&al3320a_pm_ops),
+               .acpi_match_table = al3320a_acpi_match,
        },
-       .probe_new      = al3320a_probe,
+       .probe          = al3320a_probe,
        .id_table       = al3320a_id,
 };
 
index 15dfb753734fa0ceea947128a39274eec166862e..0f978b30a232ca8f8c1462fa5382b0cda22b6abd 100644 (file)
@@ -504,7 +504,7 @@ static struct i2c_driver apds9300_driver = {
                .name   = APDS9300_DRV_NAME,
                .pm     = pm_sleep_ptr(&apds9300_pm_ops),
        },
-       .probe_new      = apds9300_probe,
+       .probe          = apds9300_probe,
        .remove         = apds9300_remove,
        .id_table       = apds9300_id,
 };
index cc5974a95bd3364995a991bd91edeea1dfacd7b2..1065a340b12bf9cb6984e9b95d711435e5c5a5a2 100644 (file)
@@ -1131,7 +1131,7 @@ static struct i2c_driver apds9960_driver = {
                .pm     = &apds9960_pm_ops,
                .acpi_match_table = apds9960_acpi_match,
        },
-       .probe_new      = apds9960_probe,
+       .probe          = apds9960_probe,
        .remove         = apds9960_remove,
        .id_table       = apds9960_id,
 };
index 2307fc531752ba414403eddaa85d9c31d8cd28ff..ec97a3a468392d8b79207546d60114d2f85c98c1 100644 (file)
@@ -790,7 +790,7 @@ static struct i2c_driver as73211_driver = {
                .of_match_table = as73211_of_match,
                .pm             = pm_sleep_ptr(&as73211_pm_ops),
        },
-       .probe_new  = as73211_probe,
+       .probe      = as73211_probe,
        .id_table   = as73211_id,
 };
 module_i2c_driver(as73211_driver);
index 390c5b3ad4f6717ee3bb29bff44b6441c49c3921..4b869fa9e5b17ed179b2c357fff1cb244e9172f2 100644 (file)
@@ -320,7 +320,7 @@ static struct i2c_driver bh1750_driver = {
                .of_match_table = bh1750_of_match,
                .pm = pm_sleep_ptr(&bh1750_pm_ops),
        },
-       .probe_new = bh1750_probe,
+       .probe = bh1750_probe,
        .remove = bh1750_remove,
        .id_table = bh1750_id,
 
index da9039e5a83918f364b00f9f761e1da2c4a0e071..b84166c5fa06eec1287856159ea1a7dd49fc587e 100644 (file)
@@ -269,7 +269,7 @@ static const struct of_device_id of_bh1780_match[] = {
 MODULE_DEVICE_TABLE(of, of_bh1780_match);
 
 static struct i2c_driver bh1780_driver = {
-       .probe_new      = bh1780_probe,
+       .probe          = bh1780_probe,
        .remove         = bh1780_remove,
        .id_table       = bh1780_id,
        .driver = {
index d4a34a3bf00d9503fbeff879f1a86278ad159d4e..9df85b3999fa88e4e7e0a6c2692de1ea748bb82b 100644 (file)
@@ -542,7 +542,7 @@ static struct i2c_driver cm32181_driver = {
                .of_match_table = cm32181_of_match,
                .pm = pm_sleep_ptr(&cm32181_pm_ops),
        },
-       .probe_new      = cm32181_probe,
+       .probe          = cm32181_probe,
 };
 
 module_i2c_driver(cm32181_driver);
index 43e492f5051d1718a6e0daa6e8947ea800ffa5a7..d48a70efca69ff87d70a93630a13a96f9ed00af2 100644 (file)
@@ -417,7 +417,7 @@ static struct i2c_driver cm3232_driver = {
                .pm     = pm_sleep_ptr(&cm3232_pm_ops),
        },
        .id_table       = cm3232_id,
-       .probe_new      = cm3232_probe,
+       .probe          = cm3232_probe,
        .remove         = cm3232_remove,
 };
 
index e5ce7d0fd272e0f629e757541eff9b053a23ec27..35d20207a6481aa39eed6ab2fc1b0b5350c6d2ed 100644 (file)
@@ -266,7 +266,7 @@ static struct i2c_driver cm3323_driver = {
                .name = CM3323_DRV_NAME,
                .of_match_table = cm3323_of_match,
        },
-       .probe_new      = cm3323_probe,
+       .probe          = cm3323_probe,
        .id_table       = cm3323_id,
 };
 
index 1707dbf2ce26784b5f62f1c7542de17d37717e32..97e559acba2b25947a2cfcb1e7e55d91dfbaaa1a 100644 (file)
@@ -730,7 +730,7 @@ static struct i2c_driver cm36651_driver = {
                .name   = "cm36651",
                .of_match_table = cm36651_of_match,
        },
-       .probe_new      = cm36651_probe,
+       .probe          = cm36651_probe,
        .remove         = cm36651_remove,
        .id_table       = cm36651_id,
 };
index c0430db0038afde7db8fde3a5ca98ca27a355b05..fec10d5e037ec1739d0756d2b1e23212557702a6 100644 (file)
@@ -710,7 +710,7 @@ static struct i2c_driver gp2ap002_driver = {
                .of_match_table = gp2ap002_of_match,
                .pm = pm_ptr(&gp2ap002_dev_pm_ops),
        },
-       .probe_new = gp2ap002_probe,
+       .probe = gp2ap002_probe,
        .remove = gp2ap002_remove,
        .id_table = gp2ap002_id_table,
 };
index a5bf9da0d2f38f0335121b303b689e70545930fa..9f41724819b61260558d2368c65ea94ea1316b34 100644 (file)
@@ -1609,7 +1609,7 @@ static struct i2c_driver gp2ap020a00f_driver = {
                .name   = GP2A_I2C_NAME,
                .of_match_table = gp2ap020a00f_of_match,
        },
-       .probe_new      = gp2ap020a00f_probe,
+       .probe          = gp2ap020a00f_probe,
        .remove         = gp2ap020a00f_remove,
        .id_table       = gp2ap020a00f_id,
 };
index 141845fb47f960e427c180c71dac9c5eeab35511..43484c18b1014237af9bd1e44086d2568bea338a 100644 (file)
@@ -865,7 +865,7 @@ static struct i2c_driver isl29018_driver = {
                        .pm = pm_sleep_ptr(&isl29018_pm_ops),
                        .of_match_table = isl29018_of_match,
                    },
-       .probe_new = isl29018_probe,
+       .probe = isl29018_probe,
        .id_table = isl29018_id,
 };
 module_i2c_driver(isl29018_driver);
index bcf3a556e41ad711b8bbc279ae5a991086c31078..5694683389bec1c20f8fcc020f2971370ad19fa4 100644 (file)
@@ -698,7 +698,7 @@ static struct i2c_driver isl29028_driver = {
                .pm = pm_ptr(&isl29028_pm_ops),
                .of_match_table = isl29028_of_match,
        },
-       .probe_new = isl29028_probe,
+       .probe = isl29028_probe,
        .remove  = isl29028_remove,
        .id_table = isl29028_id,
 };
index b4bd656ca16984459c1074c908c32ecc0cdd63cf..f1d3356d33697a4e4e24c57f593525d3038e216d 100644 (file)
@@ -337,7 +337,7 @@ static struct i2c_driver isl29125_driver = {
                .name   = ISL29125_DRV_NAME,
                .pm     = pm_sleep_ptr(&isl29125_pm_ops),
        },
-       .probe_new      = isl29125_probe,
+       .probe          = isl29125_probe,
        .remove         = isl29125_remove,
        .id_table       = isl29125_id,
 };
index d3834d0a0635aa034feb743fe4a90d900a9113c2..37e2807041a1dd3ca8fd90fb9daee73cbeb3b6a6 100644 (file)
@@ -440,7 +440,7 @@ static struct i2c_driver jsa1212_driver = {
                .pm     = pm_sleep_ptr(&jsa1212_pm_ops),
                .acpi_match_table = ACPI_PTR(jsa1212_acpi_match),
        },
-       .probe_new      = jsa1212_probe,
+       .probe          = jsa1212_probe,
        .remove         = jsa1212_remove,
        .id_table       = jsa1212_id,
 };
index bdbd918213e45cfc402e1afcab88397c33796485..061c122fdc5e70f5c0e2f3abef1386536202cedf 100644 (file)
@@ -1641,7 +1641,7 @@ static struct i2c_driver ltr501_driver = {
                .pm     = pm_sleep_ptr(&ltr501_pm_ops),
                .acpi_match_table = ACPI_PTR(ltr_acpi_match),
        },
-       .probe_new = ltr501_probe,
+       .probe = ltr501_probe,
        .remove = ltr501_remove,
        .id_table = ltr501_id,
 };
index 4b8ef36b691251f826b987784e63fb448d6add4c..8de4dd849936d403684159eb4a5e26698963e666 100644 (file)
@@ -539,7 +539,7 @@ static struct i2c_driver ltrf216a_driver = {
                .pm = pm_ptr(&ltrf216a_pm_ops),
                .of_match_table = ltrf216a_of_match,
        },
-       .probe_new = ltrf216a_probe,
+       .probe = ltrf216a_probe,
        .id_table = ltrf216a_id,
 };
 module_i2c_driver(ltrf216a_driver);
index c041fa0faa5df61cf0720fb02963a23eee29b105..a5445d58fddfc3a5c13b3f28f31e7f5ee843600d 100644 (file)
@@ -520,7 +520,7 @@ static struct i2c_driver lv0104cs_i2c_driver = {
                .name   = "lv0104cs",
        },
        .id_table       = lv0104cs_id,
-       .probe_new      = lv0104cs_probe,
+       .probe          = lv0104cs_probe,
 };
 module_i2c_driver(lv0104cs_i2c_driver);
 
index 5dcabc43a30e6e3694f505180ae614cc8ea8325f..db96c5b73100c6047f3a9a3f6f18240f6217e70f 100644 (file)
@@ -616,7 +616,7 @@ static struct i2c_driver max44000_driver = {
                .name   = MAX44000_DRV_NAME,
                .acpi_match_table = ACPI_PTR(max44000_acpi_match),
        },
-       .probe_new      = max44000_probe,
+       .probe          = max44000_probe,
        .id_table       = max44000_id,
 };
 
index 176dcad6e8e8a31d5616196be9b33627012a3aad..61ce276e86f7c242043eed65d8644dac7fb81126 100644 (file)
@@ -544,7 +544,7 @@ static struct i2c_driver max44009_driver = {
                .name = MAX44009_DRV_NAME,
                .of_match_table = max44009_of_match,
        },
-       .probe_new = max44009_probe,
+       .probe = max44009_probe,
        .id_table = max44009_id,
 };
 module_i2c_driver(max44009_driver);
index eaf548d4649ea9ea811e2d718c27fcdf73a47548..1574310020e3d5e7a8ee0fee2c2356fa77bea6d1 100644 (file)
@@ -278,7 +278,7 @@ static struct i2c_driver noa1305_driver = {
                .name           = NOA1305_DRIVER_NAME,
                .of_match_table = noa1305_of_match,
        },
-       .probe_new      = noa1305_probe,
+       .probe          = noa1305_probe,
        .id_table       = noa1305_ids,
 };
 
index ec4f5c2369c42640a2de69a026a6df6f4dba745c..cb41e5ee8ec10baa23d0bc9175656e035a4cad65 100644 (file)
@@ -834,7 +834,7 @@ static const struct of_device_id opt3001_of_match[] = {
 MODULE_DEVICE_TABLE(of, opt3001_of_match);
 
 static struct i2c_driver opt3001_driver = {
-       .probe_new = opt3001_probe,
+       .probe = opt3001_probe,
        .remove = opt3001_remove,
        .id_table = opt3001_id,
 
diff --git a/drivers/iio/light/opt4001.c b/drivers/iio/light/opt4001.c
new file mode 100644 (file)
index 0000000..502946b
--- /dev/null
@@ -0,0 +1,467 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Axis Communications AB
+ *
+ * Datasheet: https://www.ti.com/lit/gpn/opt4001
+ *
+ * Device driver for the Texas Instruments OPT4001.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+/* OPT4001 register set */
+#define OPT4001_LIGHT1_MSB    0x00
+#define OPT4001_LIGHT1_LSB    0x01
+#define OPT4001_CTRL          0x0A
+#define OPT4001_DEVICE_ID     0x11
+
+/* OPT4001 register mask */
+#define OPT4001_EXPONENT_MASK    GENMASK(15, 12)
+#define OPT4001_MSB_MASK         GENMASK(11, 0)
+#define OPT4001_LSB_MASK         GENMASK(15, 8)
+#define OPT4001_COUNTER_MASK     GENMASK(7, 4)
+#define OPT4001_CRC_MASK         GENMASK(3, 0)
+
+/* OPT4001 device id mask */
+#define OPT4001_DEVICE_ID_MASK   GENMASK(11, 0)
+
+/* OPT4001 control registers mask */
+#define OPT4001_CTRL_QWAKE_MASK          GENMASK(15, 15)
+#define OPT4001_CTRL_RANGE_MASK          GENMASK(13, 10)
+#define OPT4001_CTRL_CONV_TIME_MASK      GENMASK(9, 6)
+#define OPT4001_CTRL_OPER_MODE_MASK      GENMASK(5, 4)
+#define OPT4001_CTRL_LATCH_MASK          GENMASK(3, 3)
+#define OPT4001_CTRL_INT_POL_MASK        GENMASK(2, 2)
+#define OPT4001_CTRL_FAULT_COUNT         GENMASK(0, 1)
+
+/* OPT4001 constants */
+#define OPT4001_DEVICE_ID_VAL            0x121
+
+/* OPT4001 operating modes */
+#define OPT4001_CTRL_OPER_MODE_OFF        0x0
+#define OPT4001_CTRL_OPER_MODE_FORCED     0x1
+#define OPT4001_CTRL_OPER_MODE_ONE_SHOT   0x2
+#define OPT4001_CTRL_OPER_MODE_CONTINUOUS 0x3
+
+/* OPT4001 conversion control register definitions */
+#define OPT4001_CTRL_CONVERSION_0_6MS   0x0
+#define OPT4001_CTRL_CONVERSION_1MS     0x1
+#define OPT4001_CTRL_CONVERSION_1_8MS   0x2
+#define OPT4001_CTRL_CONVERSION_3_4MS   0x3
+#define OPT4001_CTRL_CONVERSION_6_5MS   0x4
+#define OPT4001_CTRL_CONVERSION_12_7MS  0x5
+#define OPT4001_CTRL_CONVERSION_25MS    0x6
+#define OPT4001_CTRL_CONVERSION_50MS    0x7
+#define OPT4001_CTRL_CONVERSION_100MS   0x8
+#define OPT4001_CTRL_CONVERSION_200MS   0x9
+#define OPT4001_CTRL_CONVERSION_400MS   0xa
+#define OPT4001_CTRL_CONVERSION_800MS   0xb
+
+/* OPT4001 scale light level range definitions */
+#define OPT4001_CTRL_LIGHT_SCALE_AUTO   12
+
+/* OPT4001 default values */
+#define OPT4001_DEFAULT_CONVERSION_TIME OPT4001_CTRL_CONVERSION_800MS
+
+/*
+ * The different packaging of OPT4001 has different constants used when calculating
+ * lux values.
+ */
+struct opt4001_chip_info {
+       int mul;
+       int div;
+       const char *name;
+};
+
+struct opt4001_chip {
+       struct regmap *regmap;
+       struct i2c_client *client;
+       u8 int_time;
+       const struct opt4001_chip_info *chip_info;
+};
+
+static const struct opt4001_chip_info opt4001_sot_5x3_info = {
+       .mul = 4375,
+       .div = 10000000,
+       .name = "opt4001-sot-5x3"
+};
+
+static const struct opt4001_chip_info opt4001_picostar_info = {
+       .mul = 3125,
+       .div = 10000000,
+       .name = "opt4001-picostar"
+};
+
+static const int opt4001_int_time_available[][2] = {
+       { 0,    600 },
+       { 0,   1000 },
+       { 0,   1800 },
+       { 0,   3400 },
+       { 0,   6500 },
+       { 0,  12700 },
+       { 0,  25000 },
+       { 0,  50000 },
+       { 0, 100000 },
+       { 0, 200000 },
+       { 0, 400000 },
+       { 0, 800000 },
+};
+
+/*
+ * Conversion time is integration time + time to set register
+ * this is used as integration time.
+ */
+static const int opt4001_int_time_reg[][2] = {
+       {    600,  OPT4001_CTRL_CONVERSION_0_6MS  },
+       {   1000,  OPT4001_CTRL_CONVERSION_1MS    },
+       {   1800,  OPT4001_CTRL_CONVERSION_1_8MS  },
+       {   3400,  OPT4001_CTRL_CONVERSION_3_4MS  },
+       {   6500,  OPT4001_CTRL_CONVERSION_6_5MS  },
+       {  12700,  OPT4001_CTRL_CONVERSION_12_7MS },
+       {  25000,  OPT4001_CTRL_CONVERSION_25MS   },
+       {  50000,  OPT4001_CTRL_CONVERSION_50MS   },
+       { 100000,  OPT4001_CTRL_CONVERSION_100MS  },
+       { 200000,  OPT4001_CTRL_CONVERSION_200MS  },
+       { 400000,  OPT4001_CTRL_CONVERSION_400MS  },
+       { 800000,  OPT4001_CTRL_CONVERSION_800MS  },
+};
+
+static int opt4001_als_time_to_index(const u32 als_integration_time)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(opt4001_int_time_available); i++) {
+               if (als_integration_time == opt4001_int_time_available[i][1])
+                       return i;
+       }
+
+       return -EINVAL;
+}
+
+static u8 opt4001_calculate_crc(u8 exp, u32 mantissa, u8 count)
+{
+       u8 crc;
+
+       crc = (hweight32(mantissa) + hweight32(exp) + hweight32(count)) % 2;
+       crc |= ((hweight32(mantissa & 0xAAAAA) + hweight32(exp & 0xA)
+                + hweight32(count & 0xA)) % 2) << 1;
+       crc |= ((hweight32(mantissa & 0x88888) + hweight32(exp & 0x8)
+                + hweight32(count & 0x8)) % 2) << 2;
+       crc |= (hweight32(mantissa & 0x80808) % 2) << 3;
+
+       return crc;
+}
+
+static int opt4001_read_lux_value(struct iio_dev *indio_dev,
+                                 int *val, int *val2)
+{
+       struct opt4001_chip *chip = iio_priv(indio_dev);
+       struct device *dev = &chip->client->dev;
+       unsigned int light1;
+       unsigned int light2;
+       u16 msb;
+       u16 lsb;
+       u8 exp;
+       u8 count;
+       u8 crc;
+       u8 calc_crc;
+       u64 lux_raw;
+       int ret;
+
+       ret = regmap_read(chip->regmap, OPT4001_LIGHT1_MSB, &light1);
+       if (ret < 0) {
+               dev_err(dev, "Failed to read data bytes");
+               return ret;
+       }
+
+       ret = regmap_read(chip->regmap, OPT4001_LIGHT1_LSB, &light2);
+       if (ret < 0) {
+               dev_err(dev, "Failed to read data bytes");
+               return ret;
+       }
+
+       count = FIELD_GET(OPT4001_COUNTER_MASK, light2);
+       exp = FIELD_GET(OPT4001_EXPONENT_MASK, light1);
+       crc = FIELD_GET(OPT4001_CRC_MASK, light2);
+       msb = FIELD_GET(OPT4001_MSB_MASK, light1);
+       lsb = FIELD_GET(OPT4001_LSB_MASK, light2);
+       lux_raw = (msb << 8) + lsb;
+       calc_crc = opt4001_calculate_crc(exp, lux_raw, count);
+       if (calc_crc != crc)
+               return -EIO;
+
+       lux_raw = lux_raw << exp;
+       lux_raw = lux_raw * chip->chip_info->mul;
+       *val = div_u64_rem(lux_raw, chip->chip_info->div, val2);
+       *val2 = *val2 * 100;
+
+       return IIO_VAL_INT_PLUS_NANO;
+}
+
+static int opt4001_set_conf(struct opt4001_chip *chip)
+{
+       struct device *dev = &chip->client->dev;
+       u16 reg;
+       int ret;
+
+       reg = FIELD_PREP(OPT4001_CTRL_RANGE_MASK, OPT4001_CTRL_LIGHT_SCALE_AUTO);
+       reg |= FIELD_PREP(OPT4001_CTRL_CONV_TIME_MASK, chip->int_time);
+       reg |= FIELD_PREP(OPT4001_CTRL_OPER_MODE_MASK, OPT4001_CTRL_OPER_MODE_CONTINUOUS);
+
+       ret = regmap_write(chip->regmap, OPT4001_CTRL, reg);
+       if (ret)
+               dev_err(dev, "Failed to set configuration\n");
+
+       return ret;
+}
+
+static int opt4001_power_down(struct opt4001_chip *chip)
+{
+       struct device *dev = &chip->client->dev;
+       int ret;
+       unsigned int reg;
+
+       ret = regmap_read(chip->regmap, OPT4001_DEVICE_ID, &reg);
+       if (ret) {
+               dev_err(dev, "Failed to read configuration\n");
+               return ret;
+       }
+
+       /* MODE_OFF is 0x0 so just set bits to 0 */
+       reg &= ~OPT4001_CTRL_OPER_MODE_MASK;
+
+       ret = regmap_write(chip->regmap, OPT4001_CTRL, reg);
+       if (ret)
+               dev_err(dev, "Failed to set configuration to power down\n");
+
+       return ret;
+}
+
+static void opt4001_chip_off_action(void *data)
+{
+       struct opt4001_chip *chip = data;
+
+       opt4001_power_down(chip);
+}
+
+static const struct iio_chan_spec opt4001_channels[] = {
+       {
+               .type = IIO_LIGHT,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+               .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
+               .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME)
+       },
+};
+
+static int opt4001_read_raw(struct iio_dev *indio_dev,
+                           struct iio_chan_spec const *chan,
+                           int *val, int *val2, long mask)
+{
+       struct opt4001_chip *chip = iio_priv(indio_dev);
+
+       switch (mask) {
+       case IIO_CHAN_INFO_PROCESSED:
+               return opt4001_read_lux_value(indio_dev, val, val2);
+       case IIO_CHAN_INFO_INT_TIME:
+               *val = 0;
+               *val2 = opt4001_int_time_reg[chip->int_time][0];
+               return IIO_VAL_INT_PLUS_MICRO;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int opt4001_write_raw(struct iio_dev *indio_dev,
+                            struct iio_chan_spec const *chan,
+                            int val, int val2, long mask)
+{
+       struct opt4001_chip *chip = iio_priv(indio_dev);
+       int int_time;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_INT_TIME:
+               int_time = opt4001_als_time_to_index(val2);
+               if (int_time < 0)
+                       return int_time;
+               chip->int_time = int_time;
+               return opt4001_set_conf(chip);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int opt4001_read_available(struct iio_dev *indio_dev,
+                                 struct iio_chan_spec const *chan,
+                                 const int **vals, int *type, int *length,
+                                 long mask)
+{
+       switch (mask) {
+       case IIO_CHAN_INFO_INT_TIME:
+               *length = ARRAY_SIZE(opt4001_int_time_available) * 2;
+               *vals = (const int *)opt4001_int_time_available;
+               *type = IIO_VAL_INT_PLUS_MICRO;
+               return IIO_AVAIL_LIST;
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static const struct iio_info opt4001_info_no_irq = {
+       .read_raw = opt4001_read_raw,
+       .write_raw = opt4001_write_raw,
+       .read_avail = opt4001_read_available,
+};
+
+static int opt4001_load_defaults(struct opt4001_chip *chip)
+{
+       chip->int_time = OPT4001_DEFAULT_CONVERSION_TIME;
+
+       return opt4001_set_conf(chip);
+}
+
+static bool opt4001_readable_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case OPT4001_LIGHT1_MSB:
+       case OPT4001_LIGHT1_LSB:
+       case OPT4001_CTRL:
+       case OPT4001_DEVICE_ID:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool opt4001_writable_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case OPT4001_CTRL:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool opt4001_volatile_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case OPT4001_LIGHT1_MSB:
+       case OPT4001_LIGHT1_LSB:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static const struct regmap_config opt4001_regmap_config = {
+       .name = "opt4001",
+       .reg_bits = 8,
+       .val_bits = 16,
+       .cache_type = REGCACHE_RBTREE,
+       .max_register = OPT4001_DEVICE_ID,
+       .readable_reg = opt4001_readable_reg,
+       .writeable_reg = opt4001_writable_reg,
+       .volatile_reg = opt4001_volatile_reg,
+       .val_format_endian = REGMAP_ENDIAN_BIG,
+};
+
+static int opt4001_probe(struct i2c_client *client)
+{
+       struct opt4001_chip *chip;
+       struct iio_dev *indio_dev;
+       int ret;
+       uint dev_id;
+
+       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       chip = iio_priv(indio_dev);
+
+       ret = devm_regulator_get_enable(&client->dev, "vdd");
+       if (ret)
+               return dev_err_probe(&client->dev, ret, "Failed to enable vdd supply\n");
+
+       chip->regmap = devm_regmap_init_i2c(client, &opt4001_regmap_config);
+       if (IS_ERR(chip->regmap))
+               return dev_err_probe(&client->dev, PTR_ERR(chip->regmap),
+                                    "regmap initialization failed\n");
+       chip->client = client;
+
+       indio_dev->info = &opt4001_info_no_irq;
+
+       ret = regmap_reinit_cache(chip->regmap, &opt4001_regmap_config);
+       if (ret)
+               return dev_err_probe(&client->dev, ret,
+                                    "failed to reinit regmap cache\n");
+
+       ret = regmap_read(chip->regmap, OPT4001_DEVICE_ID, &dev_id);
+       if (ret < 0)
+               return dev_err_probe(&client->dev, ret,
+                       "Failed to read the device ID register\n");
+
+       dev_id = FIELD_GET(OPT4001_DEVICE_ID_MASK, dev_id);
+       if (dev_id != OPT4001_DEVICE_ID_VAL)
+               dev_warn(&client->dev, "Device ID: %#04x unknown\n", dev_id);
+
+       chip->chip_info = device_get_match_data(&client->dev);
+
+       indio_dev->channels = opt4001_channels;
+       indio_dev->num_channels = ARRAY_SIZE(opt4001_channels);
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->name = chip->chip_info->name;
+
+       ret = opt4001_load_defaults(chip);
+       if (ret < 0)
+               return dev_err_probe(&client->dev, ret,
+                                    "Failed to set sensor defaults\n");
+
+       ret = devm_add_action_or_reset(&client->dev,
+                                       opt4001_chip_off_action,
+                                       chip);
+       if (ret < 0)
+               return dev_err_probe(&client->dev, ret,
+                                    "Failed to setup power off action\n");
+
+       return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+/*
+ * The compatible string determines which constants to use depending on
+ * opt4001 packaging
+ */
+static const struct i2c_device_id opt4001_id[] = {
+       { "opt4001-sot-5x3", (kernel_ulong_t)&opt4001_sot_5x3_info },
+       { "opt4001-picostar", (kernel_ulong_t)&opt4001_picostar_info },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, opt4001_id);
+
+static const struct of_device_id opt4001_of_match[] = {
+       { .compatible = "ti,opt4001-sot-5x3", .data = &opt4001_sot_5x3_info},
+       { .compatible = "ti,opt4001-picostar", .data = &opt4001_picostar_info},
+       {}
+};
+MODULE_DEVICE_TABLE(of, opt4001_of_match);
+
+static struct i2c_driver opt4001_driver = {
+       .driver = {
+               .name = "opt4001",
+               .of_match_table = opt4001_of_match,
+       },
+       .probe = opt4001_probe,
+       .id_table = opt4001_id,
+};
+module_i2c_driver(opt4001_driver);
+
+MODULE_AUTHOR("Stefan Windfeldt-Prytz <stefan.windfeldt-prytz@axis.com>");
+MODULE_DESCRIPTION("Texas Instruments opt4001 ambient light sensor driver");
+MODULE_LICENSE("GPL");
index 15a666f15c275f23f44390c2807efcd75aedde83..ed241598aefbe41c7b70f648e8df8c13e01140a3 100644 (file)
@@ -474,7 +474,7 @@ static struct i2c_driver pa12203001_driver = {
                .pm = &pa12203001_pm_ops,
                .acpi_match_table = ACPI_PTR(pa12203001_acpi_match),
        },
-       .probe_new = pa12203001_probe,
+       .probe = pa12203001_probe,
        .remove = pa12203001_remove,
        .id_table = pa12203001_id,
 
diff --git a/drivers/iio/light/rohm-bu27008.c b/drivers/iio/light/rohm-bu27008.c
new file mode 100644 (file)
index 0000000..489902b
--- /dev/null
@@ -0,0 +1,1026 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * BU27008 ROHM Colour Sensor
+ *
+ * Copyright (c) 2023, ROHM Semiconductor.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/units.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/iio-gts-helper.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define BU27008_REG_SYSTEM_CONTROL     0x40
+#define BU27008_MASK_SW_RESET          BIT(7)
+#define BU27008_MASK_PART_ID           GENMASK(5, 0)
+#define BU27008_ID                     0x1a
+#define BU27008_REG_MODE_CONTROL1      0x41
+#define BU27008_MASK_MEAS_MODE         GENMASK(2, 0)
+#define BU27008_MASK_CHAN_SEL          GENMASK(3, 2)
+
+#define BU27008_REG_MODE_CONTROL2      0x42
+#define BU27008_MASK_RGBC_GAIN         GENMASK(7, 3)
+#define BU27008_MASK_IR_GAIN_LO                GENMASK(2, 0)
+#define BU27008_SHIFT_IR_GAIN          3
+
+#define BU27008_REG_MODE_CONTROL3      0x43
+#define BU27008_MASK_VALID             BIT(7)
+#define BU27008_MASK_INT_EN            BIT(1)
+#define BU27008_INT_EN                 BU27008_MASK_INT_EN
+#define BU27008_INT_DIS                        0
+#define BU27008_MASK_MEAS_EN           BIT(0)
+#define BU27008_MEAS_EN                        BIT(0)
+#define BU27008_MEAS_DIS               0
+
+#define BU27008_REG_DATA0_LO           0x50
+#define BU27008_REG_DATA1_LO           0x52
+#define BU27008_REG_DATA2_LO           0x54
+#define BU27008_REG_DATA3_LO           0x56
+#define BU27008_REG_DATA3_HI           0x57
+#define BU27008_REG_MANUFACTURER_ID    0x92
+#define BU27008_REG_MAX BU27008_REG_MANUFACTURER_ID
+
+/**
+ * enum bu27008_chan_type - BU27008 channel types
+ * @BU27008_RED:       Red channel. Always via data0.
+ * @BU27008_GREEN:     Green channel. Always via data1.
+ * @BU27008_BLUE:      Blue channel. Via data2 (when used).
+ * @BU27008_CLEAR:     Clear channel. Via data2 or data3 (when used).
+ * @BU27008_IR:                IR channel. Via data3 (when used).
+ * @BU27008_NUM_CHANS: Number of channel types.
+ */
+enum bu27008_chan_type {
+       BU27008_RED,
+       BU27008_GREEN,
+       BU27008_BLUE,
+       BU27008_CLEAR,
+       BU27008_IR,
+       BU27008_NUM_CHANS
+};
+
+/**
+ * enum bu27008_chan - BU27008 physical data channel
+ * @BU27008_DATA0:             Always red.
+ * @BU27008_DATA1:             Always green.
+ * @BU27008_DATA2:             Blue or clear.
+ * @BU27008_DATA3:             IR or clear.
+ * @BU27008_NUM_HW_CHANS:      Number of physical channels
+ */
+enum bu27008_chan {
+       BU27008_DATA0,
+       BU27008_DATA1,
+       BU27008_DATA2,
+       BU27008_DATA3,
+       BU27008_NUM_HW_CHANS
+};
+
+/* We can always measure red and green at same time */
+#define ALWAYS_SCANNABLE (BIT(BU27008_RED) | BIT(BU27008_GREEN))
+
+/* We use these data channel configs. Ensure scan_masks below follow them too */
+#define BU27008_BLUE2_CLEAR3           0x0 /* buffer is R, G, B, C */
+#define BU27008_CLEAR2_IR3             0x1 /* buffer is R, G, C, IR */
+#define BU27008_BLUE2_IR3              0x2 /* buffer is R, G, B, IR */
+
+static const unsigned long bu27008_scan_masks[] = {
+       /* buffer is R, G, B, C */
+       ALWAYS_SCANNABLE | BIT(BU27008_BLUE) | BIT(BU27008_CLEAR),
+       /* buffer is R, G, C, IR */
+       ALWAYS_SCANNABLE | BIT(BU27008_CLEAR) | BIT(BU27008_IR),
+       /* buffer is R, G, B, IR */
+       ALWAYS_SCANNABLE | BIT(BU27008_BLUE) | BIT(BU27008_IR),
+       0
+};
+
+/*
+ * Available scales with gain 1x - 1024x, timings 55, 100, 200, 400 mS
+ * Time impacts to gain: 1x, 2x, 4x, 8x.
+ *
+ * => Max total gain is HWGAIN * gain by integration time (8 * 1024) = 8192
+ *
+ * Max amplification is (HWGAIN * MAX integration-time multiplier) 1024 * 8
+ * = 8192. With NANO scale we get rid of accuracy loss when we start with the
+ * scale 16.0 for HWGAIN1, INT-TIME 55 mS. This way the nano scale for MAX
+ * total gain 8192 will be 1953125
+ */
+#define BU27008_SCALE_1X 16
+
+/* See the data sheet for the "Gain Setting" table */
+#define BU27008_GSEL_1X                0x00
+#define BU27008_GSEL_4X                0x08
+#define BU27008_GSEL_8X                0x09
+#define BU27008_GSEL_16X       0x0a
+#define BU27008_GSEL_32X       0x0b
+#define BU27008_GSEL_64X       0x0c
+#define BU27008_GSEL_256X      0x18
+#define BU27008_GSEL_512X      0x19
+#define BU27008_GSEL_1024X     0x1a
+
+static const struct iio_gain_sel_pair bu27008_gains[] = {
+       GAIN_SCALE_GAIN(1, BU27008_GSEL_1X),
+       GAIN_SCALE_GAIN(4, BU27008_GSEL_4X),
+       GAIN_SCALE_GAIN(8, BU27008_GSEL_8X),
+       GAIN_SCALE_GAIN(16, BU27008_GSEL_16X),
+       GAIN_SCALE_GAIN(32, BU27008_GSEL_32X),
+       GAIN_SCALE_GAIN(64, BU27008_GSEL_64X),
+       GAIN_SCALE_GAIN(256, BU27008_GSEL_256X),
+       GAIN_SCALE_GAIN(512, BU27008_GSEL_512X),
+       GAIN_SCALE_GAIN(1024, BU27008_GSEL_1024X),
+};
+
+static const struct iio_gain_sel_pair bu27008_gains_ir[] = {
+       GAIN_SCALE_GAIN(2, BU27008_GSEL_1X),
+       GAIN_SCALE_GAIN(4, BU27008_GSEL_4X),
+       GAIN_SCALE_GAIN(8, BU27008_GSEL_8X),
+       GAIN_SCALE_GAIN(16, BU27008_GSEL_16X),
+       GAIN_SCALE_GAIN(32, BU27008_GSEL_32X),
+       GAIN_SCALE_GAIN(64, BU27008_GSEL_64X),
+       GAIN_SCALE_GAIN(256, BU27008_GSEL_256X),
+       GAIN_SCALE_GAIN(512, BU27008_GSEL_512X),
+       GAIN_SCALE_GAIN(1024, BU27008_GSEL_1024X),
+};
+
+#define BU27008_MEAS_MODE_100MS                0x00
+#define BU27008_MEAS_MODE_55MS         0x01
+#define BU27008_MEAS_MODE_200MS                0x02
+#define BU27008_MEAS_MODE_400MS                0x04
+#define BU27008_MEAS_TIME_MAX_MS       400
+
+static const struct iio_itime_sel_mul bu27008_itimes[] = {
+       GAIN_SCALE_ITIME_US(400000, BU27008_MEAS_MODE_400MS, 8),
+       GAIN_SCALE_ITIME_US(200000, BU27008_MEAS_MODE_200MS, 4),
+       GAIN_SCALE_ITIME_US(100000, BU27008_MEAS_MODE_100MS, 2),
+       GAIN_SCALE_ITIME_US(55000, BU27008_MEAS_MODE_55MS, 1),
+};
+
+/*
+ * All the RGBC channels share the same gain.
+ * IR gain can be fine-tuned from the gain set for the RGBC by 2 bit, but this
+ * would yield quite complex gain setting. Especially since not all bit
+ * compinations are supported. And in any case setting GAIN for RGBC will
+ * always also change the IR-gain.
+ *
+ * On top of this, the selector '0' which corresponds to hw-gain 1X on RGBC,
+ * corresponds to gain 2X on IR. Rest of the selctors correspond to same gains
+ * though. This, however, makes it not possible to use shared gain for all
+ * RGBC and IR settings even though they are all changed at the one go.
+ */
+#define BU27008_CHAN(color, data, separate_avail)                              \
+{                                                                              \
+       .type = IIO_INTENSITY,                                                  \
+       .modified = 1,                                                          \
+       .channel2 = IIO_MOD_LIGHT_##color,                                      \
+       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |                          \
+                             BIT(IIO_CHAN_INFO_SCALE),                         \
+       .info_mask_separate_available = (separate_avail),                       \
+       .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),                 \
+       .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),       \
+       .address = BU27008_REG_##data##_LO,                                     \
+       .scan_index = BU27008_##color,                                          \
+       .scan_type = {                                                          \
+               .sign = 's',                                                    \
+               .realbits = 16,                                                 \
+               .storagebits = 16,                                              \
+               .endianness = IIO_LE,                                           \
+       },                                                                      \
+}
+
+/* For raw reads we always configure DATA3 for CLEAR */
+static const struct iio_chan_spec bu27008_channels[] = {
+       BU27008_CHAN(RED, DATA0, BIT(IIO_CHAN_INFO_SCALE)),
+       BU27008_CHAN(GREEN, DATA1, BIT(IIO_CHAN_INFO_SCALE)),
+       BU27008_CHAN(BLUE, DATA2, BIT(IIO_CHAN_INFO_SCALE)),
+       BU27008_CHAN(CLEAR, DATA2, BIT(IIO_CHAN_INFO_SCALE)),
+       /*
+        * We don't allow setting scale for IR (because of shared gain bits).
+        * Hence we don't advertise available ones either.
+        */
+       BU27008_CHAN(IR, DATA3, 0),
+       IIO_CHAN_SOFT_TIMESTAMP(BU27008_NUM_CHANS),
+};
+
+struct bu27008_data {
+       struct regmap *regmap;
+       struct iio_trigger *trig;
+       struct device *dev;
+       struct iio_gts gts;
+       struct iio_gts gts_ir;
+       int irq;
+
+       /*
+        * Prevent changing gain/time config when scale is read/written.
+        * Similarly, protect the integration_time read/change sequence.
+        * Prevent changing gain/time when data is read.
+        */
+       struct mutex mutex;
+};
+
+static const struct regmap_range bu27008_volatile_ranges[] = {
+       {
+               .range_min = BU27008_REG_SYSTEM_CONTROL,        /* SWRESET */
+               .range_max = BU27008_REG_SYSTEM_CONTROL,
+       }, {
+               .range_min = BU27008_REG_MODE_CONTROL3,         /* VALID */
+               .range_max = BU27008_REG_MODE_CONTROL3,
+       }, {
+               .range_min = BU27008_REG_DATA0_LO,              /* DATA */
+               .range_max = BU27008_REG_DATA3_HI,
+       },
+};
+
+static const struct regmap_access_table bu27008_volatile_regs = {
+       .yes_ranges = &bu27008_volatile_ranges[0],
+       .n_yes_ranges = ARRAY_SIZE(bu27008_volatile_ranges),
+};
+
+static const struct regmap_range bu27008_read_only_ranges[] = {
+       {
+               .range_min = BU27008_REG_DATA0_LO,
+               .range_max = BU27008_REG_DATA3_HI,
+       }, {
+               .range_min = BU27008_REG_MANUFACTURER_ID,
+               .range_max = BU27008_REG_MANUFACTURER_ID,
+       },
+};
+
+static const struct regmap_access_table bu27008_ro_regs = {
+       .no_ranges = &bu27008_read_only_ranges[0],
+       .n_no_ranges = ARRAY_SIZE(bu27008_read_only_ranges),
+};
+
+static const struct regmap_config bu27008_regmap = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = BU27008_REG_MAX,
+       .cache_type = REGCACHE_RBTREE,
+       .volatile_table = &bu27008_volatile_regs,
+       .wr_table = &bu27008_ro_regs,
+       /*
+        * All register writes are serialized by the mutex which protects the
+        * scale setting/getting. This is needed because scale is combined by
+        * gain and integration time settings and we need to ensure those are
+        * not read / written when scale is being computed.
+        *
+        * As a result of this serializing, we don't need regmap locking. Note,
+        * this is not true if we add any configurations which are not
+        * serialized by the mutex and which may need for example a protected
+        * read-modify-write cycle (eg. regmap_update_bits()). Please, revise
+        * this when adding features to the driver.
+        */
+       .disable_locking = true,
+};
+
+#define BU27008_MAX_VALID_RESULT_WAIT_US       50000
+#define BU27008_VALID_RESULT_WAIT_QUANTA_US    1000
+
+static int bu27008_chan_read_data(struct bu27008_data *data, int reg, int *val)
+{
+       int ret, valid;
+       __le16 tmp;
+
+       ret = regmap_read_poll_timeout(data->regmap, BU27008_REG_MODE_CONTROL3,
+                                      valid, (valid & BU27008_MASK_VALID),
+                                      BU27008_VALID_RESULT_WAIT_QUANTA_US,
+                                      BU27008_MAX_VALID_RESULT_WAIT_US);
+       if (ret)
+               return ret;
+
+       ret = regmap_bulk_read(data->regmap, reg, &tmp, sizeof(tmp));
+       if (ret)
+               dev_err(data->dev, "Reading channel data failed\n");
+
+       *val = le16_to_cpu(tmp);
+
+       return ret;
+}
+
+static int bu27008_get_gain(struct bu27008_data *data, struct iio_gts *gts, int *gain)
+{
+       int ret, sel;
+
+       ret = regmap_read(data->regmap, BU27008_REG_MODE_CONTROL2, &sel);
+       if (ret)
+               return ret;
+
+       sel = FIELD_GET(BU27008_MASK_RGBC_GAIN, sel);
+
+       ret = iio_gts_find_gain_by_sel(gts, sel);
+       if (ret < 0) {
+               dev_err(data->dev, "unknown gain value 0x%x\n", sel);
+               return ret;
+       }
+
+       *gain = ret;
+
+       return 0;
+}
+
+static int bu27008_write_gain_sel(struct bu27008_data *data, int sel)
+{
+       int regval;
+
+       regval = FIELD_PREP(BU27008_MASK_RGBC_GAIN, sel);
+
+       /*
+        * We do always set also the LOW bits of IR-gain because othervice we
+        * would risk resulting an invalid GAIN register value.
+        *
+        * We could allow setting separate gains for RGBC and IR when the
+        * values were such that HW could support both gain settings.
+        * Eg, when the shared bits were same for both gain values.
+        *
+        * This, however, has a negligible benefit compared to the increased
+        * software complexity when we would need to go through the gains
+        * for both channels separately when the integration time changes.
+        * This would end up with nasty logic for computing gain values for
+        * both channels - and rejecting them if shared bits changed.
+        *
+        * We should then build the logic by guessing what a user prefers.
+        * RGBC or IR gains correctly set while other jumps to odd value?
+        * Maybe look-up a value where both gains are somehow optimized
+        * <what this somehow is, is ATM unknown to us>. Or maybe user would
+        * expect us to reject changes when optimal gains can't be set to both
+        * channels w/given integration time. At best that would result
+        * solution that works well for a very specific subset of
+        * configurations but causes unexpected corner-cases.
+        *
+        * So, we keep it simple. Always set same selector to IR and RGBC.
+        * We disallow setting IR (as I expect that most of the users are
+        * interested in RGBC). This way we can show the user that the scales
+        * for RGBC and IR channels are different (1X Vs 2X with sel 0) while
+        * still keeping the operation deterministic.
+        */
+       regval |= FIELD_PREP(BU27008_MASK_IR_GAIN_LO, sel);
+
+       return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL2,
+                                 BU27008_MASK_RGBC_GAIN, regval);
+}
+
+static int bu27008_set_gain(struct bu27008_data *data, int gain)
+{
+       int ret;
+
+       ret = iio_gts_find_sel_by_gain(&data->gts, gain);
+       if (ret < 0)
+               return ret;
+
+       return bu27008_write_gain_sel(data, ret);
+}
+
+static int bu27008_get_int_time_sel(struct bu27008_data *data, int *sel)
+{
+       int ret, val;
+
+       ret = regmap_read(data->regmap, BU27008_REG_MODE_CONTROL1, &val);
+       *sel = FIELD_GET(BU27008_MASK_MEAS_MODE, val);
+
+       return ret;
+}
+
+static int bu27008_set_int_time_sel(struct bu27008_data *data, int sel)
+{
+       return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL1,
+                                 BU27008_MASK_MEAS_MODE, sel);
+}
+
+static int bu27008_get_int_time_us(struct bu27008_data *data)
+{
+       int ret, sel;
+
+       ret = bu27008_get_int_time_sel(data, &sel);
+       if (ret)
+               return ret;
+
+       return iio_gts_find_int_time_by_sel(&data->gts, sel);
+}
+
+static int _bu27008_get_scale(struct bu27008_data *data, bool ir, int *val,
+                             int *val2)
+{
+       struct iio_gts *gts;
+       int gain, ret;
+
+       if (ir)
+               gts = &data->gts_ir;
+       else
+               gts = &data->gts;
+
+       ret = bu27008_get_gain(data, gts, &gain);
+       if (ret)
+               return ret;
+
+       ret = bu27008_get_int_time_us(data);
+       if (ret < 0)
+               return ret;
+
+       return iio_gts_get_scale(gts, gain, ret, val, val2);
+}
+
+static int bu27008_get_scale(struct bu27008_data *data, bool ir, int *val,
+                            int *val2)
+{
+       int ret;
+
+       mutex_lock(&data->mutex);
+       ret = _bu27008_get_scale(data, ir, val, val2);
+       mutex_unlock(&data->mutex);
+
+       return ret;
+}
+
+static int bu27008_set_int_time(struct bu27008_data *data, int time)
+{
+       int ret;
+
+       ret = iio_gts_find_sel_by_int_time(&data->gts, time);
+       if (ret < 0)
+               return ret;
+
+       return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL1,
+                                 BU27008_MASK_MEAS_MODE, ret);
+}
+
+/* Try to change the time so that the scale is maintained */
+static int bu27008_try_set_int_time(struct bu27008_data *data, int int_time_new)
+{
+       int ret, old_time_sel, new_time_sel,  old_gain, new_gain;
+
+       mutex_lock(&data->mutex);
+
+       ret = bu27008_get_int_time_sel(data, &old_time_sel);
+       if (ret < 0)
+               goto unlock_out;
+
+       if (!iio_gts_valid_time(&data->gts, int_time_new)) {
+               dev_dbg(data->dev, "Unsupported integration time %u\n",
+                       int_time_new);
+
+               ret = -EINVAL;
+               goto unlock_out;
+       }
+
+       /* If we already use requested time, then we're done */
+       new_time_sel = iio_gts_find_sel_by_int_time(&data->gts, int_time_new);
+       if (new_time_sel == old_time_sel)
+               goto unlock_out;
+
+       ret = bu27008_get_gain(data, &data->gts, &old_gain);
+       if (ret)
+               goto unlock_out;
+
+       ret = iio_gts_find_new_gain_sel_by_old_gain_time(&data->gts, old_gain,
+                               old_time_sel, new_time_sel, &new_gain);
+       if (ret) {
+               int scale1, scale2;
+               bool ok;
+
+               _bu27008_get_scale(data, false, &scale1, &scale2);
+               dev_dbg(data->dev,
+                       "Can't support time %u with current scale %u %u\n",
+                       int_time_new, scale1, scale2);
+
+               if (new_gain < 0)
+                       goto unlock_out;
+
+               /*
+                * If caller requests for integration time change and we
+                * can't support the scale - then the caller should be
+                * prepared to 'pick up the pieces and deal with the
+                * fact that the scale changed'.
+                */
+               ret = iio_find_closest_gain_low(&data->gts, new_gain, &ok);
+               if (!ok)
+                       dev_dbg(data->dev, "optimal gain out of range\n");
+
+               if (ret < 0) {
+                       dev_dbg(data->dev,
+                                "Total gain increase. Risk of saturation");
+                       ret = iio_gts_get_min_gain(&data->gts);
+                       if (ret < 0)
+                               goto unlock_out;
+               }
+               new_gain = ret;
+               dev_dbg(data->dev, "scale changed, new gain %u\n", new_gain);
+       }
+
+       ret = bu27008_set_gain(data, new_gain);
+       if (ret)
+               goto unlock_out;
+
+       ret = bu27008_set_int_time(data, int_time_new);
+
+unlock_out:
+       mutex_unlock(&data->mutex);
+
+       return ret;
+}
+
+static int bu27008_meas_set(struct bu27008_data *data, int state)
+{
+       return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL3,
+                                 BU27008_MASK_MEAS_EN, state);
+}
+
+static int bu27008_chan_cfg(struct bu27008_data *data,
+                           struct iio_chan_spec const *chan)
+{
+       int chan_sel;
+
+       if (chan->scan_index == BU27008_BLUE)
+               chan_sel = BU27008_BLUE2_CLEAR3;
+       else
+               chan_sel = BU27008_CLEAR2_IR3;
+
+       chan_sel = FIELD_PREP(BU27008_MASK_CHAN_SEL, chan_sel);
+
+       return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL3,
+                                 BU27008_MASK_CHAN_SEL, chan_sel);
+}
+
+static int bu27008_read_one(struct bu27008_data *data, struct iio_dev *idev,
+                           struct iio_chan_spec const *chan, int *val, int *val2)
+{
+       int ret, int_time;
+
+       ret = bu27008_chan_cfg(data, chan);
+       if (ret)
+               return ret;
+
+       ret = bu27008_meas_set(data, BU27008_MEAS_EN);
+       if (ret)
+               return ret;
+
+       ret = bu27008_get_int_time_us(data);
+       if (ret < 0)
+               int_time = BU27008_MEAS_TIME_MAX_MS;
+       else
+               int_time = ret / USEC_PER_MSEC;
+
+       msleep(int_time);
+
+       ret = bu27008_chan_read_data(data, chan->address, val);
+       if (!ret)
+               ret = IIO_VAL_INT;
+
+       if (bu27008_meas_set(data, BU27008_MEAS_DIS))
+               dev_warn(data->dev, "measurement disabling failed\n");
+
+       return ret;
+}
+
+static int bu27008_read_raw(struct iio_dev *idev,
+                          struct iio_chan_spec const *chan,
+                          int *val, int *val2, long mask)
+{
+       struct bu27008_data *data = iio_priv(idev);
+       int busy, ret;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               busy = iio_device_claim_direct_mode(idev);
+               if (busy)
+                       return -EBUSY;
+
+               mutex_lock(&data->mutex);
+               ret = bu27008_read_one(data, idev, chan, val, val2);
+               mutex_unlock(&data->mutex);
+
+               iio_device_release_direct_mode(idev);
+
+               return ret;
+
+       case IIO_CHAN_INFO_SCALE:
+               ret = bu27008_get_scale(data, chan->scan_index == BU27008_IR,
+                                       val, val2);
+               if (ret)
+                       return ret;
+
+               return IIO_VAL_INT_PLUS_NANO;
+
+       case IIO_CHAN_INFO_INT_TIME:
+               ret = bu27008_get_int_time_us(data);
+               if (ret < 0)
+                       return ret;
+
+               *val = 0;
+               *val2 = ret;
+
+               return IIO_VAL_INT_PLUS_MICRO;
+
+       default:
+               return -EINVAL;
+       }
+}
+
+/* Called if the new scale could not be supported with existing int-time */
+static int bu27008_try_find_new_time_gain(struct bu27008_data *data, int val,
+                                         int val2, int *gain_sel)
+{
+       int i, ret, new_time_sel;
+
+       for (i = 0; i < data->gts.num_itime; i++) {
+               new_time_sel = data->gts.itime_table[i].sel;
+               ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts,
+                                       new_time_sel, val, val2 * 1000, gain_sel);
+               if (!ret)
+                       break;
+       }
+       if (i == data->gts.num_itime) {
+               dev_err(data->dev, "Can't support scale %u %u\n", val, val2);
+
+               return -EINVAL;
+       }
+
+       return bu27008_set_int_time_sel(data, new_time_sel);
+}
+
+static int bu27008_set_scale(struct bu27008_data *data,
+                            struct iio_chan_spec const *chan,
+                            int val, int val2)
+{
+       int ret, gain_sel, time_sel;
+
+       if (chan->scan_index == BU27008_IR)
+               return -EINVAL;
+
+       mutex_lock(&data->mutex);
+
+       ret = bu27008_get_int_time_sel(data, &time_sel);
+       if (ret < 0)
+               goto unlock_out;
+
+       ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, time_sel,
+                                               val, val2 * 1000, &gain_sel);
+       if (ret) {
+               ret = bu27008_try_find_new_time_gain(data, val, val2, &gain_sel);
+               if (ret)
+                       goto unlock_out;
+
+       }
+       ret = bu27008_write_gain_sel(data, gain_sel);
+
+unlock_out:
+       mutex_unlock(&data->mutex);
+
+       return ret;
+}
+
+static int bu27008_write_raw(struct iio_dev *idev,
+                            struct iio_chan_spec const *chan,
+                            int val, int val2, long mask)
+{
+       struct bu27008_data *data = iio_priv(idev);
+       int ret;
+
+       /*
+        * Do not allow changing scale when measurement is ongoing as doing so
+        * could make values in the buffer inconsistent.
+        */
+       ret = iio_device_claim_direct_mode(idev);
+       if (ret)
+               return ret;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_SCALE:
+               ret = bu27008_set_scale(data, chan, val, val2);
+               break;
+       case IIO_CHAN_INFO_INT_TIME:
+               if (val) {
+                       ret = -EINVAL;
+                       break;
+               }
+               ret = bu27008_try_set_int_time(data, val2);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       iio_device_release_direct_mode(idev);
+
+       return ret;
+}
+
+static int bu27008_read_avail(struct iio_dev *idev,
+                             struct iio_chan_spec const *chan, const int **vals,
+                             int *type, int *length, long mask)
+{
+       struct bu27008_data *data = iio_priv(idev);
+
+       switch (mask) {
+       case IIO_CHAN_INFO_INT_TIME:
+               return iio_gts_avail_times(&data->gts, vals, type, length);
+       case IIO_CHAN_INFO_SCALE:
+               if (chan->channel2 == IIO_MOD_LIGHT_IR)
+                       return iio_gts_all_avail_scales(&data->gts_ir, vals,
+                                                       type, length);
+               return iio_gts_all_avail_scales(&data->gts, vals, type, length);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int bu27008_update_scan_mode(struct iio_dev *idev,
+                                   const unsigned long *scan_mask)
+{
+       struct bu27008_data *data = iio_priv(idev);
+       int chan_sel;
+
+       /* Configure channel selection */
+       if (test_bit(BU27008_BLUE, idev->active_scan_mask)) {
+               if (test_bit(BU27008_CLEAR, idev->active_scan_mask))
+                       chan_sel = BU27008_BLUE2_CLEAR3;
+               else
+                       chan_sel = BU27008_BLUE2_IR3;
+       } else {
+               chan_sel = BU27008_CLEAR2_IR3;
+       }
+
+       chan_sel = FIELD_PREP(BU27008_MASK_CHAN_SEL, chan_sel);
+
+       return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL3,
+                                BU27008_MASK_CHAN_SEL, chan_sel);
+}
+
+static const struct iio_info bu27008_info = {
+       .read_raw = &bu27008_read_raw,
+       .write_raw = &bu27008_write_raw,
+       .read_avail = &bu27008_read_avail,
+       .update_scan_mode = bu27008_update_scan_mode,
+       .validate_trigger = iio_validate_own_trigger,
+};
+
+static int bu27008_chip_init(struct bu27008_data *data)
+{
+       int ret;
+
+       ret = regmap_write_bits(data->regmap, BU27008_REG_SYSTEM_CONTROL,
+                               BU27008_MASK_SW_RESET, BU27008_MASK_SW_RESET);
+       if (ret)
+               return dev_err_probe(data->dev, ret, "Sensor reset failed\n");
+
+       /*
+        * The data-sheet does not tell how long performing the IC reset takes.
+        * However, the data-sheet says the minimum time it takes the IC to be
+        * able to take inputs after power is applied, is 100 uS. I'd assume
+        * > 1 mS is enough.
+        */
+       msleep(1);
+
+       ret = regmap_reinit_cache(data->regmap, &bu27008_regmap);
+       if (ret)
+               dev_err(data->dev, "Failed to reinit reg cache\n");
+
+       return ret;
+}
+
+static int bu27008_set_drdy_irq(struct bu27008_data *data, int state)
+{
+       return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL3,
+                                BU27008_MASK_INT_EN, state);
+}
+
+static int bu27008_trigger_set_state(struct iio_trigger *trig,
+                                    bool state)
+{
+       struct bu27008_data *data = iio_trigger_get_drvdata(trig);
+       int ret;
+
+       if (state)
+               ret = bu27008_set_drdy_irq(data, BU27008_INT_EN);
+       else
+               ret = bu27008_set_drdy_irq(data, BU27008_INT_DIS);
+       if (ret)
+               dev_err(data->dev, "Failed to set trigger state\n");
+
+       return ret;
+}
+
+static void bu27008_trigger_reenable(struct iio_trigger *trig)
+{
+       struct bu27008_data *data = iio_trigger_get_drvdata(trig);
+
+       enable_irq(data->irq);
+}
+
+static const struct iio_trigger_ops bu27008_trigger_ops = {
+       .set_trigger_state = bu27008_trigger_set_state,
+       .reenable = bu27008_trigger_reenable,
+};
+
+static irqreturn_t bu27008_trigger_handler(int irq, void *p)
+{
+       struct iio_poll_func *pf = p;
+       struct iio_dev *idev = pf->indio_dev;
+       struct bu27008_data *data = iio_priv(idev);
+       struct {
+               __le16 chan[BU27008_NUM_HW_CHANS];
+               s64 ts __aligned(8);
+       } raw;
+       int ret, dummy;
+
+       memset(&raw, 0, sizeof(raw));
+
+       /*
+        * After some measurements, it seems reading the
+        * BU27008_REG_MODE_CONTROL3 debounces the IRQ line
+        */
+       ret = regmap_read(data->regmap, BU27008_REG_MODE_CONTROL3, &dummy);
+       if (ret < 0)
+               goto err_read;
+
+       ret = regmap_bulk_read(data->regmap, BU27008_REG_DATA0_LO, &raw.chan,
+                              sizeof(raw.chan));
+       if (ret < 0)
+               goto err_read;
+
+       iio_push_to_buffers_with_timestamp(idev, &raw, pf->timestamp);
+err_read:
+       iio_trigger_notify_done(idev->trig);
+
+       return IRQ_HANDLED;
+}
+
+static int bu27008_buffer_preenable(struct iio_dev *idev)
+{
+       struct bu27008_data *data = iio_priv(idev);
+
+       return bu27008_meas_set(data, BU27008_MEAS_EN);
+}
+
+static int bu27008_buffer_postdisable(struct iio_dev *idev)
+{
+       struct bu27008_data *data = iio_priv(idev);
+
+       return bu27008_meas_set(data, BU27008_MEAS_DIS);
+}
+
+static const struct iio_buffer_setup_ops bu27008_buffer_ops = {
+       .preenable = bu27008_buffer_preenable,
+       .postdisable = bu27008_buffer_postdisable,
+};
+
+static irqreturn_t bu27008_data_rdy_poll(int irq, void *private)
+{
+       /*
+        * The BU27008 keeps IRQ asserted until we read the VALID bit from
+        * a register. We need to keep the IRQ disabled until then.
+        */
+       disable_irq_nosync(irq);
+       iio_trigger_poll(private);
+
+       return IRQ_HANDLED;
+}
+
+static int bu27008_setup_trigger(struct bu27008_data *data, struct iio_dev *idev)
+{
+       struct iio_trigger *itrig;
+       char *name;
+       int ret;
+
+       ret = devm_iio_triggered_buffer_setup(data->dev, idev,
+                                             &iio_pollfunc_store_time,
+                                             bu27008_trigger_handler,
+                                             &bu27008_buffer_ops);
+       if (ret)
+               return dev_err_probe(data->dev, ret,
+                            "iio_triggered_buffer_setup_ext FAIL\n");
+
+       itrig = devm_iio_trigger_alloc(data->dev, "%sdata-rdy-dev%d",
+                                      idev->name, iio_device_id(idev));
+       if (!itrig)
+               return -ENOMEM;
+
+       data->trig = itrig;
+
+       itrig->ops = &bu27008_trigger_ops;
+       iio_trigger_set_drvdata(itrig, data);
+
+       name = devm_kasprintf(data->dev, GFP_KERNEL, "%s-bu27008",
+                             dev_name(data->dev));
+
+       ret = devm_request_irq(data->dev, data->irq,
+                              &bu27008_data_rdy_poll,
+                              0, name, itrig);
+       if (ret)
+               return dev_err_probe(data->dev, ret, "Could not request IRQ\n");
+
+       ret = devm_iio_trigger_register(data->dev, itrig);
+       if (ret)
+               return dev_err_probe(data->dev, ret,
+                                    "Trigger registration failed\n");
+
+       /* set default trigger */
+       idev->trig = iio_trigger_get(itrig);
+
+       return 0;
+}
+
+static int bu27008_probe(struct i2c_client *i2c)
+{
+       struct device *dev = &i2c->dev;
+       struct bu27008_data *data;
+       struct regmap *regmap;
+       unsigned int part_id, reg;
+       struct iio_dev *idev;
+       int ret;
+
+       regmap = devm_regmap_init_i2c(i2c, &bu27008_regmap);
+       if (IS_ERR(regmap))
+               return dev_err_probe(dev, PTR_ERR(regmap),
+                                    "Failed to initialize Regmap\n");
+
+       idev = devm_iio_device_alloc(dev, sizeof(*data));
+       if (!idev)
+               return -ENOMEM;
+
+       ret = devm_regulator_get_enable(dev, "vdd");
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to get regulator\n");
+
+       data = iio_priv(idev);
+
+       ret = regmap_read(regmap, BU27008_REG_SYSTEM_CONTROL, &reg);
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to access sensor\n");
+
+       part_id = FIELD_GET(BU27008_MASK_PART_ID, reg);
+
+       if (part_id != BU27008_ID)
+               dev_warn(dev, "unknown device 0x%x\n", part_id);
+
+       ret = devm_iio_init_iio_gts(dev, BU27008_SCALE_1X, 0, bu27008_gains,
+                                   ARRAY_SIZE(bu27008_gains), bu27008_itimes,
+                                   ARRAY_SIZE(bu27008_itimes), &data->gts);
+       if (ret)
+               return ret;
+
+       ret = devm_iio_init_iio_gts(dev, BU27008_SCALE_1X, 0, bu27008_gains_ir,
+                                   ARRAY_SIZE(bu27008_gains_ir), bu27008_itimes,
+                                   ARRAY_SIZE(bu27008_itimes), &data->gts_ir);
+       if (ret)
+               return ret;
+
+       mutex_init(&data->mutex);
+       data->regmap = regmap;
+       data->dev = dev;
+       data->irq = i2c->irq;
+
+       idev->channels = bu27008_channels;
+       idev->num_channels = ARRAY_SIZE(bu27008_channels);
+       idev->name = "bu27008";
+       idev->info = &bu27008_info;
+       idev->modes = INDIO_DIRECT_MODE;
+       idev->available_scan_masks = bu27008_scan_masks;
+
+       ret = bu27008_chip_init(data);
+       if (ret)
+               return ret;
+
+       if (i2c->irq) {
+               ret = bu27008_setup_trigger(data, idev);
+               if (ret)
+                       return ret;
+       } else {
+               dev_info(dev, "No IRQ, buffered mode disabled\n");
+       }
+
+       ret = devm_iio_device_register(dev, idev);
+       if (ret)
+               return dev_err_probe(dev, ret,
+                                    "Unable to register iio device\n");
+
+       return 0;
+}
+
+static const struct of_device_id bu27008_of_match[] = {
+       { .compatible = "rohm,bu27008" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, bu27008_of_match);
+
+static struct i2c_driver bu27008_i2c_driver = {
+       .driver = {
+               .name = "bu27008",
+               .of_match_table = bu27008_of_match,
+               .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+       },
+       .probe = bu27008_probe,
+};
+module_i2c_driver(bu27008_i2c_driver);
+
+MODULE_DESCRIPTION("ROHM BU27008 colour sensor driver");
+MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(IIO_GTS_HELPER);
index e486dcf35eba7d60fc84e52f75fc566e52193a72..e63ef5789cde1e4fd17b4485761b461308007283 100644 (file)
@@ -231,6 +231,9 @@ struct bu27034_result {
 
 static const struct regmap_range bu27034_volatile_ranges[] = {
        {
+               .range_min = BU27034_REG_SYSTEM_CONTROL,
+               .range_max = BU27034_REG_SYSTEM_CONTROL,
+       }, {
                .range_min = BU27034_REG_MODE_CONTROL4,
                .range_max = BU27034_REG_MODE_CONTROL4,
        }, {
@@ -1167,11 +1170,12 @@ static int bu27034_read_raw(struct iio_dev *idev,
 
        switch (mask) {
        case IIO_CHAN_INFO_INT_TIME:
-               *val = bu27034_get_int_time(data);
-               if (*val < 0)
-                       return *val;
+               *val = 0;
+               *val2 = bu27034_get_int_time(data);
+               if (*val2 < 0)
+                       return *val2;
 
-               return IIO_VAL_INT;
+               return IIO_VAL_INT_PLUS_MICRO;
 
        case IIO_CHAN_INFO_SCALE:
                return bu27034_get_scale(data, chan->channel, val, val2);
@@ -1229,7 +1233,10 @@ static int bu27034_write_raw(struct iio_dev *idev,
                ret = bu27034_set_scale(data, chan->channel, val, val2);
                break;
        case IIO_CHAN_INFO_INT_TIME:
-               ret = bu27034_try_set_int_time(data, val);
+               if (!val)
+                       ret = bu27034_try_set_int_time(data, val2);
+               else
+                       ret = -EINVAL;
                break;
        default:
                ret = -EINVAL;
@@ -1268,12 +1275,19 @@ static int bu27034_chip_init(struct bu27034_data *data)
        int ret, sel;
 
        /* Reset */
-       ret = regmap_update_bits(data->regmap, BU27034_REG_SYSTEM_CONTROL,
+       ret = regmap_write_bits(data->regmap, BU27034_REG_SYSTEM_CONTROL,
                           BU27034_MASK_SW_RESET, BU27034_MASK_SW_RESET);
        if (ret)
                return dev_err_probe(data->dev, ret, "Sensor reset failed\n");
 
        msleep(1);
+
+       ret = regmap_reinit_cache(data->regmap, &bu27034_regmap);
+       if (ret) {
+               dev_err(data->dev, "Failed to reinit reg cache\n");
+               return ret;
+       }
+
        /*
         * Read integration time here to ensure it is in regmap cache. We do
         * this to speed-up the int-time acquisition in the start of the buffer
@@ -1486,8 +1500,9 @@ static struct i2c_driver bu27034_i2c_driver = {
        .driver = {
                .name = "bu27034-als",
                .of_match_table = bu27034_of_match,
+               .probe_type = PROBE_PREFER_ASYNCHRONOUS,
        },
-       .probe_new = bu27034_probe,
+       .probe = bu27034_probe,
 };
 module_i2c_driver(bu27034_i2c_driver);
 
index 9d0218b7426ee77c42411b4ca802ca1ab901bd4b..bbb8581622f29d358f3f04415725b802a0952793 100644 (file)
@@ -1121,7 +1121,7 @@ static struct i2c_driver rpr0521_driver = {
                .pm     = pm_ptr(&rpr0521_pm_ops),
                .acpi_match_table = ACPI_PTR(rpr0521_acpi_match),
        },
-       .probe_new      = rpr0521_probe,
+       .probe          = rpr0521_probe,
        .remove         = rpr0521_remove,
        .id_table       = rpr0521_id,
 };
index a08fbc8f5adb1bdfd0624b7f7672c510f68849c5..ea2c437199c0fb37739b4e5b40360f16f2a74b8f 100644 (file)
@@ -1064,7 +1064,7 @@ static struct i2c_driver si1133_driver = {
        .driver = {
            .name   = "si1133",
        },
-       .probe_new = si1133_probe,
+       .probe = si1133_probe,
        .id_table = si1133_ids,
 };
 
index f7126235f94c91cbd954e774c2edf4fa388acd04..77666b780a5c5a264522cd52dd2b6b1bad58ecea 100644 (file)
@@ -1352,7 +1352,7 @@ static struct i2c_driver si1145_driver = {
        .driver = {
                .name   = "si1145",
        },
-       .probe_new = si1145_probe,
+       .probe = si1145_probe,
        .id_table = si1145_ids,
 };
 
index 2160e87bb498e7790153a328aa15ff4bf29be439..6bc2ddfb77ca633361682b3637f2c45e558a0f6f 100644 (file)
@@ -57,7 +57,7 @@ static struct i2c_driver st_uvis25_driver = {
                .pm = pm_sleep_ptr(&st_uvis25_pm_ops),
                .of_match_table = st_uvis25_i2c_of_match,
        },
-       .probe_new = st_uvis25_i2c_probe,
+       .probe = st_uvis25_i2c_probe,
        .id_table = st_uvis25_i2c_id_table,
 };
 module_i2c_driver(st_uvis25_driver);
index 48ae6ff0015e1eb91b9ad26638a41f5667537105..72b08d870d337b9ca583e2449f0b8a02a8e5dc19 100644 (file)
@@ -714,7 +714,7 @@ static struct i2c_driver stk3310_driver = {
                .pm = pm_sleep_ptr(&stk3310_pm_ops),
                .acpi_match_table = ACPI_PTR(stk3310_acpi_id),
        },
-       .probe_new =        stk3310_probe,
+       .probe =        stk3310_probe,
        .remove =           stk3310_remove,
        .id_table =         stk3310_i2c_id,
 };
index 5100732fbaf0a1255c89e17e622ada20601a5c0e..dcdd85b006be0b9e7f4cb073160cafca93ffd915 100644 (file)
@@ -373,7 +373,7 @@ static struct i2c_driver tcs3414_driver = {
                .name   = TCS3414_DRV_NAME,
                .pm     = pm_sleep_ptr(&tcs3414_pm_ops),
        },
-       .probe_new      = tcs3414_probe,
+       .probe          = tcs3414_probe,
        .id_table       = tcs3414_id,
 };
 module_i2c_driver(tcs3414_driver);
index 6187c54879162d035e0129737c3116eeda948d33..75fcf2c93717b67d9ba0e144b03a5b21cbcfad71 100644 (file)
@@ -609,7 +609,7 @@ static struct i2c_driver tcs3472_driver = {
                .name   = TCS3472_DRV_NAME,
                .pm     = pm_sleep_ptr(&tcs3472_pm_ops),
        },
-       .probe_new      = tcs3472_probe,
+       .probe          = tcs3472_probe,
        .remove         = tcs3472_remove,
        .id_table       = tcs3472_id,
 };
index f2f55239a072f97670362d94b9e86e3714f9ae19..1a6f514bced6e0bd542c14a279071d5820a462c8 100644 (file)
@@ -862,7 +862,7 @@ static struct i2c_driver tsl2563_i2c_driver = {
                .of_match_table = tsl2563_of_match,
                .pm     = pm_sleep_ptr(&tsl2563_pm_ops),
        },
-       .probe_new      = tsl2563_probe,
+       .probe          = tsl2563_probe,
        .remove         = tsl2563_remove,
        .id_table       = tsl2563_id,
 };
index a05f1c0453d16d3455283b765b1cdce339141e02..02ad11611b9c576afa7e09515ed6fbeb8c4f0db2 100644 (file)
@@ -942,7 +942,7 @@ static struct i2c_driver tsl2583_driver = {
                .of_match_table = tsl2583_of_match,
        },
        .id_table = tsl2583_idtable,
-       .probe_new = tsl2583_probe,
+       .probe = tsl2583_probe,
        .remove = tsl2583_remove,
 };
 module_i2c_driver(tsl2583_driver);
index e485a556e6da8086247b99c7ee6c177bdb4d7896..7bdbfe72f0f0413625c9c2ee5b3aac05ac974e4f 100644 (file)
@@ -1214,7 +1214,7 @@ static struct i2c_driver tsl2591_driver = {
                .pm = pm_ptr(&tsl2591_pm_ops),
                .of_match_table = tsl2591_of_match,
        },
-       .probe_new = tsl2591_probe
+       .probe = tsl2591_probe
 };
 module_i2c_driver(tsl2591_driver);
 
index e823c145f6792ee4204697f902d238c0a1b9f440..cab468a82b616a23394977da1d8822d29d8941d3 100644 (file)
@@ -1932,7 +1932,7 @@ static struct i2c_driver tsl2772_driver = {
                .pm = &tsl2772_pm_ops,
        },
        .id_table = tsl2772_idtable,
-       .probe_new = tsl2772_probe,
+       .probe = tsl2772_probe,
 };
 
 module_i2c_driver(tsl2772_driver);
index d95397eb15263bd456bef5922e4991e69207de15..4da7d78906d4a361b0d43f3ba2fd11305300533e 100644 (file)
@@ -237,7 +237,7 @@ static struct i2c_driver tsl4531_driver = {
                .name   = TSL4531_DRV_NAME,
                .pm     = pm_sleep_ptr(&tsl4531_pm_ops),
        },
-       .probe_new = tsl4531_probe,
+       .probe = tsl4531_probe,
        .remove = tsl4531_remove,
        .id_table = tsl4531_id,
 };
index 8b2a0c99c8e6f856be4f5e322512a4c7d1bdae2d..61b3b2aea626fb2322a5ab87be28085447f8e443 100644 (file)
@@ -974,7 +974,7 @@ static struct i2c_driver us5182d_driver = {
                .of_match_table = us5182d_of_match,
                .acpi_match_table = ACPI_PTR(us5182d_acpi_match),
        },
-       .probe_new = us5182d_probe,
+       .probe = us5182d_probe,
        .remove = us5182d_remove,
        .id_table = us5182d_id,
 
index 56d3963d3d66a3285ce0632f37eebd624daff962..7c7362e2882137592652d7b7e030b135a82e6628 100644 (file)
@@ -1500,7 +1500,7 @@ static struct i2c_driver vcnl4000_driver = {
                .pm     = pm_ptr(&vcnl4000_pm_ops),
                .of_match_table = vcnl_4000_of_match,
        },
-       .probe_new = vcnl4000_probe,
+       .probe = vcnl4000_probe,
        .id_table = vcnl4000_id,
        .remove = vcnl4000_remove,
 };
index 14e29330e972eb91f094a284913fb57e79e50572..56bbefbc0ae6434514670f2e84bca38db1118ee3 100644 (file)
@@ -8,6 +8,7 @@
  * TODO: Proximity
  */
 #include <linux/bitops.h>
+#include <linux/bitfield.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
@@ -42,6 +43,7 @@
 #define VCNL4035_ALS_PERS_MASK         GENMASK(3, 2)
 #define VCNL4035_INT_ALS_IF_H_MASK     BIT(12)
 #define VCNL4035_INT_ALS_IF_L_MASK     BIT(13)
+#define VCNL4035_DEV_ID_MASK           GENMASK(7, 0)
 
 /* Default values */
 #define VCNL4035_MODE_ALS_ENABLE       BIT(0)
@@ -413,6 +415,7 @@ static int vcnl4035_init(struct vcnl4035_data *data)
                return ret;
        }
 
+       id = FIELD_GET(VCNL4035_DEV_ID_MASK, id);
        if (id != VCNL4035_DEV_ID_VAL) {
                dev_err(&data->client->dev, "Wrong id, got %x, expected %x\n",
                        id, VCNL4035_DEV_ID_VAL);
@@ -667,7 +670,7 @@ static struct i2c_driver vcnl4035_driver = {
                .pm     = pm_ptr(&vcnl4035_pm_ops),
                .of_match_table = vcnl4035_of_match,
        },
-       .probe_new = vcnl4035_probe,
+       .probe = vcnl4035_probe,
        .remove = vcnl4035_remove,
        .id_table = vcnl4035_id,
 };
index e7d2d5d177d43c8cc28d3a8ddb4a59d4946c27b3..043f233d9bdb068dea467c5a6068519f9501dabc 100644 (file)
@@ -892,7 +892,7 @@ static struct i2c_driver veml6030_driver = {
                .of_match_table = veml6030_of_match,
                .pm = pm_ptr(&veml6030_pm_ops),
        },
-       .probe_new = veml6030_probe,
+       .probe = veml6030_probe,
        .id_table = veml6030_id,
 };
 module_i2c_driver(veml6030_driver);
index ee76a68deb24af1ed34dd149812af29149ea9b10..d99bf3ae0fe8e943d13016568fb8ed2a4dff8c0d 100644 (file)
@@ -198,7 +198,7 @@ static struct i2c_driver veml6070_driver = {
        .driver = {
                .name   = VEML6070_DRV_NAME,
        },
-       .probe_new = veml6070_probe,
+       .probe = veml6070_probe,
        .remove  = veml6070_remove,
        .id_table = veml6070_id,
 };
index 8b56df26c59e8fff7f6a2a79ad8dc8c3792cb888..d4948dfc31ff14ab13bed360c7889dfd94cda762 100644 (file)
@@ -538,7 +538,7 @@ static struct i2c_driver vl6180_driver = {
                .name   = VL6180_DRV_NAME,
                .of_match_table = vl6180_of_match,
        },
-       .probe_new = vl6180_probe,
+       .probe = vl6180_probe,
        .id_table = vl6180_id,
 };
 
index e3bac8b563807427dd4f3982996682f75d99ccc9..d370193a4742347db7fc7de1846c3a5ac9180b2f 100644 (file)
@@ -554,7 +554,7 @@ static struct i2c_driver zopt2201_driver = {
        .driver = {
                .name   = ZOPT2201_DRV_NAME,
        },
-       .probe_new = zopt2201_probe,
+       .probe = zopt2201_probe,
        .id_table = zopt2201_id,
 };
 
index 45abdcce6bc0ad1f3849827238a215c2ad974846..c74d11943ec797b3cfde6efece6f73a6fa446e4b 100644 (file)
@@ -1046,7 +1046,7 @@ static struct i2c_driver ak8974_driver = {
                .pm = pm_ptr(&ak8974_dev_pm_ops),
                .of_match_table = ak8974_of_match,
        },
-       .probe_new = ak8974_probe,
+       .probe = ak8974_probe,
        .remove   = ak8974_remove,
        .id_table = ak8974_id,
 };
index 924b481a3034aac393a8d1bb0e621caba0bb139c..eb706d0bf70bc0d6354a44d1b99e704b63561b83 100644 (file)
@@ -1110,7 +1110,7 @@ static struct i2c_driver ak8975_driver = {
                .of_match_table = ak8975_of_match,
                .acpi_match_table = ak_acpi_match,
        },
-       .probe_new      = ak8975_probe,
+       .probe          = ak8975_probe,
        .remove         = ak8975_remove,
        .id_table       = ak8975_id,
 };
index 44b8960eea175fb744e772fa5dbad5bcb2bf3de3..281d1fa31c8e17dc71f6a92e9e33b02904bc7f2c 100644 (file)
@@ -71,7 +71,7 @@ static struct i2c_driver bmc150_magn_driver = {
                .acpi_match_table = ACPI_PTR(bmc150_magn_acpi_match),
                .pm     = &bmc150_magn_pm_ops,
        },
-       .probe_new      = bmc150_magn_i2c_probe,
+       .probe          = bmc150_magn_i2c_probe,
        .remove         = bmc150_magn_i2c_remove,
        .id_table       = bmc150_magn_i2c_id,
 };
index 7ef2b1d562898ee4d21c106759b9355e5e076371..bdd2784a9f863b0c872501a93438aa7e2d074b98 100644 (file)
@@ -95,7 +95,7 @@ static struct i2c_driver hmc5843_driver = {
                .of_match_table = hmc5843_of_match,
        },
        .id_table       = hmc5843_id,
-       .probe_new      = hmc5843_i2c_probe,
+       .probe          = hmc5843_i2c_probe,
        .remove         = hmc5843_i2c_remove,
 };
 module_i2c_driver(hmc5843_driver);
index 661176a885ad763e8a387a88c6e184551c76de70..deffe3ca90043bbeba9055470fa244842a2d0c1a 100644 (file)
@@ -641,7 +641,7 @@ static struct i2c_driver mag3110_driver = {
                .of_match_table = mag3110_of_match,
                .pm     = pm_sleep_ptr(&mag3110_pm_ops),
        },
-       .probe_new = mag3110_probe,
+       .probe = mag3110_probe,
        .remove = mag3110_remove,
        .id_table = mag3110_id,
 };
index 756dadbad106f73d0736b1ca2af8188c38a05c1b..b495b8a6392848e3eca7dc278eacdcc21803291a 100644 (file)
@@ -575,7 +575,7 @@ static struct i2c_driver mmc35240_driver = {
                .pm = pm_sleep_ptr(&mmc35240_pm_ops),
                .acpi_match_table = ACPI_PTR(mmc35240_acpi_match),
        },
-       .probe_new      = mmc35240_probe,
+       .probe          = mmc35240_probe,
        .id_table       = mmc35240_id,
 };
 
index ba669ab7113dbe011c8e02810c67fbd67aa0c0dc..ac7276b3798c07290669f19ccac3f163fd15838f 100644 (file)
@@ -45,7 +45,7 @@ static struct i2c_driver rm3100_driver = {
                .name = "rm3100-i2c",
                .of_match_table = rm3100_dt_match,
        },
-       .probe_new = rm3100_probe,
+       .probe = rm3100_probe,
 };
 module_i2c_driver(rm3100_driver);
 
index 8faa7409d9e12d6a9192b3f9ec38bd659fe2d429..6cc0dfd31821b094735f04b0bc0e15319407a759 100644 (file)
@@ -427,6 +427,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
                .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = LSM9DS0_IMU_DEV_NAME,
+                       [1] = LSM303D_IMU_DEV_NAME,
                },
                .ch = (struct iio_chan_spec *)st_magn_4_16bit_channels,
                .odr = {
index cc0e0e94b129c12eb5f39cbf3fa734d9b82d10b1..950826dd20bf5f16bf0f0c7b4f02ea2dc095de8c 100644 (file)
@@ -111,7 +111,7 @@ static struct i2c_driver st_magn_driver = {
                .name = "st-magn-i2c",
                .of_match_table = st_magn_of_match,
        },
-       .probe_new = st_magn_i2c_probe,
+       .probe = st_magn_i2c_probe,
        .id_table = st_magn_id_table,
 };
 module_i2c_driver(st_magn_driver);
index 28bb7efe8df8c07bba0b4810c9beae3e60c5ef8c..c5e5c4ad681e644760acd4ddb67bbe7105a9f293 100644 (file)
@@ -296,12 +296,13 @@ static int tmag5273_read_raw(struct iio_dev *indio_dev,
                        return ret;
 
                ret = tmag5273_get_measure(data, &t, &x, &y, &z, &angle, &magnitude);
-               if (ret)
-                       return ret;
 
                pm_runtime_mark_last_busy(data->dev);
                pm_runtime_put_autosuspend(data->dev);
 
+               if (ret)
+                       return ret;
+
                switch (chan->address) {
                case TEMPERATURE:
                        *val = t;
@@ -733,7 +734,7 @@ static struct i2c_driver tmag5273_driver = {
                .of_match_table = tmag5273_of_match,
                .pm = pm_ptr(&tmag5273_pm_ops),
        },
-       .probe_new = tmag5273_probe,
+       .probe = tmag5273_probe,
        .id_table = tmag5273_id,
 };
 module_i2c_driver(tmag5273_driver);
index 753717158b073c24884dcad168107957733acd59..c5e485bfc6fc03d9ba92e70ef1de014fca6ab4a4 100644 (file)
@@ -1605,7 +1605,7 @@ static struct i2c_driver yas5xx_driver = {
                .of_match_table = yas5xx_of_match,
                .pm = pm_ptr(&yas5xx_dev_pm_ops),
        },
-       .probe_new = yas5xx_probe,
+       .probe = yas5xx_probe,
        .remove   = yas5xx_remove,
        .id_table = yas5xx_id,
 };
index 01dd3f858d99cb78df9b5dadbaa2b1bf53125cf6..e6a9a3c67845cb961ed5e53d6dce9d6043d7da83 100644 (file)
@@ -136,4 +136,14 @@ config TPL0102
          To compile this driver as a module, choose M here: the
          module will be called tpl0102.
 
+config X9250
+       tristate "Renesas X9250 quad controlled potentiometers"
+       depends on SPI
+       help
+         Enable support for the Renesas X9250 quad controlled
+         potentiometers.
+
+         To compile this driver as a module, choose M here: the module
+         will be called x9250.
+
 endmenu
index 5ebb8e3bbd76cfe620ed0efd7b18137a179c840f..d11fb739176cc922f6dd382c1c0a7e1926434873 100644 (file)
@@ -15,3 +15,4 @@ obj-$(CONFIG_MCP4131) += mcp4131.o
 obj-$(CONFIG_MCP4531) += mcp4531.o
 obj-$(CONFIG_MCP41010) += mcp41010.o
 obj-$(CONFIG_TPL0102) += tpl0102.o
+obj-$(CONFIG_X9250) += x9250.o
index 8fbcce4829898fd5fa1c6d65b53ca6ad11b4f27f..991e745c4f937272db6e178a1d78ce00486788c5 100644 (file)
@@ -334,7 +334,7 @@ static struct i2c_driver ad5110_driver = {
                .name   = "ad5110",
                .of_match_table = ad5110_of_match,
        },
-       .probe_new      = ad5110_probe,
+       .probe          = ad5110_probe,
        .id_table       = ad5110_id,
 };
 module_i2c_driver(ad5110_driver);
index aa140d63210161d736900455ce88726abca57879..b17941e4c2f7c543e64e4eedde642520e0d3e405 100644 (file)
@@ -218,7 +218,7 @@ static struct i2c_driver ad5272_driver = {
                .name   = "ad5272",
                .of_match_table = ad5272_dt_ids,
        },
-       .probe_new      = ad5272_probe,
+       .probe          = ad5272_probe,
        .id_table       = ad5272_id,
 };
 
index 0b5e475807cbcaea920d7fe836090a9c8351e6be..fc183e0790dafb989a1260a6e10526dc458b61db 100644 (file)
@@ -252,7 +252,7 @@ static struct i2c_driver ds1803_driver = {
                .name   = "ds1803",
                .of_match_table = ds1803_dt_ids,
        },
-       .probe_new      = ds1803_probe,
+       .probe          = ds1803_probe,
        .id_table       = ds1803_id,
 };
 
index 94ef27ef3fb57981947e37b665e0647383ad6ef9..c8e2481dadb5330fed5ba0eaa5d29121296c4cc2 100644 (file)
@@ -123,7 +123,7 @@ static struct i2c_driver max5432_driver = {
                .name = "max5432",
                .of_match_table = max5432_dt_ids,
        },
-       .probe_new = max5432_probe,
+       .probe = max5432_probe,
 };
 
 module_i2c_driver(max5432_driver);
index c0e171fec0629a5ab3ce6b8f1c7eed6f4b04ad26..89daecc90305a1893a74c5101a8b3652af66f3b9 100644 (file)
@@ -174,7 +174,7 @@ static struct i2c_driver mcp4018_driver = {
                .name   = "mcp4018",
                .of_match_table = mcp4018_of_match,
        },
-       .probe_new      = mcp4018_probe,
+       .probe          = mcp4018_probe,
        .id_table       = mcp4018_id,
 };
 
index c25f84b4a270b14b482aa9916d6cdc8a90b5eac9..c513c00c82435661636f6ecbb6ab62cae0620b29 100644 (file)
@@ -385,7 +385,7 @@ static struct i2c_driver mcp4531_driver = {
                .name   = "mcp4531",
                .of_match_table = mcp4531_of_match,
        },
-       .probe_new      = mcp4531_probe,
+       .probe          = mcp4531_probe,
        .id_table       = mcp4531_id,
 };
 
index a3465b413b0caa4f22fbadb36464b2e968070568..8923ccb0fc4f793c64e01c5b6c2143255e27ab5c 100644 (file)
@@ -161,7 +161,7 @@ static struct i2c_driver tpl0102_driver = {
        .driver = {
                .name = "tpl0102",
        },
-       .probe_new = tpl0102_probe,
+       .probe = tpl0102_probe,
        .id_table = tpl0102_id,
 };
 
diff --git a/drivers/iio/potentiometer/x9250.c b/drivers/iio/potentiometer/x9250.c
new file mode 100644 (file)
index 0000000..7353484
--- /dev/null
@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * x9250.c  --  Renesas X9250 potentiometers IIO driver
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina <herve.codina@bootlin.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iio/iio.h>
+#include <linux/limits.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+
+struct x9250_cfg {
+       const char *name;
+       int kohms;
+};
+
+struct x9250 {
+       struct spi_device *spi;
+       const struct x9250_cfg *cfg;
+       struct gpio_desc *wp_gpio;
+};
+
+#define X9250_ID               0x50
+#define X9250_CMD_RD_WCR(_p)    (0x90 | (_p))
+#define X9250_CMD_WR_WCR(_p)    (0xa0 | (_p))
+
+static int x9250_write8(struct x9250 *x9250, u8 cmd, u8 val)
+{
+       u8 txbuf[3];
+
+       txbuf[0] = X9250_ID;
+       txbuf[1] = cmd;
+       txbuf[2] = val;
+
+       return spi_write_then_read(x9250->spi, txbuf, ARRAY_SIZE(txbuf), NULL, 0);
+}
+
+static int x9250_read8(struct x9250 *x9250, u8 cmd, u8 *val)
+{
+       u8 txbuf[2];
+
+       txbuf[0] = X9250_ID;
+       txbuf[1] = cmd;
+
+       return spi_write_then_read(x9250->spi, txbuf, ARRAY_SIZE(txbuf), val, 1);
+}
+
+#define X9250_CHANNEL(ch) {                                            \
+       .type = IIO_RESISTANCE,                                         \
+       .indexed = 1,                                                   \
+       .output = 1,                                                    \
+       .channel = (ch),                                                \
+       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),                   \
+       .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),           \
+       .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_RAW),   \
+}
+
+static const struct iio_chan_spec x9250_channels[] = {
+       X9250_CHANNEL(0),
+       X9250_CHANNEL(1),
+       X9250_CHANNEL(2),
+       X9250_CHANNEL(3),
+};
+
+static int x9250_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+                         int *val, int *val2, long mask)
+{
+       struct x9250 *x9250 = iio_priv(indio_dev);
+       int ch = chan->channel;
+       int ret;
+       u8 v;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               ret = x9250_read8(x9250, X9250_CMD_RD_WCR(ch), &v);
+               if (ret)
+                       return ret;
+               *val = v;
+               return IIO_VAL_INT;
+
+       case IIO_CHAN_INFO_SCALE:
+               *val = 1000 * x9250->cfg->kohms;
+               *val2 = U8_MAX;
+               return IIO_VAL_FRACTIONAL;
+       }
+
+       return -EINVAL;
+}
+
+static int x9250_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+                           const int **vals, int *type, int *length, long mask)
+{
+       static const int range[] = {0, 1, 255}; /* min, step, max */
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               *length = ARRAY_SIZE(range);
+               *vals = range;
+               *type = IIO_VAL_INT;
+               return IIO_AVAIL_RANGE;
+       }
+
+       return -EINVAL;
+}
+
+static int x9250_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+                          int val, int val2, long mask)
+{
+       struct x9250 *x9250 = iio_priv(indio_dev);
+       int ch = chan->channel;
+       int ret;
+
+       if (mask != IIO_CHAN_INFO_RAW)
+               return -EINVAL;
+
+       if (val > U8_MAX || val < 0)
+               return -EINVAL;
+
+       gpiod_set_value_cansleep(x9250->wp_gpio, 0);
+       ret = x9250_write8(x9250, X9250_CMD_WR_WCR(ch), val);
+       gpiod_set_value_cansleep(x9250->wp_gpio, 1);
+
+       return ret;
+}
+
+static const struct iio_info x9250_info = {
+       .read_raw = x9250_read_raw,
+       .read_avail = x9250_read_avail,
+       .write_raw = x9250_write_raw,
+};
+
+enum x9250_type {
+       X9250T,
+       X9250U,
+};
+
+static const struct x9250_cfg x9250_cfg[] = {
+       [X9250T] = { .name = "x9250t", .kohms =  100, },
+       [X9250U] = { .name = "x9250u", .kohms =  50, },
+};
+
+static const char *const x9250_regulator_names[] = {
+       "vcc",
+       "avp",
+       "avn",
+};
+
+static int x9250_probe(struct spi_device *spi)
+{
+       struct iio_dev *indio_dev;
+       struct x9250 *x9250;
+       int ret;
+
+       ret = devm_regulator_bulk_get_enable(&spi->dev, ARRAY_SIZE(x9250_regulator_names),
+                                            x9250_regulator_names);
+       if (ret)
+               return dev_err_probe(&spi->dev, ret, "Failed to get regulators\n");
+
+       /*
+        * The x9250 needs a 5ms maximum delay after the power-supplies are set
+        * before performing the first write (1ms for the first read).
+        */
+       usleep_range(5000, 6000);
+
+       indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*x9250));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       x9250 = iio_priv(indio_dev);
+       x9250->spi = spi;
+       x9250->cfg = spi_get_device_match_data(spi);
+       x9250->wp_gpio = devm_gpiod_get_optional(&spi->dev, "wp", GPIOD_OUT_LOW);
+       if (IS_ERR(x9250->wp_gpio))
+               return dev_err_probe(&spi->dev, PTR_ERR(x9250->wp_gpio),
+                                    "failed to get wp gpio\n");
+
+       indio_dev->info = &x9250_info;
+       indio_dev->channels = x9250_channels;
+       indio_dev->num_channels = ARRAY_SIZE(x9250_channels);
+       indio_dev->name = x9250->cfg->name;
+
+       return devm_iio_device_register(&spi->dev, indio_dev);
+}
+
+static const struct of_device_id x9250_of_match[] = {
+       { .compatible = "renesas,x9250t", .data = &x9250_cfg[X9250T]},
+       { .compatible = "renesas,x9250u", .data = &x9250_cfg[X9250U]},
+       { }
+};
+MODULE_DEVICE_TABLE(of, x9250_of_match);
+
+static const struct spi_device_id x9250_id_table[] = {
+       { "x9250t", (kernel_ulong_t)&x9250_cfg[X9250T] },
+       { "x9250u", (kernel_ulong_t)&x9250_cfg[X9250U] },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, x9250_id_table);
+
+static struct spi_driver x9250_spi_driver = {
+       .driver  = {
+               .name = "x9250",
+               .of_match_table = x9250_of_match,
+       },
+       .id_table = x9250_id_table,
+       .probe  = x9250_probe,
+};
+
+module_spi_driver(x9250_spi_driver);
+
+MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
+MODULE_DESCRIPTION("X9250 ALSA SoC driver");
+MODULE_LICENSE("GPL");
index 0083e858c21ecbc7f1e9674bb18c9176c8f94c15..bd0f2c3bf2f2d0b33c3f613bf77f6b355bc44fcb 100644 (file)
@@ -416,7 +416,7 @@ static struct i2c_driver lmp91000_driver = {
                .name = LMP91000_DRV_NAME,
                .of_match_table = lmp91000_of_match,
        },
-       .probe_new = lmp91000_probe,
+       .probe = lmp91000_probe,
        .remove = lmp91000_remove,
        .id_table = lmp91000_id,
 };
index 02b97e89de505d249b7408c51a17c165b9508f64..7b4c2af32852f6e5849be8402b6aaa9bb8291816 100644 (file)
@@ -148,6 +148,19 @@ config MPL3115
          To compile this driver as a module, choose M here: the module
          will be called mpl3115.
 
+config MPRLS0025PA
+       tristate "Honeywell MPRLS0025PA (MicroPressure sensors series)"
+       depends on I2C
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
+       help
+         Say Y here to build support for the Honeywell MicroPressure pressure
+         sensor series. There are many different types with different pressure
+         range. These ranges can be set up in the device tree.
+
+         To compile this driver as a module, choose M here: the module will be
+         called mprls0025pa.
+
 config MS5611
        tristate "Measurement Specialties MS5611 pressure sensor driver"
        select IIO_BUFFER
index 083ae87ff48f5d24c9931de8549100f6a6cdef45..c90f77210e94d9079b4e8655aa8a75e8e36d8987 100644 (file)
@@ -19,6 +19,7 @@ obj-$(CONFIG_MPL115) += mpl115.o
 obj-$(CONFIG_MPL115_I2C) += mpl115_i2c.o
 obj-$(CONFIG_MPL115_SPI) += mpl115_spi.o
 obj-$(CONFIG_MPL3115) += mpl3115.o
+obj-$(CONFIG_MPRLS0025PA) += mprls0025pa.o
 obj-$(CONFIG_MS5611) += ms5611_core.o
 obj-$(CONFIG_MS5611_I2C) += ms5611_i2c.o
 obj-$(CONFIG_MS5611_SPI) += ms5611_spi.o
index c0140779366aff6e6e14d7c7332f386dadb22e31..752a63c06b44c11c1d935732d00ffac41e5ff591 100644 (file)
@@ -255,7 +255,7 @@ static struct i2c_driver abp060mg_driver = {
        .driver = {
                .name = "abp060mg",
        },
-       .probe_new = abp060mg_probe,
+       .probe = abp060mg_probe,
        .id_table = abp060mg_id_table,
 };
 module_i2c_driver(abp060mg_driver);
index 567b945e6427af979bb8c6adf7f98f73daf2ed3c..dbe630ad05b5a8c820230806b46caecf53904d56 100644 (file)
@@ -56,7 +56,7 @@ static struct i2c_driver bmp280_i2c_driver = {
                .of_match_table = bmp280_of_i2c_match,
                .pm = pm_ptr(&bmp280_dev_pm_ops),
        },
-       .probe_new      = bmp280_i2c_probe,
+       .probe          = bmp280_i2c_probe,
        .id_table       = bmp280_i2c_id,
 };
 module_i2c_driver(bmp280_i2c_driver);
index 43650b048d6295e2f9fac9cd4dc1e20f0e524977..28c8269ba65d31f1547fc0e35c0fc9465c4b9740 100644 (file)
@@ -362,7 +362,7 @@ static struct i2c_driver dlh_driver = {
                .name = "dlhl60d",
                .of_match_table = dlh_of_match,
        },
-       .probe_new = dlh_probe,
+       .probe = dlh_probe,
        .id_table = dlh_id,
 };
 module_i2c_driver(dlh_driver);
index 2af275a24ff9e29fbab8d7aed58a5b63c7e03eea..b10dbf5cf494091a60d281178a7785653b6d2eb1 100644 (file)
@@ -887,7 +887,7 @@ static struct i2c_driver dps310_driver = {
                .name = DPS310_DEV_NAME,
                .acpi_match_table = dps310_acpi_match,
        },
-       .probe_new = dps310_probe,
+       .probe = dps310_probe,
        .id_table = dps310_id,
 };
 module_i2c_driver(dps310_driver);
index bd1f71a99cfa3d24f96b947514117224ce1de2c0..8bdb279129fa21df271c3b2dfe0ff95571baf667 100644 (file)
@@ -282,7 +282,7 @@ static struct i2c_driver hp03_driver = {
                .name   = "hp03",
                .of_match_table = hp03_of_match,
        },
-       .probe_new      = hp03_probe,
+       .probe          = hp03_probe,
        .id_table       = hp03_id,
 };
 module_i2c_driver(hp03_driver);
index b6d2ff46434194a681bd9e96acf20fdb0256d97e..a072de6cb59c7f82240156e73cc2699fcc29c152 100644 (file)
@@ -409,7 +409,7 @@ MODULE_DEVICE_TABLE(acpi, hp206c_acpi_match);
 #endif
 
 static struct i2c_driver hp206c_driver = {
-       .probe_new = hp206c_probe,
+       .probe = hp206c_probe,
        .id_table = hp206c_id,
        .driver = {
                .name = "hp206c",
index 407cf25ea0e335e7dde1373260db4d01b76f8323..2086f3ef338fefb6519c92b59d461beff15ef596 100644 (file)
@@ -648,7 +648,7 @@ static struct i2c_driver icp10100_driver = {
                .pm = pm_ptr(&icp10100_pm),
                .of_match_table = icp10100_of_match,
        },
-       .probe_new = icp10100_probe,
+       .probe = icp10100_probe,
        .id_table = icp10100_id,
 };
 module_i2c_driver(icp10100_driver);
index ade4dd854ddf1b57f3ef1aa30086d0d1efeb8313..fcbdadf4a51189e34f0b58fc9154fed4ea2e96d6 100644 (file)
@@ -55,7 +55,7 @@ static struct i2c_driver mpl115_i2c_driver = {
                .name   = "mpl115",
                .pm = pm_ptr(&mpl115_dev_pm_ops),
        },
-       .probe_new = mpl115_i2c_probe,
+       .probe = mpl115_i2c_probe,
        .id_table = mpl115_i2c_id,
 };
 module_i2c_driver(mpl115_i2c_driver);
index 72e811a5c96e607bf63e26eb5b755263d916cf26..7aa19584c340c16c836822b93a527570a51e5755 100644 (file)
@@ -335,7 +335,7 @@ static struct i2c_driver mpl3115_driver = {
                .of_match_table = mpl3115_of_match,
                .pm     = pm_sleep_ptr(&mpl3115_pm_ops),
        },
-       .probe_new = mpl3115_probe,
+       .probe = mpl3115_probe,
        .remove = mpl3115_remove,
        .id_table = mpl3115_id,
 };
diff --git a/drivers/iio/pressure/mprls0025pa.c b/drivers/iio/pressure/mprls0025pa.c
new file mode 100644 (file)
index 0000000..30fb2de
--- /dev/null
@@ -0,0 +1,450 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * MPRLS0025PA - Honeywell MicroPressure pressure sensor series driver
+ *
+ * Copyright (c) Andreas Klinger <ak@it-klinger.de>
+ *
+ * Data sheet:
+ *  https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/
+ *    products/sensors/pressure-sensors/board-mount-pressure-sensors/
+ *    micropressure-mpr-series/documents/
+ *    sps-siot-mpr-series-datasheet-32332628-ciid-172626.pdf
+ *
+ * 7-bit I2C default slave address: 0x18
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/math64.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/units.h>
+
+#include <linux/gpio/consumer.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#include <linux/regulator/consumer.h>
+
+#include <asm/unaligned.h>
+
+/* bits in i2c status byte */
+#define MPR_I2C_POWER  BIT(6)  /* device is powered */
+#define MPR_I2C_BUSY   BIT(5)  /* device is busy */
+#define MPR_I2C_MEMORY BIT(2)  /* integrity test passed */
+#define MPR_I2C_MATH   BIT(0)  /* internal math saturation */
+
+/*
+ * support _RAW sysfs interface:
+ *
+ * Calculation formula from the datasheet:
+ * pressure = (press_cnt - outputmin) * scale + pmin
+ * with:
+ * * pressure  - measured pressure in Pascal
+ * * press_cnt - raw value read from sensor
+ * * pmin      - minimum pressure range value of sensor (data->pmin)
+ * * pmax      - maximum pressure range value of sensor (data->pmax)
+ * * outputmin - minimum numerical range raw value delivered by sensor
+ *                                             (mpr_func_spec.output_min)
+ * * outputmax - maximum numerical range raw value delivered by sensor
+ *                                             (mpr_func_spec.output_max)
+ * * scale     - (pmax - pmin) / (outputmax - outputmin)
+ *
+ * formula of the userspace:
+ * pressure = (raw + offset) * scale
+ *
+ * Values given to the userspace in sysfs interface:
+ * * raw       - press_cnt
+ * * offset    - (-1 * outputmin) - pmin / scale
+ *                note: With all sensors from the datasheet pmin = 0
+ *                which reduces the offset to (-1 * outputmin)
+ */
+
+/*
+ * transfer function A: 10%   to 90%   of 2^24
+ * transfer function B:  2.5% to 22.5% of 2^24
+ * transfer function C: 20%   to 80%   of 2^24
+ */
+enum mpr_func_id {
+       MPR_FUNCTION_A,
+       MPR_FUNCTION_B,
+       MPR_FUNCTION_C,
+};
+
+struct mpr_func_spec {
+       u32                     output_min;
+       u32                     output_max;
+};
+
+static const struct mpr_func_spec mpr_func_spec[] = {
+       [MPR_FUNCTION_A] = {.output_min = 1677722, .output_max = 15099494},
+       [MPR_FUNCTION_B] = {.output_min =  419430, .output_max =  3774874},
+       [MPR_FUNCTION_C] = {.output_min = 3355443, .output_max = 13421773},
+};
+
+struct mpr_chan {
+       s32                     pres;           /* pressure value */
+       s64                     ts;             /* timestamp */
+};
+
+struct mpr_data {
+       struct i2c_client       *client;
+       struct mutex            lock;           /*
+                                                * access to device during read
+                                                */
+       u32                     pmin;           /* minimal pressure in pascal */
+       u32                     pmax;           /* maximal pressure in pascal */
+       enum mpr_func_id        function;       /* transfer function */
+       u32                     outmin;         /*
+                                                * minimal numerical range raw
+                                                * value from sensor
+                                                */
+       u32                     outmax;         /*
+                                                * maximal numerical range raw
+                                                * value from sensor
+                                                */
+       int                     scale;          /* int part of scale */
+       int                     scale2;         /* nano part of scale */
+       int                     offset;         /* int part of offset */
+       int                     offset2;        /* nano part of offset */
+       struct gpio_desc        *gpiod_reset;   /* reset */
+       int                     irq;            /*
+                                                * end of conversion irq;
+                                                * used to distinguish between
+                                                * irq mode and reading in a
+                                                * loop until data is ready
+                                                */
+       struct completion       completion;     /* handshake from irq to read */
+       struct mpr_chan         chan;           /*
+                                                * channel values for buffered
+                                                * mode
+                                                */
+};
+
+static const struct iio_chan_spec mpr_channels[] = {
+       {
+               .type = IIO_PRESSURE,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                                       BIT(IIO_CHAN_INFO_SCALE) |
+                                       BIT(IIO_CHAN_INFO_OFFSET),
+               .scan_index = 0,
+               .scan_type = {
+                       .sign = 's',
+                       .realbits = 32,
+                       .storagebits = 32,
+                       .endianness = IIO_CPU,
+               },
+       },
+       IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
+static void mpr_reset(struct mpr_data *data)
+{
+       if (data->gpiod_reset) {
+               gpiod_set_value(data->gpiod_reset, 0);
+               udelay(10);
+               gpiod_set_value(data->gpiod_reset, 1);
+       }
+}
+
+/**
+ * mpr_read_pressure() - Read pressure value from sensor via I2C
+ * @data: Pointer to private data struct.
+ * @press: Output value read from sensor.
+ *
+ * Reading from the sensor by sending and receiving I2C telegrams.
+ *
+ * If there is an end of conversion (EOC) interrupt registered the function
+ * waits for a maximum of one second for the interrupt.
+ *
+ * Context: The function can sleep and data->lock should be held when calling it
+ * Return:
+ * * 0         - OK, the pressure value could be read
+ * * -ETIMEDOUT        - Timeout while waiting for the EOC interrupt or busy flag is
+ *               still set after nloops attempts of reading
+ */
+static int mpr_read_pressure(struct mpr_data *data, s32 *press)
+{
+       struct device *dev = &data->client->dev;
+       int ret, i;
+       u8 wdata[] = {0xAA, 0x00, 0x00};
+       s32 status;
+       int nloops = 10;
+       u8 buf[4];
+
+       reinit_completion(&data->completion);
+
+       ret = i2c_master_send(data->client, wdata, sizeof(wdata));
+       if (ret < 0) {
+               dev_err(dev, "error while writing ret: %d\n", ret);
+               return ret;
+       }
+       if (ret != sizeof(wdata)) {
+               dev_err(dev, "received size doesn't fit - ret: %d / %u\n", ret,
+                                                       (u32)sizeof(wdata));
+               return -EIO;
+       }
+
+       if (data->irq > 0) {
+               ret = wait_for_completion_timeout(&data->completion, HZ);
+               if (!ret) {
+                       dev_err(dev, "timeout while waiting for eoc irq\n");
+                       return -ETIMEDOUT;
+               }
+       } else {
+               /* wait until status indicates data is ready */
+               for (i = 0; i < nloops; i++) {
+                       /*
+                        * datasheet only says to wait at least 5 ms for the
+                        * data but leave the maximum response time open
+                        * --> let's try it nloops (10) times which seems to be
+                        *     quite long
+                        */
+                       usleep_range(5000, 10000);
+                       status = i2c_smbus_read_byte(data->client);
+                       if (status < 0) {
+                               dev_err(dev,
+                                       "error while reading, status: %d\n",
+                                       status);
+                               return status;
+                       }
+                       if (!(status & MPR_I2C_BUSY))
+                               break;
+               }
+               if (i == nloops) {
+                       dev_err(dev, "timeout while reading\n");
+                       return -ETIMEDOUT;
+               }
+       }
+
+       ret = i2c_master_recv(data->client, buf, sizeof(buf));
+       if (ret < 0) {
+               dev_err(dev, "error in i2c_master_recv ret: %d\n", ret);
+               return ret;
+       }
+       if (ret != sizeof(buf)) {
+               dev_err(dev, "received size doesn't fit - ret: %d / %u\n", ret,
+                                                       (u32)sizeof(buf));
+               return -EIO;
+       }
+
+       if (buf[0] & MPR_I2C_BUSY) {
+               /*
+                * it should never be the case that status still indicates
+                * business
+                */
+               dev_err(dev, "data still not ready: %08x\n", buf[0]);
+               return -ETIMEDOUT;
+       }
+
+       *press = get_unaligned_be24(&buf[1]);
+
+       dev_dbg(dev, "received: %*ph cnt: %d\n", ret, buf, *press);
+
+       return 0;
+}
+
+static irqreturn_t mpr_eoc_handler(int irq, void *p)
+{
+       struct mpr_data *data = p;
+
+       complete(&data->completion);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t mpr_trigger_handler(int irq, void *p)
+{
+       int ret;
+       struct iio_poll_func *pf = p;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct mpr_data *data = iio_priv(indio_dev);
+
+       mutex_lock(&data->lock);
+       ret = mpr_read_pressure(data, &data->chan.pres);
+       if (ret < 0)
+               goto err;
+
+       iio_push_to_buffers_with_timestamp(indio_dev, &data->chan,
+                                               iio_get_time_ns(indio_dev));
+
+err:
+       mutex_unlock(&data->lock);
+       iio_trigger_notify_done(indio_dev->trig);
+
+       return IRQ_HANDLED;
+}
+
+static int mpr_read_raw(struct iio_dev *indio_dev,
+       struct iio_chan_spec const *chan, int *val, int *val2, long mask)
+{
+       int ret;
+       s32 pressure;
+       struct mpr_data *data = iio_priv(indio_dev);
+
+       if (chan->type != IIO_PRESSURE)
+               return -EINVAL;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               mutex_lock(&data->lock);
+               ret = mpr_read_pressure(data, &pressure);
+               mutex_unlock(&data->lock);
+               if (ret < 0)
+                       return ret;
+               *val = pressure;
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_SCALE:
+               *val = data->scale;
+               *val2 = data->scale2;
+               return IIO_VAL_INT_PLUS_NANO;
+       case IIO_CHAN_INFO_OFFSET:
+               *val = data->offset;
+               *val2 = data->offset2;
+               return IIO_VAL_INT_PLUS_NANO;
+       default:
+               return -EINVAL;
+       }
+}
+
+static const struct iio_info mpr_info = {
+       .read_raw = &mpr_read_raw,
+};
+
+static int mpr_probe(struct i2c_client *client)
+{
+       int ret;
+       struct mpr_data *data;
+       struct iio_dev *indio_dev;
+       struct device *dev = &client->dev;
+       s64 scale, offset;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE))
+               return dev_err_probe(dev, -EOPNOTSUPP,
+                                       "I2C functionality not supported\n");
+
+       indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+       if (!indio_dev)
+               return dev_err_probe(dev, -ENOMEM, "couldn't get iio_dev\n");
+
+       data = iio_priv(indio_dev);
+       data->client = client;
+       data->irq = client->irq;
+
+       mutex_init(&data->lock);
+       init_completion(&data->completion);
+
+       indio_dev->name = "mprls0025pa";
+       indio_dev->info = &mpr_info;
+       indio_dev->channels = mpr_channels;
+       indio_dev->num_channels = ARRAY_SIZE(mpr_channels);
+       indio_dev->modes = INDIO_DIRECT_MODE;
+
+       ret = devm_regulator_get_enable(dev, "vdd");
+       if (ret)
+               return dev_err_probe(dev, ret,
+                               "can't get and enable vdd supply\n");
+
+       if (dev_fwnode(dev)) {
+               ret = device_property_read_u32(dev, "honeywell,pmin-pascal",
+                                                               &data->pmin);
+               if (ret)
+                       return dev_err_probe(dev, ret,
+                               "honeywell,pmin-pascal could not be read\n");
+               ret = device_property_read_u32(dev, "honeywell,pmax-pascal",
+                                                               &data->pmax);
+               if (ret)
+                       return dev_err_probe(dev, ret,
+                               "honeywell,pmax-pascal could not be read\n");
+               ret = device_property_read_u32(dev,
+                               "honeywell,transfer-function", &data->function);
+               if (ret)
+                       return dev_err_probe(dev, ret,
+                               "honeywell,transfer-function could not be read\n");
+               if (data->function > MPR_FUNCTION_C)
+                       return dev_err_probe(dev, -EINVAL,
+                               "honeywell,transfer-function %d invalid\n",
+                                                               data->function);
+       } else {
+               /* when loaded as i2c device we need to use default values */
+               dev_notice(dev, "firmware node not found; using defaults\n");
+               data->pmin = 0;
+               data->pmax = 172369; /* 25 psi */
+               data->function = MPR_FUNCTION_A;
+       }
+
+       data->outmin = mpr_func_spec[data->function].output_min;
+       data->outmax = mpr_func_spec[data->function].output_max;
+
+       /* use 64 bit calculation for preserving a reasonable precision */
+       scale = div_s64(((s64)(data->pmax - data->pmin)) * NANO,
+                                               data->outmax - data->outmin);
+       data->scale = div_s64_rem(scale, NANO, &data->scale2);
+       /*
+        * multiply with NANO before dividing by scale and later divide by NANO
+        * again.
+        */
+       offset = ((-1LL) * (s64)data->outmin) * NANO -
+                       div_s64(div_s64((s64)data->pmin * NANO, scale), NANO);
+       data->offset = div_s64_rem(offset, NANO, &data->offset2);
+
+       if (data->irq > 0) {
+               ret = devm_request_irq(dev, data->irq, mpr_eoc_handler,
+                               IRQF_TRIGGER_RISING, client->name, data);
+               if (ret)
+                       return dev_err_probe(dev, ret,
+                               "request irq %d failed\n", data->irq);
+       }
+
+       data->gpiod_reset = devm_gpiod_get_optional(dev, "reset",
+                                                       GPIOD_OUT_HIGH);
+       if (IS_ERR(data->gpiod_reset))
+               return dev_err_probe(dev, PTR_ERR(data->gpiod_reset),
+                                               "request reset-gpio failed\n");
+
+       mpr_reset(data);
+
+       ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
+                                               mpr_trigger_handler, NULL);
+       if (ret)
+               return dev_err_probe(dev, ret,
+                                       "iio triggered buffer setup failed\n");
+
+       ret = devm_iio_device_register(dev, indio_dev);
+       if (ret)
+               return dev_err_probe(dev, ret,
+                                       "unable to register iio device\n");
+
+       return 0;
+}
+
+static const struct of_device_id mpr_matches[] = {
+       { .compatible = "honeywell,mprls0025pa" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, mpr_matches);
+
+static const struct i2c_device_id mpr_id[] = {
+       { "mprls0025pa" },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, mpr_id);
+
+static struct i2c_driver mpr_driver = {
+       .probe          = mpr_probe,
+       .id_table       = mpr_id,
+       .driver         = {
+               .name           = "mprls0025pa",
+               .of_match_table = mpr_matches,
+       },
+};
+module_i2c_driver(mpr_driver);
+
+MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
+MODULE_DESCRIPTION("Honeywell MPRLS0025PA I2C driver");
+MODULE_LICENSE("GPL");
index e3c68a3ed76ace11148cd034e231a4d3bca85ca2..9a0f52321fcb9d9bbf08acb4b5e527aea7caa8ba 100644 (file)
@@ -125,7 +125,7 @@ static struct i2c_driver ms5611_driver = {
                .of_match_table = ms5611_i2c_matches,
        },
        .id_table = ms5611_id,
-       .probe_new = ms5611_i2c_probe,
+       .probe = ms5611_i2c_probe,
 };
 module_i2c_driver(ms5611_driver);
 
index c4981b29dccb1716c87af5a793962d81c709c7d6..9b3abffb724b600d5ed6a25d4691937d3b5d0a64 100644 (file)
@@ -238,7 +238,7 @@ static const struct of_device_id ms5637_of_match[] = {
 MODULE_DEVICE_TABLE(of, ms5637_of_match);
 
 static struct i2c_driver ms5637_driver = {
-       .probe_new = ms5637_probe,
+       .probe = ms5637_probe,
        .id_table = ms5637_id,
        .driver = {
                   .name = "ms5637",
index f2c3bb568d16ba3f1bb71b37f8ec450090757c96..5101552e3f3849dd9b9660438a50ad482b51f56f 100644 (file)
@@ -116,7 +116,7 @@ static struct i2c_driver st_press_driver = {
                .of_match_table = st_press_of_match,
                .acpi_match_table = ACPI_PTR(st_press_acpi_match),
        },
-       .probe_new = st_press_i2c_probe,
+       .probe = st_press_i2c_probe,
        .id_table = st_press_id_table,
 };
 module_i2c_driver(st_press_driver);
index 2fbf14aff03392e29d6b58bf585f85084d21ef6d..a6463c06975eb5fcb416cea086941fa6c7d0e17a 100644 (file)
@@ -260,7 +260,7 @@ static struct i2c_driver t5403_driver = {
        .driver = {
                .name   = "t5403",
        },
-       .probe_new = t5403_probe,
+       .probe = t5403_probe,
        .id_table = t5403_id,
 };
 module_i2c_driver(t5403_driver);
index ade465014be1ed61f7910689ce442771b2200d97..c7fffbe7c788ab3263e45c78c348433a3f9257da 100644 (file)
@@ -76,7 +76,7 @@ static struct i2c_driver zpa2326_i2c_driver = {
                .of_match_table = zpa2326_i2c_matches,
                .pm             = ZPA2326_PM_OPS,
        },
-       .probe_new = zpa2326_probe_i2c,
+       .probe = zpa2326_probe_i2c,
        .remove   = zpa2326_remove_i2c,
        .id_table = zpa2326_i2c_ids,
 };
index 7b8f40b7ccf33081654b6d4dcdf95f06677bd457..fe45ca35a124e53c7a6c44b799a1c48e755c85c4 100644 (file)
@@ -1008,7 +1008,7 @@ static struct i2c_driver isl29501_driver = {
                .name   = "isl29501",
        },
        .id_table       = isl29501_id,
-       .probe_new      = isl29501_probe,
+       .probe          = isl29501_probe,
 };
 module_i2c_driver(isl29501_driver);
 
index e70cac8240afc7d72d1d8d172b22ad3a6e76c0aa..fb1073c8d9f7892fce9a3df61a89bf801a885ec7 100644 (file)
@@ -264,7 +264,7 @@ static struct i2c_driver mb1232_driver = {
                .name   = "maxbotix-mb1232",
                .of_match_table = of_mb1232_match,
        },
-       .probe_new = mb1232_probe,
+       .probe = mb1232_probe,
        .id_table = mb1232_id,
 };
 module_i2c_driver(mb1232_driver);
index c9eead01a0314c92affc6cef7f3a7d33f4e8d7e4..2913d5e0fe4f99576ed2b7cf7e5c0645e6844c94 100644 (file)
@@ -365,7 +365,7 @@ static struct i2c_driver lidar_driver = {
                .of_match_table = lidar_dt_ids,
                .pm     = pm_ptr(&lidar_pm_ops),
        },
-       .probe_new      = lidar_probe,
+       .probe          = lidar_probe,
        .remove         = lidar_remove,
        .id_table       = lidar_id,
 };
index 44f72b78bd5063a797c10e3f12d7f570575495fd..f02e83e3f15f34628da3be5fab40d6d3e5befd21 100644 (file)
@@ -318,7 +318,7 @@ static struct i2c_driver rfd77402_driver = {
                .name   = RFD77402_DRV_NAME,
                .pm     = pm_sleep_ptr(&rfd77402_pm_ops),
        },
-       .probe_new = rfd77402_probe,
+       .probe = rfd77402_probe,
        .id_table = rfd77402_id,
 };
 
index 61866d0440f76f7827ee6d64aea51395d96d9da3..a75ea50428767cba22bc5306460674762aa5b9b1 100644 (file)
@@ -549,7 +549,7 @@ static struct i2c_driver srf08_driver = {
                .name   = "srf08",
                .of_match_table = of_srf08_match,
        },
-       .probe_new = srf08_probe,
+       .probe = srf08_probe,
        .id_table = srf08_id,
 };
 module_i2c_driver(srf08_driver);
index 0e4747ccd3cf74c6c2cb7ebc64a4d80b730ba1aa..d977aacb74919a3473039cea004cb32d1c8bfaa8 100644 (file)
@@ -1050,7 +1050,7 @@ static struct i2c_driver sx9310_driver = {
                 */
                .probe_type = PROBE_PREFER_ASYNCHRONOUS,
        },
-       .probe_new      = sx9310_probe,
+       .probe          = sx9310_probe,
        .id_table       = sx9310_id,
 };
 module_i2c_driver(sx9310_driver);
index 9a40ca32bb1ca637dd5f5837390a4049f41cabe5..438f9c9aba6eaf9b8135bd6bb697798db72c25a4 100644 (file)
@@ -1152,7 +1152,7 @@ static struct i2c_driver sx9324_driver = {
                 */
                .probe_type = PROBE_PREFER_ASYNCHRONOUS,
        },
-       .probe_new      = sx9324_probe,
+       .probe          = sx9324_probe,
        .id_table       = sx9324_id,
 };
 module_i2c_driver(sx9324_driver);
index a50d9176411a1345b89444a0f94bd79db18994ab..2c4e14a4fe9fbde8005bbdc1807e20f3c5b218f3 100644 (file)
@@ -896,7 +896,7 @@ static struct i2c_driver sx9360_driver = {
                 */
                .probe_type = PROBE_PREFER_ASYNCHRONOUS,
        },
-       .probe_new      = sx9360_probe,
+       .probe          = sx9360_probe,
        .id_table       = sx9360_id,
 };
 module_i2c_driver(sx9360_driver);
index 9b2cfcade6a49bf4f1f4d558d6f9d6e80ac6dc65..550e7d3cd5ee5ed2346d7ca0319fe2640471a8e8 100644 (file)
@@ -1055,7 +1055,7 @@ static struct i2c_driver sx9500_driver = {
                .of_match_table = sx9500_of_match,
                .pm = pm_sleep_ptr(&sx9500_pm_ops),
        },
-       .probe_new      = sx9500_probe,
+       .probe          = sx9500_probe,
        .remove         = sx9500_remove,
        .id_table       = sx9500_id,
 };
index cbc8400c773c4664da5fe7e8677846999cbe8a4e..d1ddf85f53836ec34464d382426b187804964a57 100644 (file)
@@ -662,7 +662,7 @@ static struct i2c_driver vcnl3020_driver = {
                .name   = "vcnl3020",
                .of_match_table = vcnl3020_of_match,
        },
-       .probe_new  = vcnl3020_probe,
+       .probe      = vcnl3020_probe,
 };
 module_i2c_driver(vcnl3020_driver);
 
index c7c4d33d340f0adfa701464b0569728156f3b2f5..2cea64bea9098657bd482c52223c12836e984404 100644 (file)
@@ -294,7 +294,7 @@ static struct i2c_driver vl53l0x_driver = {
                .name = "vl53l0x-i2c",
                .of_match_table = st_vl53l0x_dt_match,
        },
-       .probe_new = vl53l0x_probe,
+       .probe = vl53l0x_probe,
        .id_table = vl53l0x_id,
 };
 module_i2c_driver(vl53l0x_driver);
index c85c21474711f47d8a345271b135d6c7645cfb5b..48be03852cd8dfa869ebe244be7458758e1c1fb4 100644 (file)
@@ -242,7 +242,7 @@ static struct i2c_driver max30208_driver = {
                .of_match_table = max30208_of_match,
                .acpi_match_table = max30208_acpi_match,
        },
-       .probe_new = max30208_probe,
+       .probe = max30208_probe,
        .id_table = max30208_id_table,
 };
 module_i2c_driver(max30208_driver);
index 909fadb623491ee7fe0ef940772aeba48371cf6e..676dc870192443e023c4d6596c127b380687fd30 100644 (file)
@@ -1,12 +1,15 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * mlx90614.c - Support for Melexis MLX90614 contactless IR temperature sensor
+ * mlx90614.c - Support for Melexis MLX90614/MLX90615 contactless IR temperature sensor
  *
  * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
  * Copyright (c) 2015 Essensium NV
  * Copyright (c) 2015 Melexis
  *
- * Driver for the Melexis MLX90614 I2C 16-bit IR thermopile sensor
+ * Driver for the Melexis MLX90614/MLX90615 I2C 16-bit IR thermopile sensor
+ *
+ * MLX90614 - 17-bit ADC + MLX90302 DSP
+ * MLX90615 - 16-bit ADC + MLX90325 DSP
  *
  * (7-bit I2C slave address 0x5a, 100KHz bus speed only!)
  *
  * the "wakeup" GPIO is not given, power management will be disabled.
  */
 
+#include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/delay.h>
 #include <linux/jiffies.h>
-#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/pm_runtime.h>
 
 #include <linux/iio/iio.h>
 #define MLX90614_OP_EEPROM     0x20
 #define MLX90614_OP_SLEEP      0xff
 
-/* RAM offsets with 16-bit data, MSB first */
-#define MLX90614_RAW1  (MLX90614_OP_RAM | 0x04) /* raw data IR channel 1 */
-#define MLX90614_RAW2  (MLX90614_OP_RAM | 0x05) /* raw data IR channel 2 */
-#define MLX90614_TA    (MLX90614_OP_RAM | 0x06) /* ambient temperature */
-#define MLX90614_TOBJ1 (MLX90614_OP_RAM | 0x07) /* object 1 temperature */
-#define MLX90614_TOBJ2 (MLX90614_OP_RAM | 0x08) /* object 2 temperature */
-
-/* EEPROM offsets with 16-bit data, MSB first */
-#define MLX90614_EMISSIVITY    (MLX90614_OP_EEPROM | 0x04) /* emissivity correction coefficient */
-#define MLX90614_CONFIG                (MLX90614_OP_EEPROM | 0x05) /* configuration register */
+#define MLX90615_OP_EEPROM     0x10
+#define MLX90615_OP_RAM                0x20
+#define MLX90615_OP_SLEEP      0xc6
 
 /* Control bits in configuration register */
 #define MLX90614_CONFIG_IIR_SHIFT 0 /* IIR coefficient */
 #define MLX90614_CONFIG_DUAL_MASK (1 << MLX90614_CONFIG_DUAL_SHIFT)
 #define MLX90614_CONFIG_FIR_SHIFT 8 /* FIR coefficient */
 #define MLX90614_CONFIG_FIR_MASK (0x7 << MLX90614_CONFIG_FIR_SHIFT)
-#define MLX90614_CONFIG_GAIN_SHIFT 11 /* gain */
-#define MLX90614_CONFIG_GAIN_MASK (0x7 << MLX90614_CONFIG_GAIN_SHIFT)
+
+#define MLX90615_CONFIG_IIR_SHIFT 12 /* IIR coefficient */
+#define MLX90615_CONFIG_IIR_MASK (0x7 << MLX90615_CONFIG_IIR_SHIFT)
 
 /* Timings (in ms) */
 #define MLX90614_TIMING_EEPROM 20 /* time for EEPROM write/erase to complete */
 #define MLX90614_TIMING_WAKEUP 34 /* time to hold SDA low for wake-up */
 #define MLX90614_TIMING_STARTUP 250 /* time before first data after wake-up */
 
+#define MLX90615_TIMING_WAKEUP 22 /* time to hold SCL low for wake-up */
+
 #define MLX90614_AUTOSLEEP_DELAY 5000 /* default autosleep delay */
 
 /* Magic constants */
 #define MLX90614_CONST_OFFSET_DEC -13657 /* decimal part of the Kelvin offset */
 #define MLX90614_CONST_OFFSET_REM 500000 /* remainder of offset (273.15*50) */
 #define MLX90614_CONST_SCALE 20 /* Scale in milliKelvin (0.02 * 1000) */
-#define MLX90614_CONST_RAW_EMISSIVITY_MAX 65535 /* max value for emissivity */
-#define MLX90614_CONST_EMISSIVITY_RESOLUTION 15259 /* 1/65535 ~ 0.000015259 */
 #define MLX90614_CONST_FIR 0x7 /* Fixed value for FIR part of low pass filter */
 
+/* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */
+#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
+#define field_prep(_mask, _val)        (((_val) << (ffs(_mask) - 1)) & (_mask))
+
+struct mlx_chip_info {
+       /* EEPROM offsets with 16-bit data, MSB first */
+       /* emissivity correction coefficient */
+       u8                      op_eeprom_emissivity;
+       u8                      op_eeprom_config1;
+       /* RAM offsets with 16-bit data, MSB first */
+       /* ambient temperature */
+       u8                      op_ram_ta;
+       /* object 1 temperature */
+       u8                      op_ram_tobj1;
+       /* object 2 temperature */
+       u8                      op_ram_tobj2;
+       u8                      op_sleep;
+       /* support for two input channels (MLX90614 only) */
+       u8                      dual_channel;
+       u8                      wakeup_delay_ms;
+       u16                     emissivity_max;
+       u16                     fir_config_mask;
+       u16                     iir_config_mask;
+       int                     iir_valid_offset;
+       u16                     iir_values[8];
+       int                     iir_freqs[8][2];
+};
+
 struct mlx90614_data {
        struct i2c_client *client;
        struct mutex lock; /* for EEPROM access only */
        struct gpio_desc *wakeup_gpio; /* NULL to disable sleep/wake-up */
+       const struct mlx_chip_info *chip_info; /* Chip hardware details */
        unsigned long ready_timestamp; /* in jiffies */
 };
 
-/* Bandwidth values for IIR filtering */
-static const int mlx90614_iir_values[] = {77, 31, 20, 15, 723, 153, 110, 86};
-static const int mlx90614_freqs[][2] = {
-       {0, 150000},
-       {0, 200000},
-       {0, 310000},
-       {0, 770000},
-       {0, 860000},
-       {1, 100000},
-       {1, 530000},
-       {7, 230000}
-};
-
 /*
  * Erase an address and write word.
  * The mutex must be locked before calling.
@@ -129,21 +143,26 @@ static s32 mlx90614_write_word(const struct i2c_client *client, u8 command,
 }
 
 /*
- * Find the IIR value inside mlx90614_iir_values array and return its position
+ * Find the IIR value inside iir_values array and return its position
  * which is equivalent to the bit value in sensor register
  */
 static inline s32 mlx90614_iir_search(const struct i2c_client *client,
                                      int value)
 {
+       struct iio_dev *indio_dev = i2c_get_clientdata(client);
+       struct mlx90614_data *data = iio_priv(indio_dev);
+       const struct mlx_chip_info *chip_info = data->chip_info;
        int i;
        s32 ret;
 
-       for (i = 0; i < ARRAY_SIZE(mlx90614_iir_values); ++i) {
-               if (value == mlx90614_iir_values[i])
+       for (i = chip_info->iir_valid_offset;
+            i < ARRAY_SIZE(chip_info->iir_values);
+            i++) {
+               if (value == chip_info->iir_values[i])
                        break;
        }
 
-       if (i == ARRAY_SIZE(mlx90614_iir_values))
+       if (i == ARRAY_SIZE(chip_info->iir_values))
                return -EINVAL;
 
        /*
@@ -151,17 +170,21 @@ static inline s32 mlx90614_iir_search(const struct i2c_client *client,
         * we must read them before we actually write
         * changes
         */
-       ret = i2c_smbus_read_word_data(client, MLX90614_CONFIG);
+       ret = i2c_smbus_read_word_data(client, chip_info->op_eeprom_config1);
        if (ret < 0)
                return ret;
 
-       ret &= ~MLX90614_CONFIG_FIR_MASK;
-       ret |= MLX90614_CONST_FIR << MLX90614_CONFIG_FIR_SHIFT;
-       ret &= ~MLX90614_CONFIG_IIR_MASK;
-       ret |= i << MLX90614_CONFIG_IIR_SHIFT;
+       /* Modify FIR on parts which have configurable FIR filter */
+       if (chip_info->fir_config_mask) {
+               ret &= ~chip_info->fir_config_mask;
+               ret |= field_prep(chip_info->fir_config_mask, MLX90614_CONST_FIR);
+       }
+
+       ret &= ~chip_info->iir_config_mask;
+       ret |= field_prep(chip_info->iir_config_mask, i);
 
        /* Write changed values */
-       ret = mlx90614_write_word(client, MLX90614_CONFIG, ret);
+       ret = mlx90614_write_word(client, chip_info->op_eeprom_config1, ret);
        return ret;
 }
 
@@ -221,22 +244,26 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev,
                            int *val2, long mask)
 {
        struct mlx90614_data *data = iio_priv(indio_dev);
-       u8 cmd;
+       const struct mlx_chip_info *chip_info = data->chip_info;
+       u8 cmd, idx;
        s32 ret;
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW: /* 0.02K / LSB */
                switch (channel->channel2) {
                case IIO_MOD_TEMP_AMBIENT:
-                       cmd = MLX90614_TA;
+                       cmd = chip_info->op_ram_ta;
                        break;
                case IIO_MOD_TEMP_OBJECT:
+                       if (chip_info->dual_channel && channel->channel)
+                               return -EINVAL;
+
                        switch (channel->channel) {
                        case 0:
-                               cmd = MLX90614_TOBJ1;
+                               cmd = chip_info->op_ram_tobj1;
                                break;
                        case 1:
-                               cmd = MLX90614_TOBJ2;
+                               cmd = chip_info->op_ram_tobj2;
                                break;
                        default:
                                return -EINVAL;
@@ -268,45 +295,48 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                *val = MLX90614_CONST_SCALE;
                return IIO_VAL_INT;
-       case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */
+       case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/emissivity_max / LSB */
                ret = mlx90614_power_get(data, false);
                if (ret < 0)
                        return ret;
 
                mutex_lock(&data->lock);
                ret = i2c_smbus_read_word_data(data->client,
-                                              MLX90614_EMISSIVITY);
+                                              chip_info->op_eeprom_emissivity);
                mutex_unlock(&data->lock);
                mlx90614_power_put(data);
 
                if (ret < 0)
                        return ret;
 
-               if (ret == MLX90614_CONST_RAW_EMISSIVITY_MAX) {
+               if (ret == chip_info->emissivity_max) {
                        *val = 1;
                        *val2 = 0;
                } else {
                        *val = 0;
-                       *val2 = ret * MLX90614_CONST_EMISSIVITY_RESOLUTION;
+                       *val2 = ret * NSEC_PER_SEC / chip_info->emissivity_max;
                }
                return IIO_VAL_INT_PLUS_NANO;
-       case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* IIR setting with
-                                                            FIR = 1024 */
+       /* IIR setting with FIR=1024 (MLX90614) or FIR=65536 (MLX90615) */
+       case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
                ret = mlx90614_power_get(data, false);
                if (ret < 0)
                        return ret;
 
                mutex_lock(&data->lock);
-               ret = i2c_smbus_read_word_data(data->client, MLX90614_CONFIG);
+               ret = i2c_smbus_read_word_data(data->client,
+                                              chip_info->op_eeprom_config1);
                mutex_unlock(&data->lock);
                mlx90614_power_put(data);
 
                if (ret < 0)
                        return ret;
 
-               *val = mlx90614_iir_values[ret & MLX90614_CONFIG_IIR_MASK] / 100;
-               *val2 = (mlx90614_iir_values[ret & MLX90614_CONFIG_IIR_MASK] % 100) *
-                       10000;
+               idx = field_get(chip_info->iir_config_mask, ret) -
+                     chip_info->iir_valid_offset;
+
+               *val = chip_info->iir_values[idx] / 100;
+               *val2 = (chip_info->iir_values[idx] % 100) * 10000;
                return IIO_VAL_INT_PLUS_MICRO;
        default:
                return -EINVAL;
@@ -318,22 +348,23 @@ static int mlx90614_write_raw(struct iio_dev *indio_dev,
                             int val2, long mask)
 {
        struct mlx90614_data *data = iio_priv(indio_dev);
+       const struct mlx_chip_info *chip_info = data->chip_info;
        s32 ret;
 
        switch (mask) {
-       case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */
+       case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/emissivity_max / LSB */
                if (val < 0 || val2 < 0 || val > 1 || (val == 1 && val2 != 0))
                        return -EINVAL;
-               val = val * MLX90614_CONST_RAW_EMISSIVITY_MAX +
-                       val2 / MLX90614_CONST_EMISSIVITY_RESOLUTION;
+               val = val * chip_info->emissivity_max +
+                     val2 * chip_info->emissivity_max / NSEC_PER_SEC;
 
                ret = mlx90614_power_get(data, false);
                if (ret < 0)
                        return ret;
 
                mutex_lock(&data->lock);
-               ret = mlx90614_write_word(data->client, MLX90614_EMISSIVITY,
-                                         val);
+               ret = mlx90614_write_word(data->client,
+                                         chip_info->op_eeprom_emissivity, val);
                mutex_unlock(&data->lock);
                mlx90614_power_put(data);
 
@@ -377,11 +408,15 @@ static int mlx90614_read_avail(struct iio_dev *indio_dev,
                               const int **vals, int *type, int *length,
                               long mask)
 {
+       struct mlx90614_data *data = iio_priv(indio_dev);
+       const struct mlx_chip_info *chip_info = data->chip_info;
+
        switch (mask) {
        case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
-               *vals = (int *)mlx90614_freqs;
+               *vals = (int *)chip_info->iir_freqs;
                *type = IIO_VAL_INT_PLUS_MICRO;
-               *length = 2 * ARRAY_SIZE(mlx90614_freqs);
+               *length = 2 * (ARRAY_SIZE(chip_info->iir_freqs) -
+                              chip_info->iir_valid_offset);
                return IIO_AVAIL_LIST;
        default:
                return -EINVAL;
@@ -435,6 +470,7 @@ static const struct iio_info mlx90614_info = {
 #ifdef CONFIG_PM
 static int mlx90614_sleep(struct mlx90614_data *data)
 {
+       const struct mlx_chip_info *chip_info = data->chip_info;
        s32 ret;
 
        if (!data->wakeup_gpio) {
@@ -447,7 +483,7 @@ static int mlx90614_sleep(struct mlx90614_data *data)
        mutex_lock(&data->lock);
        ret = i2c_smbus_xfer(data->client->adapter, data->client->addr,
                             data->client->flags | I2C_CLIENT_PEC,
-                            I2C_SMBUS_WRITE, MLX90614_OP_SLEEP,
+                            I2C_SMBUS_WRITE, chip_info->op_sleep,
                             I2C_SMBUS_BYTE, NULL);
        mutex_unlock(&data->lock);
 
@@ -456,6 +492,8 @@ static int mlx90614_sleep(struct mlx90614_data *data)
 
 static int mlx90614_wakeup(struct mlx90614_data *data)
 {
+       const struct mlx_chip_info *chip_info = data->chip_info;
+
        if (!data->wakeup_gpio) {
                dev_dbg(&data->client->dev, "Wake-up disabled");
                return -ENOSYS;
@@ -465,7 +503,7 @@ static int mlx90614_wakeup(struct mlx90614_data *data)
 
        i2c_lock_bus(data->client->adapter, I2C_LOCK_ROOT_ADAPTER);
        gpiod_direction_output(data->wakeup_gpio, 0);
-       msleep(MLX90614_TIMING_WAKEUP);
+       msleep(chip_info->wakeup_delay_ms);
        gpiod_direction_input(data->wakeup_gpio);
        i2c_unlock_bus(data->client->adapter, I2C_LOCK_ROOT_ADAPTER);
 
@@ -478,7 +516,7 @@ static int mlx90614_wakeup(struct mlx90614_data *data)
         * If the read fails, the controller will probably be reset so that
         * further reads will work.
         */
-       i2c_smbus_read_word_data(data->client, MLX90614_CONFIG);
+       i2c_smbus_read_word_data(data->client, chip_info->op_eeprom_config1);
 
        return 0;
 }
@@ -527,9 +565,15 @@ static inline struct gpio_desc *mlx90614_probe_wakeup(struct i2c_client *client)
 /* Return 0 for single sensor, 1 for dual sensor, <0 on error. */
 static int mlx90614_probe_num_ir_sensors(struct i2c_client *client)
 {
+       struct iio_dev *indio_dev = i2c_get_clientdata(client);
+       struct mlx90614_data *data = iio_priv(indio_dev);
+       const struct mlx_chip_info *chip_info = data->chip_info;
        s32 ret;
 
-       ret = i2c_smbus_read_word_data(client, MLX90614_CONFIG);
+       if (chip_info->dual_channel)
+               return 0;
+
+       ret = i2c_smbus_read_word_data(client, chip_info->op_eeprom_config1);
 
        if (ret < 0)
                return ret;
@@ -556,6 +600,7 @@ static int mlx90614_probe(struct i2c_client *client)
        data->client = client;
        mutex_init(&data->lock);
        data->wakeup_gpio = mlx90614_probe_wakeup(client);
+       data->chip_info = device_get_match_data(&client->dev);
 
        mlx90614_wakeup(data);
 
@@ -605,14 +650,68 @@ static void mlx90614_remove(struct i2c_client *client)
        }
 }
 
+static const struct mlx_chip_info mlx90614_chip_info = {
+       .op_eeprom_emissivity           = MLX90614_OP_EEPROM | 0x04,
+       .op_eeprom_config1              = MLX90614_OP_EEPROM | 0x05,
+       .op_ram_ta                      = MLX90614_OP_RAM | 0x06,
+       .op_ram_tobj1                   = MLX90614_OP_RAM | 0x07,
+       .op_ram_tobj2                   = MLX90614_OP_RAM | 0x08,
+       .op_sleep                       = MLX90614_OP_SLEEP,
+       .dual_channel                   = true,
+       .wakeup_delay_ms                = MLX90614_TIMING_WAKEUP,
+       .emissivity_max                 = 65535,
+       .fir_config_mask                = MLX90614_CONFIG_FIR_MASK,
+       .iir_config_mask                = MLX90614_CONFIG_IIR_MASK,
+       .iir_valid_offset               = 0,
+       .iir_values                     = { 77, 31, 20, 15, 723, 153, 110, 86 },
+       .iir_freqs                      = {
+               { 0, 150000 },  /* 13% ~= 0.15 Hz */
+               { 0, 200000 },  /* 17% ~= 0.20 Hz */
+               { 0, 310000 },  /* 25% ~= 0.31 Hz */
+               { 0, 770000 },  /* 50% ~= 0.77 Hz */
+               { 0, 860000 },  /* 57% ~= 0.86 Hz */
+               { 1, 100000 },  /* 67% ~= 1.10 Hz */
+               { 1, 530000 },  /* 80% ~= 1.53 Hz */
+               { 7, 230000 }   /* 100% ~= 7.23 Hz */
+       },
+};
+
+static const struct mlx_chip_info mlx90615_chip_info = {
+       .op_eeprom_emissivity           = MLX90615_OP_EEPROM | 0x03,
+       .op_eeprom_config1              = MLX90615_OP_EEPROM | 0x02,
+       .op_ram_ta                      = MLX90615_OP_RAM | 0x06,
+       .op_ram_tobj1                   = MLX90615_OP_RAM | 0x07,
+       .op_ram_tobj2                   = MLX90615_OP_RAM | 0x08,
+       .op_sleep                       = MLX90615_OP_SLEEP,
+       .dual_channel                   = false,
+       .wakeup_delay_ms                = MLX90615_TIMING_WAKEUP,
+       .emissivity_max                 = 16383,
+       .fir_config_mask                = 0,    /* MLX90615 FIR is fixed */
+       .iir_config_mask                = MLX90615_CONFIG_IIR_MASK,
+       /* IIR value 0 is FORBIDDEN COMBINATION on MLX90615 */
+       .iir_valid_offset               = 1,
+       .iir_values                     = { 500, 50, 30, 20, 15, 13, 10 },
+       .iir_freqs                      = {
+               { 0, 100000 },  /* 14% ~= 0.10 Hz */
+               { 0, 130000 },  /* 17% ~= 0.13 Hz */
+               { 0, 150000 },  /* 20% ~= 0.15 Hz */
+               { 0, 200000 },  /* 25% ~= 0.20 Hz */
+               { 0, 300000 },  /* 33% ~= 0.30 Hz */
+               { 0, 500000 },  /* 50% ~= 0.50 Hz */
+               { 5, 000000 },  /* 100% ~= 5.00 Hz */
+       },
+};
+
 static const struct i2c_device_id mlx90614_id[] = {
-       { "mlx90614", 0 },
+       { "mlx90614", .driver_data = (kernel_ulong_t)&mlx90614_chip_info },
+       { "mlx90615", .driver_data = (kernel_ulong_t)&mlx90615_chip_info },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, mlx90614_id);
 
 static const struct of_device_id mlx90614_of_match[] = {
-       { .compatible = "melexis,mlx90614" },
+       { .compatible = "melexis,mlx90614", .data = &mlx90614_chip_info },
+       { .compatible = "melexis,mlx90615", .data = &mlx90615_chip_info },
        { }
 };
 MODULE_DEVICE_TABLE(of, mlx90614_of_match);
@@ -675,7 +774,7 @@ static struct i2c_driver mlx90614_driver = {
                .of_match_table = mlx90614_of_match,
                .pm     = pm_ptr(&mlx90614_pm_ops),
        },
-       .probe_new = mlx90614_probe,
+       .probe = mlx90614_probe,
        .remove = mlx90614_remove,
        .id_table = mlx90614_id,
 };
index 753b7a4ccfddc2886f01f283fb692c3c16b582b7..8a57be108620af2733bb9f8a170b542960487163 100644 (file)
@@ -1337,7 +1337,7 @@ static struct i2c_driver mlx90632_driver = {
                .of_match_table = mlx90632_of_match,
                .pm     = pm_ptr(&mlx90632_pm_ops),
        },
-       .probe_new = mlx90632_probe,
+       .probe = mlx90632_probe,
        .id_table = mlx90632_id,
 };
 module_i2c_driver(mlx90632_driver);
index cdf08477e63f7bc04649ce2f6ddad2643dba442d..3a3904fe138c116e03b435f1a73cab45af4c42b9 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/i2c.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/mod_devicetable.h>
 #include <linux/pm.h>
 #include <linux/bitops.h>
 
@@ -272,6 +273,12 @@ static int tmp006_resume(struct device *dev)
 
 static DEFINE_SIMPLE_DEV_PM_OPS(tmp006_pm_ops, tmp006_suspend, tmp006_resume);
 
+static const struct of_device_id tmp006_of_match[] = {
+       { .compatible = "ti,tmp006" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, tmp006_of_match);
+
 static const struct i2c_device_id tmp006_id[] = {
        { "tmp006", 0 },
        { }
@@ -281,9 +288,10 @@ MODULE_DEVICE_TABLE(i2c, tmp006_id);
 static struct i2c_driver tmp006_driver = {
        .driver = {
                .name   = "tmp006",
+               .of_match_table = tmp006_of_match,
                .pm     = pm_sleep_ptr(&tmp006_pm_ops),
        },
-       .probe_new = tmp006_probe,
+       .probe = tmp006_probe,
        .id_table = tmp006_id,
 };
 module_i2c_driver(tmp006_driver);
index 8d27aa3bdd6dae45e4b5963d75d519531dfede0e..decef689636238d2bfa7954a5fda885236c0efdd 100644 (file)
@@ -574,7 +574,7 @@ static struct i2c_driver tmp007_driver = {
                .of_match_table = tmp007_of_match,
                .pm     = pm_sleep_ptr(&tmp007_pm_ops),
        },
-       .probe_new      = tmp007_probe,
+       .probe          = tmp007_probe,
        .id_table       = tmp007_id,
 };
 module_i2c_driver(tmp007_driver);
index 638e3a5bd6b84621636a96705d73213ae490ad34..fc02f491688b53622015fa71437a1b7bd3ac17ea 100644 (file)
@@ -217,7 +217,7 @@ static struct i2c_driver tmp117_driver = {
                .name   = "tmp117",
                .of_match_table = tmp117_of_match,
        },
-       .probe_new      = tmp117_probe,
+       .probe          = tmp117_probe,
        .id_table       = tmp117_id,
 };
 module_i2c_driver(tmp117_driver);
index 30b268ba82ccf91521582b2132886c4db68f38db..53ef56fbfe1defd1353382c1ecf73575852363c7 100644 (file)
@@ -218,7 +218,7 @@ static const struct of_device_id tsys01_of_match[] = {
 MODULE_DEVICE_TABLE(of, tsys01_of_match);
 
 static struct i2c_driver tsys01_driver = {
-       .probe_new = tsys01_i2c_probe,
+       .probe = tsys01_i2c_probe,
        .id_table = tsys01_id,
        .driver = {
                   .name = "tsys01",
index cdefe046ab17d784f664f8ddd0119226b5e0fe39..6191db92ef9a53751e26725567bd75e7e80130b1 100644 (file)
@@ -174,7 +174,7 @@ static const struct i2c_device_id tsys02d_id[] = {
 MODULE_DEVICE_TABLE(i2c, tsys02d_id);
 
 static struct i2c_driver tsys02d_driver = {
-       .probe_new = tsys02d_probe,
+       .probe = tsys02d_probe,
        .id_table = tsys02d_id,
        .driver = {
                   .name = "tsys02d",
index e86afecfbe46e67374f38e799f0d01acd332b8b4..b1c36412025f3141503b2886f858baf5a5941093 100644 (file)
@@ -3341,9 +3341,7 @@ static int bnxt_re_process_raw_qp_pkt_rx(struct bnxt_re_qp *gsi_qp,
        udwr.remote_qkey = gsi_sqp->qplib_qp.qkey;
 
        /* post data received  in the send queue */
-       rc = bnxt_re_post_send_shadow_qp(rdev, gsi_sqp, swr);
-
-       return 0;
+       return bnxt_re_post_send_shadow_qp(rdev, gsi_sqp, swr);
 }
 
 static void bnxt_re_process_res_rawqp1_wc(struct ib_wc *wc,
index b9e2f89337e85e9a26b1d7ce63ceef906fd4fd67..e34eccd178d0f3ad666973097d075e084b051e3e 100644 (file)
@@ -1336,6 +1336,10 @@ static void bnxt_re_setup_cc(struct bnxt_re_dev *rdev, bool enable)
 {
        struct bnxt_qplib_cc_param cc_param = {};
 
+       /* Do not enable congestion control on VFs */
+       if (rdev->is_virtfn)
+               return;
+
        /* Currently enabling only for GenP5 adapters */
        if (!bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx))
                return;
index f139d4cd17128a9b5a79bb02f400092b7b4d986a..8974f6235cfaa83a9e658faf08e2085a23738f4e 100644 (file)
@@ -2056,6 +2056,12 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
        u32 pg_sz_lvl;
        int rc;
 
+       if (!cq->dpi) {
+               dev_err(&rcfw->pdev->dev,
+                       "FP: CREATE_CQ failed due to NULL DPI\n");
+               return -EINVAL;
+       }
+
        hwq_attr.res = res;
        hwq_attr.depth = cq->max_wqe;
        hwq_attr.stride = sizeof(struct cq_base);
@@ -2069,11 +2075,6 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
                                 CMDQ_BASE_OPCODE_CREATE_CQ,
                                 sizeof(req));
 
-       if (!cq->dpi) {
-               dev_err(&rcfw->pdev->dev,
-                       "FP: CREATE_CQ failed due to NULL DPI\n");
-               return -EINVAL;
-       }
        req.dpi = cpu_to_le32(cq->dpi->dpi);
        req.cq_handle = cpu_to_le64(cq->cq_handle);
        req.cq_size = cpu_to_le32(cq->hwq.max_elements);
index 126d4f26f75ad722f9f71857b0711e3e31b0f451..81b0c5e879f9e857a77875dd104530eb4edaee91 100644 (file)
@@ -215,17 +215,9 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq,
                        return -EINVAL;
                hwq_attr->sginfo->npages = npages;
        } else {
-               unsigned long sginfo_num_pages = ib_umem_num_dma_blocks(
-                       hwq_attr->sginfo->umem, hwq_attr->sginfo->pgsize);
-
+               npages = ib_umem_num_dma_blocks(hwq_attr->sginfo->umem,
+                                               hwq_attr->sginfo->pgsize);
                hwq->is_user = true;
-               npages = sginfo_num_pages;
-               npages = (npages * PAGE_SIZE) /
-                         BIT_ULL(hwq_attr->sginfo->pgshft);
-               if ((sginfo_num_pages * PAGE_SIZE) %
-                    BIT_ULL(hwq_attr->sginfo->pgshft))
-                       if (!npages)
-                               npages++;
        }
 
        if (npages == MAX_PBL_LVL_0_PGS && !hwq_attr->sginfo->nopte) {
index 1714a1e231132fcf3b6eee90ca03277475d88d7a..b967a17a44bebcc282547488eb9209781dda3450 100644 (file)
@@ -617,16 +617,15 @@ int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
                /* Free the hwq if it already exist, must be a rereg */
                if (mr->hwq.max_elements)
                        bnxt_qplib_free_hwq(res, &mr->hwq);
-               /* Use system PAGE_SIZE */
                hwq_attr.res = res;
                hwq_attr.depth = pages;
-               hwq_attr.stride = buf_pg_size;
+               hwq_attr.stride = sizeof(dma_addr_t);
                hwq_attr.type = HWQ_TYPE_MR;
                hwq_attr.sginfo = &sginfo;
                hwq_attr.sginfo->umem = umem;
                hwq_attr.sginfo->npages = pages;
-               hwq_attr.sginfo->pgsize = PAGE_SIZE;
-               hwq_attr.sginfo->pgshft = PAGE_SHIFT;
+               hwq_attr.sginfo->pgsize = buf_pg_size;
+               hwq_attr.sginfo->pgshft = ilog2(buf_pg_size);
                rc = bnxt_qplib_alloc_init_hwq(&mr->hwq, &hwq_attr);
                if (rc) {
                        dev_err(&res->pdev->dev,
index 8eca6c14d0cfca3db186810789058aaeecbcae21..2a195c4b0f17de077a87b6ff7a8fed4e837f03ad 100644 (file)
@@ -1403,7 +1403,7 @@ static int pbl_continuous_initialize(struct efa_dev *dev,
  */
 static int pbl_indirect_initialize(struct efa_dev *dev, struct pbl_context *pbl)
 {
-       u32 size_in_pages = DIV_ROUND_UP(pbl->pbl_buf_size_in_bytes, PAGE_SIZE);
+       u32 size_in_pages = DIV_ROUND_UP(pbl->pbl_buf_size_in_bytes, EFA_CHUNK_PAYLOAD_SIZE);
        struct scatterlist *sgl;
        int sg_dma_cnt, err;
 
index 84f1167de1d9e7a9c2affa62adeb9034245fac5f..d4c6b9bc0a4ea222e7d4bff78ab3010d452a049c 100644 (file)
@@ -4583,11 +4583,9 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
        mtu = ib_mtu_enum_to_int(ib_mtu);
        if (WARN_ON(mtu <= 0))
                return -EINVAL;
-#define MAX_LP_MSG_LEN 16384
-       /* MTU * (2 ^ LP_PKTN_INI) shouldn't be bigger than 16KB */
-       lp_pktn_ini = ilog2(MAX_LP_MSG_LEN / mtu);
-       if (WARN_ON(lp_pktn_ini >= 0xF))
-               return -EINVAL;
+#define MIN_LP_MSG_LEN 1024
+       /* mtu * (2 ^ lp_pktn_ini) should be in the range of 1024 to mtu */
+       lp_pktn_ini = ilog2(max(mtu, MIN_LP_MSG_LEN) / mtu);
 
        if (attr_mask & IB_QP_PATH_MTU) {
                hr_reg_write(context, QPC_MTU, ib_mtu);
@@ -5012,7 +5010,6 @@ static int hns_roce_v2_set_abs_fields(struct ib_qp *ibqp,
 static bool check_qp_timeout_cfg_range(struct hns_roce_dev *hr_dev, u8 *timeout)
 {
 #define QP_ACK_TIMEOUT_MAX_HIP08 20
-#define QP_ACK_TIMEOUT_OFFSET 10
 #define QP_ACK_TIMEOUT_MAX 31
 
        if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) {
@@ -5021,7 +5018,7 @@ static bool check_qp_timeout_cfg_range(struct hns_roce_dev *hr_dev, u8 *timeout)
                                   "local ACK timeout shall be 0 to 20.\n");
                        return false;
                }
-               *timeout += QP_ACK_TIMEOUT_OFFSET;
+               *timeout += HNS_ROCE_V2_QP_ACK_TIMEOUT_OFS_HIP08;
        } else if (hr_dev->pci_dev->revision > PCI_REVISION_ID_HIP08) {
                if (*timeout > QP_ACK_TIMEOUT_MAX) {
                        ibdev_warn(&hr_dev->ib_dev,
@@ -5307,6 +5304,18 @@ out:
        return ret;
 }
 
+static u8 get_qp_timeout_attr(struct hns_roce_dev *hr_dev,
+                             struct hns_roce_v2_qp_context *context)
+{
+       u8 timeout;
+
+       timeout = (u8)hr_reg_read(context, QPC_AT);
+       if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08)
+               timeout -= HNS_ROCE_V2_QP_ACK_TIMEOUT_OFS_HIP08;
+
+       return timeout;
+}
+
 static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
                                int qp_attr_mask,
                                struct ib_qp_init_attr *qp_init_attr)
@@ -5384,7 +5393,7 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
        qp_attr->max_dest_rd_atomic = 1 << hr_reg_read(&context, QPC_RR_MAX);
 
        qp_attr->min_rnr_timer = (u8)hr_reg_read(&context, QPC_MIN_RNR_TIME);
-       qp_attr->timeout = (u8)hr_reg_read(&context, QPC_AT);
+       qp_attr->timeout = get_qp_timeout_attr(hr_dev, &context);
        qp_attr->retry_cnt = hr_reg_read(&context, QPC_RETRY_NUM_INIT);
        qp_attr->rnr_retry = hr_reg_read(&context, QPC_RNR_NUM_INIT);
 
index 1b44d2434ab415a756cb36fe6d3df6ee5d8bf637..7033eae2407c541c88a07d4a8543678c1fb630f7 100644 (file)
@@ -44,6 +44,8 @@
 #define HNS_ROCE_V2_MAX_XRCD_NUM               0x1000000
 #define HNS_ROCE_V2_RSV_XRCD_NUM               0
 
+#define HNS_ROCE_V2_QP_ACK_TIMEOUT_OFS_HIP08    10
+
 #define HNS_ROCE_V3_SCCC_SZ                    64
 #define HNS_ROCE_V3_GMV_ENTRY_SZ               32
 
index 37a5cf62f88b48b12293946e311bdd5d067edbaf..14376490ac226abce81b3f4f27f58726f5994a29 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <linux/vmalloc.h>
 #include <rdma/ib_umem.h>
+#include <linux/math.h>
 #include "hns_roce_device.h"
 #include "hns_roce_cmd.h"
 #include "hns_roce_hem.h"
@@ -909,6 +910,44 @@ static int mtr_init_buf_cfg(struct hns_roce_dev *hr_dev,
        return page_cnt;
 }
 
+static u64 cal_pages_per_l1ba(unsigned int ba_per_bt, unsigned int hopnum)
+{
+       return int_pow(ba_per_bt, hopnum - 1);
+}
+
+static unsigned int cal_best_bt_pg_sz(struct hns_roce_dev *hr_dev,
+                                     struct hns_roce_mtr *mtr,
+                                     unsigned int pg_shift)
+{
+       unsigned long cap = hr_dev->caps.page_size_cap;
+       struct hns_roce_buf_region *re;
+       unsigned int pgs_per_l1ba;
+       unsigned int ba_per_bt;
+       unsigned int ba_num;
+       int i;
+
+       for_each_set_bit_from(pg_shift, &cap, sizeof(cap) * BITS_PER_BYTE) {
+               if (!(BIT(pg_shift) & cap))
+                       continue;
+
+               ba_per_bt = BIT(pg_shift) / BA_BYTE_LEN;
+               ba_num = 0;
+               for (i = 0; i < mtr->hem_cfg.region_count; i++) {
+                       re = &mtr->hem_cfg.region[i];
+                       if (re->hopnum == 0)
+                               continue;
+
+                       pgs_per_l1ba = cal_pages_per_l1ba(ba_per_bt, re->hopnum);
+                       ba_num += DIV_ROUND_UP(re->count, pgs_per_l1ba);
+               }
+
+               if (ba_num <= ba_per_bt)
+                       return pg_shift;
+       }
+
+       return 0;
+}
+
 static int mtr_alloc_mtt(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
                         unsigned int ba_page_shift)
 {
@@ -917,6 +956,10 @@ static int mtr_alloc_mtt(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
 
        hns_roce_hem_list_init(&mtr->hem_list);
        if (!cfg->is_direct) {
+               ba_page_shift = cal_best_bt_pg_sz(hr_dev, mtr, ba_page_shift);
+               if (!ba_page_shift)
+                       return -ERANGE;
+
                ret = hns_roce_hem_list_request(hr_dev, &mtr->hem_list,
                                                cfg->region, cfg->region_count,
                                                ba_page_shift);
index ab5cdf78278521123c92f8ff4482144797b765f6..eaa12c124598285beaa891761d8a2ec6aaa17ada 100644 (file)
@@ -522,11 +522,6 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
        if (!iwqp->user_mode)
                cancel_delayed_work_sync(&iwqp->dwork_flush);
 
-       irdma_qp_rem_ref(&iwqp->ibqp);
-       wait_for_completion(&iwqp->free_qp);
-       irdma_free_lsmm_rsrc(iwqp);
-       irdma_cqp_qp_destroy_cmd(&iwdev->rf->sc_dev, &iwqp->sc_qp);
-
        if (!iwqp->user_mode) {
                if (iwqp->iwscq) {
                        irdma_clean_cqes(iwqp, iwqp->iwscq);
@@ -534,6 +529,12 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
                                irdma_clean_cqes(iwqp, iwqp->iwrcq);
                }
        }
+
+       irdma_qp_rem_ref(&iwqp->ibqp);
+       wait_for_completion(&iwqp->free_qp);
+       irdma_free_lsmm_rsrc(iwqp);
+       irdma_cqp_qp_destroy_cmd(&iwdev->rf->sc_dev, &iwqp->sc_qp);
+
        irdma_remove_push_mmap_entries(iwqp);
        irdma_free_qp_rsrc(iwqp);
 
@@ -3291,6 +3292,7 @@ static int irdma_post_send(struct ib_qp *ibqp,
                        break;
                case IB_WR_LOCAL_INV:
                        info.op_type = IRDMA_OP_TYPE_INV_STAG;
+                       info.local_fence = info.read_fence;
                        info.op.inv_local_stag.target_stag = ib_wr->ex.invalidate_rkey;
                        err = irdma_uk_stag_local_invalidate(ukqp, &info, true);
                        break;
index db18ace74d2b53a8e0bbc68bc3d7cded8463d263..f46c5a5fd0aea4d4c0530d054949a8867013053a 100644 (file)
@@ -115,15 +115,16 @@ static enum ib_wc_opcode wr_to_wc_opcode(enum ib_wr_opcode opcode)
 void retransmit_timer(struct timer_list *t)
 {
        struct rxe_qp *qp = from_timer(qp, t, retrans_timer);
+       unsigned long flags;
 
        rxe_dbg_qp(qp, "retransmit timer fired\n");
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (qp->valid) {
                qp->comp.timeout = 1;
                rxe_sched_task(&qp->comp.task);
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 }
 
 void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
@@ -481,11 +482,13 @@ static void do_complete(struct rxe_qp *qp, struct rxe_send_wqe *wqe)
 
 static void comp_check_sq_drain_done(struct rxe_qp *qp)
 {
-       spin_lock_bh(&qp->state_lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (unlikely(qp_state(qp) == IB_QPS_SQD)) {
                if (qp->attr.sq_draining && qp->comp.psn == qp->req.psn) {
                        qp->attr.sq_draining = 0;
-                       spin_unlock_bh(&qp->state_lock);
+                       spin_unlock_irqrestore(&qp->state_lock, flags);
 
                        if (qp->ibqp.event_handler) {
                                struct ib_event ev;
@@ -499,7 +502,7 @@ static void comp_check_sq_drain_done(struct rxe_qp *qp)
                        return;
                }
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 }
 
 static inline enum comp_state complete_ack(struct rxe_qp *qp,
@@ -625,13 +628,15 @@ static void free_pkt(struct rxe_pkt_info *pkt)
  */
 static void reset_retry_timer(struct rxe_qp *qp)
 {
+       unsigned long flags;
+
        if (qp_type(qp) == IB_QPT_RC && qp->qp_timeout_jiffies) {
-               spin_lock_bh(&qp->state_lock);
+               spin_lock_irqsave(&qp->state_lock, flags);
                if (qp_state(qp) >= IB_QPS_RTS &&
                    psn_compare(qp->req.psn, qp->comp.psn) > 0)
                        mod_timer(&qp->retrans_timer,
                                  jiffies + qp->qp_timeout_jiffies);
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
        }
 }
 
@@ -643,18 +648,19 @@ int rxe_completer(struct rxe_qp *qp)
        struct rxe_pkt_info *pkt = NULL;
        enum comp_state state;
        int ret;
+       unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (!qp->valid || qp_state(qp) == IB_QPS_ERR ||
                          qp_state(qp) == IB_QPS_RESET) {
                bool notify = qp->valid && (qp_state(qp) == IB_QPS_ERR);
 
                drain_resp_pkts(qp);
                flush_send_queue(qp, notify);
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                goto exit;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        if (qp->comp.timeout) {
                qp->comp.timeout_retry = 1;
index 2bc7361152ea70f95c78f743098c4b6cc547fa16..a38fab19bed19c637628c412bc7daabc3191ad2a 100644 (file)
@@ -412,15 +412,16 @@ int rxe_xmit_packet(struct rxe_qp *qp, struct rxe_pkt_info *pkt,
        int err;
        int is_request = pkt->mask & RXE_REQ_MASK;
        struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+       unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if ((is_request && (qp_state(qp) < IB_QPS_RTS)) ||
            (!is_request && (qp_state(qp) < IB_QPS_RTR))) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                rxe_dbg_qp(qp, "Packet dropped. QP is not in ready state\n");
                goto drop;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        rxe_icrc_generate(skb, pkt);
 
index c5451a4488ca35b4cd7cb21930f7fab1ca482784..61a2eb77d9999ea135a509f02ea5a4ca6712163c 100644 (file)
@@ -300,6 +300,7 @@ int rxe_qp_from_init(struct rxe_dev *rxe, struct rxe_qp *qp, struct rxe_pd *pd,
        struct rxe_cq *rcq = to_rcq(init->recv_cq);
        struct rxe_cq *scq = to_rcq(init->send_cq);
        struct rxe_srq *srq = init->srq ? to_rsrq(init->srq) : NULL;
+       unsigned long flags;
 
        rxe_get(pd);
        rxe_get(rcq);
@@ -325,10 +326,10 @@ int rxe_qp_from_init(struct rxe_dev *rxe, struct rxe_qp *qp, struct rxe_pd *pd,
        if (err)
                goto err2;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        qp->attr.qp_state = IB_QPS_RESET;
        qp->valid = 1;
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        return 0;
 
@@ -492,24 +493,28 @@ static void rxe_qp_reset(struct rxe_qp *qp)
 /* move the qp to the error state */
 void rxe_qp_error(struct rxe_qp *qp)
 {
-       spin_lock_bh(&qp->state_lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&qp->state_lock, flags);
        qp->attr.qp_state = IB_QPS_ERR;
 
        /* drain work and packet queues */
        rxe_sched_task(&qp->resp.task);
        rxe_sched_task(&qp->comp.task);
        rxe_sched_task(&qp->req.task);
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 }
 
 static void rxe_qp_sqd(struct rxe_qp *qp, struct ib_qp_attr *attr,
                       int mask)
 {
-       spin_lock_bh(&qp->state_lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&qp->state_lock, flags);
        qp->attr.sq_draining = 1;
        rxe_sched_task(&qp->comp.task);
        rxe_sched_task(&qp->req.task);
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 }
 
 /* caller should hold qp->state_lock */
@@ -555,14 +560,16 @@ int rxe_qp_from_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask,
                qp->attr.cur_qp_state = attr->qp_state;
 
        if (mask & IB_QP_STATE) {
-               spin_lock_bh(&qp->state_lock);
+               unsigned long flags;
+
+               spin_lock_irqsave(&qp->state_lock, flags);
                err = __qp_chk_state(qp, attr, mask);
                if (!err) {
                        qp->attr.qp_state = attr->qp_state;
                        rxe_dbg_qp(qp, "state -> %s\n",
                                        qps2str[attr->qp_state]);
                }
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
 
                if (err)
                        return err;
@@ -688,6 +695,8 @@ int rxe_qp_from_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask,
 /* called by the query qp verb */
 int rxe_qp_to_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask)
 {
+       unsigned long flags;
+
        *attr = qp->attr;
 
        attr->rq_psn                            = qp->resp.psn;
@@ -708,12 +717,13 @@ int rxe_qp_to_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask)
        /* Applications that get this state typically spin on it.
         * Yield the processor
         */
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (qp->attr.sq_draining) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                cond_resched();
+       } else {
+               spin_unlock_irqrestore(&qp->state_lock, flags);
        }
-       spin_unlock_bh(&qp->state_lock);
 
        return 0;
 }
@@ -736,10 +746,11 @@ int rxe_qp_chk_destroy(struct rxe_qp *qp)
 static void rxe_qp_do_cleanup(struct work_struct *work)
 {
        struct rxe_qp *qp = container_of(work, typeof(*qp), cleanup_work.work);
+       unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        qp->valid = 0;
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
        qp->qp_timeout_jiffies = 0;
 
        if (qp_type(qp) == IB_QPT_RC) {
index 2f953cc74256d90c9015bd413520be8369a6ff2b..5861e42440490dd1014efad9c0a52c2d9ebb5bc4 100644 (file)
@@ -14,6 +14,7 @@ static int check_type_state(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
                            struct rxe_qp *qp)
 {
        unsigned int pkt_type;
+       unsigned long flags;
 
        if (unlikely(!qp->valid))
                return -EINVAL;
@@ -38,19 +39,19 @@ static int check_type_state(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
                return -EINVAL;
        }
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (pkt->mask & RXE_REQ_MASK) {
                if (unlikely(qp_state(qp) < IB_QPS_RTR)) {
-                       spin_unlock_bh(&qp->state_lock);
+                       spin_unlock_irqrestore(&qp->state_lock, flags);
                        return -EINVAL;
                }
        } else {
                if (unlikely(qp_state(qp) < IB_QPS_RTS)) {
-                       spin_unlock_bh(&qp->state_lock);
+                       spin_unlock_irqrestore(&qp->state_lock, flags);
                        return -EINVAL;
                }
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        return 0;
 }
index 65134a9aefe7bfe5f9ea71f57d237af5f61170ad..5fe7cbae30313c0ce5f2ab61e00e33e6778b19ad 100644 (file)
@@ -99,17 +99,18 @@ static void req_retry(struct rxe_qp *qp)
 void rnr_nak_timer(struct timer_list *t)
 {
        struct rxe_qp *qp = from_timer(qp, t, rnr_nak_timer);
+       unsigned long flags;
 
        rxe_dbg_qp(qp, "nak timer fired\n");
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (qp->valid) {
                /* request a send queue retry */
                qp->req.need_retry = 1;
                qp->req.wait_for_rnr_timer = 0;
                rxe_sched_task(&qp->req.task);
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 }
 
 static void req_check_sq_drain_done(struct rxe_qp *qp)
@@ -118,8 +119,9 @@ static void req_check_sq_drain_done(struct rxe_qp *qp)
        unsigned int index;
        unsigned int cons;
        struct rxe_send_wqe *wqe;
+       unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (qp_state(qp) == IB_QPS_SQD) {
                q = qp->sq.queue;
                index = qp->req.wqe_index;
@@ -140,7 +142,7 @@ static void req_check_sq_drain_done(struct rxe_qp *qp)
                                break;
 
                        qp->attr.sq_draining = 0;
-                       spin_unlock_bh(&qp->state_lock);
+                       spin_unlock_irqrestore(&qp->state_lock, flags);
 
                        if (qp->ibqp.event_handler) {
                                struct ib_event ev;
@@ -154,7 +156,7 @@ static void req_check_sq_drain_done(struct rxe_qp *qp)
                        return;
                } while (0);
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 }
 
 static struct rxe_send_wqe *__req_next_wqe(struct rxe_qp *qp)
@@ -173,6 +175,7 @@ static struct rxe_send_wqe *__req_next_wqe(struct rxe_qp *qp)
 static struct rxe_send_wqe *req_next_wqe(struct rxe_qp *qp)
 {
        struct rxe_send_wqe *wqe;
+       unsigned long flags;
 
        req_check_sq_drain_done(qp);
 
@@ -180,13 +183,13 @@ static struct rxe_send_wqe *req_next_wqe(struct rxe_qp *qp)
        if (wqe == NULL)
                return NULL;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (unlikely((qp_state(qp) == IB_QPS_SQD) &&
                     (wqe->state != wqe_state_processing))) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                return NULL;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        wqe->mask = wr_opcode_mask(wqe->wr.opcode, qp);
        return wqe;
@@ -676,16 +679,17 @@ int rxe_requester(struct rxe_qp *qp)
        struct rxe_queue *q = qp->sq.queue;
        struct rxe_ah *ah;
        struct rxe_av *av;
+       unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (unlikely(!qp->valid)) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                goto exit;
        }
 
        if (unlikely(qp_state(qp) == IB_QPS_ERR)) {
                wqe = __req_next_wqe(qp);
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                if (wqe)
                        goto err;
                else
@@ -700,10 +704,10 @@ int rxe_requester(struct rxe_qp *qp)
                qp->req.wait_psn = 0;
                qp->req.need_retry = 0;
                qp->req.wait_for_rnr_timer = 0;
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                goto exit;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        /* we come here if the retransmit timer has fired
         * or if the rnr timer has fired. If the retransmit
index 68f6cd188d8ed2f943d89d15438f2189ed4c16fe..1da044f6b7d494f62d33cad76a2918c3059f9edd 100644 (file)
@@ -1047,6 +1047,7 @@ static enum resp_states do_complete(struct rxe_qp *qp,
        struct ib_uverbs_wc *uwc = &cqe.uibwc;
        struct rxe_recv_wqe *wqe = qp->resp.wqe;
        struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+       unsigned long flags;
 
        if (!wqe)
                goto finish;
@@ -1137,12 +1138,12 @@ static enum resp_states do_complete(struct rxe_qp *qp,
                return RESPST_ERR_CQ_OVERFLOW;
 
 finish:
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (unlikely(qp_state(qp) == IB_QPS_ERR)) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                return RESPST_CHK_RESOURCE;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        if (unlikely(!pkt))
                return RESPST_DONE;
@@ -1468,18 +1469,19 @@ int rxe_responder(struct rxe_qp *qp)
        enum resp_states state;
        struct rxe_pkt_info *pkt = NULL;
        int ret;
+       unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (!qp->valid || qp_state(qp) == IB_QPS_ERR ||
                          qp_state(qp) == IB_QPS_RESET) {
                bool notify = qp->valid && (qp_state(qp) == IB_QPS_ERR);
 
                drain_req_pkts(qp);
                flush_recv_queue(qp, notify);
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                goto exit;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        qp->resp.aeth_syndrome = AETH_ACK_UNLIMITED;
 
index dea605b7f68335f78c94d8464594071aef2dd351..4d8f6b8051ff7db5509b2e9961af54c1479373cb 100644 (file)
@@ -904,10 +904,10 @@ static int rxe_post_send_kernel(struct rxe_qp *qp,
        if (!err)
                rxe_sched_task(&qp->req.task);
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (qp_state(qp) == IB_QPS_ERR)
                rxe_sched_task(&qp->comp.task);
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        return err;
 }
@@ -917,22 +917,23 @@ static int rxe_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
 {
        struct rxe_qp *qp = to_rqp(ibqp);
        int err;
+       unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        /* caller has already called destroy_qp */
        if (WARN_ON_ONCE(!qp->valid)) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                rxe_err_qp(qp, "qp has been destroyed");
                return -EINVAL;
        }
 
        if (unlikely(qp_state(qp) < IB_QPS_RTS)) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                *bad_wr = wr;
                rxe_err_qp(qp, "qp not ready to send");
                return -EINVAL;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        if (qp->is_user) {
                /* Utilize process context to do protocol processing */
@@ -1008,22 +1009,22 @@ static int rxe_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
        struct rxe_rq *rq = &qp->rq;
        unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        /* caller has already called destroy_qp */
        if (WARN_ON_ONCE(!qp->valid)) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                rxe_err_qp(qp, "qp has been destroyed");
                return -EINVAL;
        }
 
        /* see C10-97.2.1 */
        if (unlikely((qp_state(qp) < IB_QPS_INIT))) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                *bad_wr = wr;
                rxe_dbg_qp(qp, "qp not ready to post recv");
                return -EINVAL;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        if (unlikely(qp->srq)) {
                *bad_wr = wr;
@@ -1044,10 +1045,10 @@ static int rxe_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
 
        spin_unlock_irqrestore(&rq->producer_lock, flags);
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (qp_state(qp) == IB_QPS_ERR)
                rxe_sched_task(&qp->resp.task);
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        return err;
 }
index db98c3f86e8c8b87f4c9c7e45b1f1b775f72c2f0..4d800601e8ecd6002c462383e4fc6d2cc186cb03 100644 (file)
@@ -282,6 +282,7 @@ config EXYNOS_IOMMU_DEBUG
 config IPMMU_VMSA
        bool "Renesas VMSA-compatible IPMMU"
        depends on ARCH_RENESAS || COMPILE_TEST
+       depends on ARM || ARM64 || COMPILE_TEST
        depends on !GENERIC_ATOMIC64    # for IOMMU_IO_PGTABLE_LPAE
        select IOMMU_API
        select IOMMU_IO_PGTABLE_LPAE
@@ -417,22 +418,6 @@ config S390_IOMMU
        help
          Support for the IOMMU API for s390 PCI devices.
 
-config S390_CCW_IOMMU
-       bool "S390 CCW IOMMU Support"
-       depends on S390 && CCW || COMPILE_TEST
-       select IOMMU_API
-       help
-         Enables bits of IOMMU API required by VFIO. The iommu_ops
-         is not implemented as it is not necessary for VFIO.
-
-config S390_AP_IOMMU
-       bool "S390 AP IOMMU Support"
-       depends on S390 && ZCRYPT || COMPILE_TEST
-       select IOMMU_API
-       help
-         Enables bits of IOMMU API required by VFIO. The iommu_ops
-         is not implemented as it is not necessary for VFIO.
-
 config MTK_IOMMU
        tristate "MediaTek IOMMU Support"
        depends on ARCH_MEDIATEK || COMPILE_TEST
index e98f20a9bdd82e6be58e4d9938094f18979482b6..9beeceb9d825dfeae9e2aa9229e031513680ba09 100644 (file)
@@ -15,9 +15,7 @@ extern irqreturn_t amd_iommu_int_thread(int irq, void *data);
 extern irqreturn_t amd_iommu_int_handler(int irq, void *data);
 extern void amd_iommu_apply_erratum_63(struct amd_iommu *iommu, u16 devid);
 extern void amd_iommu_restart_event_logging(struct amd_iommu *iommu);
-extern int amd_iommu_init_devices(void);
-extern void amd_iommu_uninit_devices(void);
-extern void amd_iommu_init_notifier(void);
+extern void amd_iommu_restart_ga_log(struct amd_iommu *iommu);
 extern void amd_iommu_set_rlookup_table(struct amd_iommu *iommu, u16 devid);
 
 #ifdef CONFIG_AMD_IOMMU_DEBUGFS
index 329a406cc37de8f84e88acde441eea20ce65599b..c2d80a4e5fb066c69cfe0f8cab1856894bfbb2e3 100644 (file)
@@ -758,6 +758,30 @@ void amd_iommu_restart_event_logging(struct amd_iommu *iommu)
        iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN);
 }
 
+/*
+ * This function restarts event logging in case the IOMMU experienced
+ * an GA log overflow.
+ */
+void amd_iommu_restart_ga_log(struct amd_iommu *iommu)
+{
+       u32 status;
+
+       status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
+       if (status & MMIO_STATUS_GALOG_RUN_MASK)
+               return;
+
+       pr_info_ratelimited("IOMMU GA Log restarting\n");
+
+       iommu_feature_disable(iommu, CONTROL_GALOG_EN);
+       iommu_feature_disable(iommu, CONTROL_GAINT_EN);
+
+       writel(MMIO_STATUS_GALOG_OVERFLOW_MASK,
+              iommu->mmio_base + MMIO_STATUS_OFFSET);
+
+       iommu_feature_enable(iommu, CONTROL_GAINT_EN);
+       iommu_feature_enable(iommu, CONTROL_GALOG_EN);
+}
+
 /*
  * This function resets the command buffer if the IOMMU stopped fetching
  * commands from it.
index 4a314647d1f792e3ef74538baedb654b8e8a2f42..dc1ec684977542ea5aa1af73a055ff962cdbe3d0 100644 (file)
@@ -845,6 +845,7 @@ amd_iommu_set_pci_msi_domain(struct device *dev, struct amd_iommu *iommu) { }
        (MMIO_STATUS_EVT_OVERFLOW_INT_MASK | \
         MMIO_STATUS_EVT_INT_MASK | \
         MMIO_STATUS_PPR_INT_MASK | \
+        MMIO_STATUS_GALOG_OVERFLOW_MASK | \
         MMIO_STATUS_GALOG_INT_MASK)
 
 irqreturn_t amd_iommu_int_thread(int irq, void *data)
@@ -868,10 +869,16 @@ irqreturn_t amd_iommu_int_thread(int irq, void *data)
                }
 
 #ifdef CONFIG_IRQ_REMAP
-               if (status & MMIO_STATUS_GALOG_INT_MASK) {
+               if (status & (MMIO_STATUS_GALOG_INT_MASK |
+                             MMIO_STATUS_GALOG_OVERFLOW_MASK)) {
                        pr_devel("Processing IOMMU GA Log\n");
                        iommu_poll_ga_log(iommu);
                }
+
+               if (status & MMIO_STATUS_GALOG_OVERFLOW_MASK) {
+                       pr_info_ratelimited("IOMMU GA Log overflow\n");
+                       amd_iommu_restart_ga_log(iommu);
+               }
 #endif
 
                if (status & MMIO_STATUS_EVT_OVERFLOW_INT_MASK) {
@@ -2067,7 +2074,7 @@ static struct protection_domain *protection_domain_alloc(unsigned int type)
 {
        struct io_pgtable_ops *pgtbl_ops;
        struct protection_domain *domain;
-       int pgtable = amd_iommu_pgtable;
+       int pgtable;
        int mode = DEFAULT_PGTABLE_LEVEL;
        int ret;
 
@@ -2084,6 +2091,10 @@ static struct protection_domain *protection_domain_alloc(unsigned int type)
                mode = PAGE_MODE_NONE;
        } else if (type == IOMMU_DOMAIN_UNMANAGED) {
                pgtable = AMD_IOMMU_V1;
+       } else if (type == IOMMU_DOMAIN_DMA || type == IOMMU_DOMAIN_DMA_FQ) {
+               pgtable = amd_iommu_pgtable;
+       } else {
+               return NULL;
        }
 
        switch (pgtable) {
@@ -2118,6 +2129,15 @@ out_err:
        return NULL;
 }
 
+static inline u64 dma_max_address(void)
+{
+       if (amd_iommu_pgtable == AMD_IOMMU_V1)
+               return ~0ULL;
+
+       /* V2 with 4/5 level page table */
+       return ((1ULL << PM_LEVEL_SHIFT(amd_iommu_gpt_level)) - 1);
+}
+
 static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
 {
        struct protection_domain *domain;
@@ -2134,7 +2154,7 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
                return NULL;
 
        domain->domain.geometry.aperture_start = 0;
-       domain->domain.geometry.aperture_end   = ~0ULL;
+       domain->domain.geometry.aperture_end   = dma_max_address();
        domain->domain.geometry.force_aperture = true;
 
        return &domain->domain;
@@ -2387,7 +2407,7 @@ static void amd_iommu_iotlb_sync(struct iommu_domain *domain,
        unsigned long flags;
 
        spin_lock_irqsave(&dom->lock, flags);
-       domain_flush_pages(dom, gather->start, gather->end - gather->start, 1);
+       domain_flush_pages(dom, gather->start, gather->end - gather->start + 1, 1);
        amd_iommu_domain_flush_complete(dom);
        spin_unlock_irqrestore(&dom->lock, flags);
 }
@@ -3493,8 +3513,7 @@ int amd_iommu_activate_guest_mode(void *data)
        struct irte_ga *entry = (struct irte_ga *) ir_data->entry;
        u64 valid;
 
-       if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) ||
-           !entry || entry->lo.fields_vapic.guest_mode)
+       if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) || !entry)
                return 0;
 
        valid = entry->lo.fields_vapic.valid;
index ae09c627bc8448b962f95f581ef213ff06b0ab58..c71afda79d6442f57026b945fd7ff8fe08cd35a4 100644 (file)
@@ -517,6 +517,7 @@ static const struct of_device_id __maybe_unused qcom_smmu_impl_of_match[] = {
        { .compatible = "qcom,qcm2290-smmu-500", .data = &qcom_smmu_500_impl0_data },
        { .compatible = "qcom,qdu1000-smmu-500", .data = &qcom_smmu_500_impl0_data  },
        { .compatible = "qcom,sc7180-smmu-500", .data = &qcom_smmu_500_impl0_data },
+       { .compatible = "qcom,sc7180-smmu-v2", .data = &qcom_smmu_v2_data },
        { .compatible = "qcom,sc7280-smmu-500", .data = &qcom_smmu_500_impl0_data },
        { .compatible = "qcom,sc8180x-smmu-500", .data = &qcom_smmu_500_impl0_data },
        { .compatible = "qcom,sc8280xp-smmu-500", .data = &qcom_smmu_500_impl0_data },
@@ -561,5 +562,14 @@ struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu)
        if (match)
                return qcom_smmu_create(smmu, match->data);
 
+       /*
+        * If you hit this WARN_ON() you are missing an entry in the
+        * qcom_smmu_impl_of_match[] table, and GPU per-process page-
+        * tables will be broken.
+        */
+       WARN(of_device_is_compatible(np, "qcom,adreno-smmu"),
+            "Missing qcom_smmu_impl_of_match entry for: %s",
+            dev_name(smmu->dev));
+
        return smmu;
 }
index aecc7d154f28eeb1cfb493b9e61686f1fba2f4bf..e93906d6e112e826facaea508e118e36b78fb666 100644 (file)
@@ -781,7 +781,8 @@ static void mtk_iommu_flush_iotlb_all(struct iommu_domain *domain)
 {
        struct mtk_iommu_domain *dom = to_mtk_domain(domain);
 
-       mtk_iommu_tlb_flush_all(dom->bank->parent_data);
+       if (dom->bank)
+               mtk_iommu_tlb_flush_all(dom->bank->parent_data);
 }
 
 static void mtk_iommu_iotlb_sync(struct iommu_domain *domain,
index ea5a3088bb7e8a566ab9285d644009eb2bcd1d6a..4054030c32379533eca2e96003016a8a6a51481a 100644 (file)
@@ -1335,20 +1335,22 @@ static int rk_iommu_probe(struct platform_device *pdev)
        for (i = 0; i < iommu->num_irq; i++) {
                int irq = platform_get_irq(pdev, i);
 
-               if (irq < 0)
-                       return irq;
+               if (irq < 0) {
+                       err = irq;
+                       goto err_pm_disable;
+               }
 
                err = devm_request_irq(iommu->dev, irq, rk_iommu_irq,
                                       IRQF_SHARED, dev_name(dev), iommu);
-               if (err) {
-                       pm_runtime_disable(dev);
-                       goto err_remove_sysfs;
-               }
+               if (err)
+                       goto err_pm_disable;
        }
 
        dma_set_mask_and_coherent(dev, rk_ops->dma_bit_mask);
 
        return 0;
+err_pm_disable:
+       pm_runtime_disable(dev);
 err_remove_sysfs:
        iommu_device_sysfs_remove(&iommu->iommu);
 err_put_group:
index a610821c8ff2af1e8485046480b047c6d3538a27..afd6a1841715a152afd572dac15e4366bfd96d1f 100644 (file)
@@ -16,7 +16,13 @@ void gic_enable_of_quirks(const struct device_node *np,
                          const struct gic_quirk *quirks, void *data)
 {
        for (; quirks->desc; quirks++) {
-               if (!of_device_is_compatible(np, quirks->compatible))
+               if (!quirks->compatible && !quirks->property)
+                       continue;
+               if (quirks->compatible &&
+                   !of_device_is_compatible(np, quirks->compatible))
+                       continue;
+               if (quirks->property &&
+                   !of_property_read_bool(np, quirks->property))
                        continue;
                if (quirks->init(data))
                        pr_info("GIC: enabling workaround for %s\n",
@@ -28,7 +34,7 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
                void *data)
 {
        for (; quirks->desc; quirks++) {
-               if (quirks->compatible)
+               if (quirks->compatible || quirks->property)
                        continue;
                if (quirks->iidr != (quirks->mask & iidr))
                        continue;
index 27e3d4ed4f32861a4c46eebcc4634eb835a8e45b..3db4592cda1c01ad8a27e73f62b9d0890019667d 100644 (file)
@@ -13,6 +13,7 @@
 struct gic_quirk {
        const char *desc;
        const char *compatible;
+       const char *property;
        bool (*init)(void *data);
        u32 iidr;
        u32 mask;
index 6fcee221f201720929f1481aa64d3367d6395737..a605aa79435a4dca64dd1eb012f0f1fe7f394ff3 100644 (file)
@@ -39,6 +39,7 @@
 
 #define FLAGS_WORKAROUND_GICR_WAKER_MSM8996    (1ULL << 0)
 #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539  (1ULL << 1)
+#define FLAGS_WORKAROUND_MTK_GICR_SAVE         (1ULL << 2)
 
 #define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1)
 
@@ -1720,6 +1721,15 @@ static bool gic_enable_quirk_msm8996(void *data)
        return true;
 }
 
+static bool gic_enable_quirk_mtk_gicr(void *data)
+{
+       struct gic_chip_data *d = data;
+
+       d->flags |= FLAGS_WORKAROUND_MTK_GICR_SAVE;
+
+       return true;
+}
+
 static bool gic_enable_quirk_cavium_38539(void *data)
 {
        struct gic_chip_data *d = data;
@@ -1792,6 +1802,11 @@ static const struct gic_quirk gic_quirks[] = {
                .compatible = "qcom,msm8996-gic-v3",
                .init   = gic_enable_quirk_msm8996,
        },
+       {
+               .desc   = "GICv3: Mediatek Chromebook GICR save problem",
+               .property = "mediatek,broken-save-restore-fw",
+               .init   = gic_enable_quirk_mtk_gicr,
+       },
        {
                .desc   = "GICv3: HIP06 erratum 161010803",
                .iidr   = 0x0204043b,
@@ -1834,6 +1849,11 @@ static void gic_enable_nmi_support(void)
        if (!gic_prio_masking_enabled())
                return;
 
+       if (gic_data.flags & FLAGS_WORKAROUND_MTK_GICR_SAVE) {
+               pr_warn("Skipping NMI enable due to firmware issues\n");
+               return;
+       }
+
        ppi_nmi_refs = kcalloc(gic_data.ppi_nr, sizeof(*ppi_nmi_refs), GFP_KERNEL);
        if (!ppi_nmi_refs)
                return;
index eada5e0e3eb956c939be7d6eef06e1a0a4aedd39..5101a3fb11df5bef53122db9db3c194669d754e7 100644 (file)
@@ -240,26 +240,27 @@ static int mbigen_of_create_domain(struct platform_device *pdev,
        struct irq_domain *domain;
        struct device_node *np;
        u32 num_pins;
+       int ret = 0;
+
+       parent = bus_get_dev_root(&platform_bus_type);
+       if (!parent)
+               return -ENODEV;
 
        for_each_child_of_node(pdev->dev.of_node, np) {
                if (!of_property_read_bool(np, "interrupt-controller"))
                        continue;
 
-               parent = bus_get_dev_root(&platform_bus_type);
-               if (parent) {
-                       child = of_platform_device_create(np, NULL, parent);
-                       put_device(parent);
-                       if (!child) {
-                               of_node_put(np);
-                               return -ENOMEM;
-                       }
+               child = of_platform_device_create(np, NULL, parent);
+               if (!child) {
+                       ret = -ENOMEM;
+                       break;
                }
 
                if (of_property_read_u32(child->dev.of_node, "num-pins",
                                         &num_pins) < 0) {
                        dev_err(&pdev->dev, "No num-pins property\n");
-                       of_node_put(np);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       break;
                }
 
                domain = platform_msi_create_device_domain(&child->dev, num_pins,
@@ -267,12 +268,16 @@ static int mbigen_of_create_domain(struct platform_device *pdev,
                                                           &mbigen_domain_ops,
                                                           mgn_chip);
                if (!domain) {
-                       of_node_put(np);
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       break;
                }
        }
 
-       return 0;
+       put_device(parent);
+       if (ret)
+               of_node_put(np);
+
+       return ret;
 }
 
 #ifdef CONFIG_ACPI
index 2aaa9aad3e87acf666e7cf1fbe97feb9a175d797..7da18ef95211984bd2998af59e3bac07b5bedf98 100644 (file)
@@ -150,7 +150,7 @@ static const struct meson_gpio_irq_params s4_params = {
        INIT_MESON_S4_COMMON_DATA(82)
 };
 
-static const struct of_device_id meson_irq_gpio_matches[] = {
+static const struct of_device_id meson_irq_gpio_matches[] __maybe_unused = {
        { .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params },
        { .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params },
        { .compatible = "amlogic,meson-gxbb-gpio-intc", .data = &gxbb_params },
index 046c355e120b6485abf5266490670af9ce21be21..6d5ecc10a87032dfccb0835964999bfb07d912bd 100644 (file)
@@ -50,7 +50,7 @@ void __iomem *mips_gic_base;
 
 static DEFINE_PER_CPU_READ_MOSTLY(unsigned long[GIC_MAX_LONGS], pcpu_masks);
 
-static DEFINE_SPINLOCK(gic_lock);
+static DEFINE_RAW_SPINLOCK(gic_lock);
 static struct irq_domain *gic_irq_domain;
 static int gic_shared_intrs;
 static unsigned int gic_cpu_pin;
@@ -210,7 +210,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 
        irq = GIC_HWIRQ_TO_SHARED(d->hwirq);
 
-       spin_lock_irqsave(&gic_lock, flags);
+       raw_spin_lock_irqsave(&gic_lock, flags);
        switch (type & IRQ_TYPE_SENSE_MASK) {
        case IRQ_TYPE_EDGE_FALLING:
                pol = GIC_POL_FALLING_EDGE;
@@ -250,7 +250,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
        else
                irq_set_chip_handler_name_locked(d, &gic_level_irq_controller,
                                                 handle_level_irq, NULL);
-       spin_unlock_irqrestore(&gic_lock, flags);
+       raw_spin_unlock_irqrestore(&gic_lock, flags);
 
        return 0;
 }
@@ -268,7 +268,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
                return -EINVAL;
 
        /* Assumption : cpumask refers to a single CPU */
-       spin_lock_irqsave(&gic_lock, flags);
+       raw_spin_lock_irqsave(&gic_lock, flags);
 
        /* Re-route this IRQ */
        write_gic_map_vp(irq, BIT(mips_cm_vp_id(cpu)));
@@ -279,7 +279,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
                set_bit(irq, per_cpu_ptr(pcpu_masks, cpu));
 
        irq_data_update_effective_affinity(d, cpumask_of(cpu));
-       spin_unlock_irqrestore(&gic_lock, flags);
+       raw_spin_unlock_irqrestore(&gic_lock, flags);
 
        return IRQ_SET_MASK_OK;
 }
@@ -357,12 +357,12 @@ static void gic_mask_local_irq_all_vpes(struct irq_data *d)
        cd = irq_data_get_irq_chip_data(d);
        cd->mask = false;
 
-       spin_lock_irqsave(&gic_lock, flags);
+       raw_spin_lock_irqsave(&gic_lock, flags);
        for_each_online_cpu(cpu) {
                write_gic_vl_other(mips_cm_vp_id(cpu));
                write_gic_vo_rmask(BIT(intr));
        }
-       spin_unlock_irqrestore(&gic_lock, flags);
+       raw_spin_unlock_irqrestore(&gic_lock, flags);
 }
 
 static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
@@ -375,12 +375,12 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
        cd = irq_data_get_irq_chip_data(d);
        cd->mask = true;
 
-       spin_lock_irqsave(&gic_lock, flags);
+       raw_spin_lock_irqsave(&gic_lock, flags);
        for_each_online_cpu(cpu) {
                write_gic_vl_other(mips_cm_vp_id(cpu));
                write_gic_vo_smask(BIT(intr));
        }
-       spin_unlock_irqrestore(&gic_lock, flags);
+       raw_spin_unlock_irqrestore(&gic_lock, flags);
 }
 
 static void gic_all_vpes_irq_cpu_online(void)
@@ -393,19 +393,21 @@ static void gic_all_vpes_irq_cpu_online(void)
        unsigned long flags;
        int i;
 
-       spin_lock_irqsave(&gic_lock, flags);
+       raw_spin_lock_irqsave(&gic_lock, flags);
 
        for (i = 0; i < ARRAY_SIZE(local_intrs); i++) {
                unsigned int intr = local_intrs[i];
                struct gic_all_vpes_chip_data *cd;
 
+               if (!gic_local_irq_is_routable(intr))
+                       continue;
                cd = &gic_all_vpes_chip_data[intr];
                write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map);
                if (cd->mask)
                        write_gic_vl_smask(BIT(intr));
        }
 
-       spin_unlock_irqrestore(&gic_lock, flags);
+       raw_spin_unlock_irqrestore(&gic_lock, flags);
 }
 
 static struct irq_chip gic_all_vpes_local_irq_controller = {
@@ -435,11 +437,11 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
 
        data = irq_get_irq_data(virq);
 
-       spin_lock_irqsave(&gic_lock, flags);
+       raw_spin_lock_irqsave(&gic_lock, flags);
        write_gic_map_pin(intr, GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin);
        write_gic_map_vp(intr, BIT(mips_cm_vp_id(cpu)));
        irq_data_update_effective_affinity(data, cpumask_of(cpu));
-       spin_unlock_irqrestore(&gic_lock, flags);
+       raw_spin_unlock_irqrestore(&gic_lock, flags);
 
        return 0;
 }
@@ -531,12 +533,12 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
        if (!gic_local_irq_is_routable(intr))
                return -EPERM;
 
-       spin_lock_irqsave(&gic_lock, flags);
+       raw_spin_lock_irqsave(&gic_lock, flags);
        for_each_online_cpu(cpu) {
                write_gic_vl_other(mips_cm_vp_id(cpu));
                write_gic_vo_map(mips_gic_vx_map_reg(intr), map);
        }
-       spin_unlock_irqrestore(&gic_lock, flags);
+       raw_spin_unlock_irqrestore(&gic_lock, flags);
 
        return 0;
 }
index 2690e2c5a1584103f80bd9aa37c1da49fb838fb9..6fd1b3f84a29191a155da0445529d7784ad78433 100644 (file)
@@ -6,7 +6,6 @@
 menuconfig ISDN
        bool "ISDN support"
        depends on NET && NETDEVICES
-       depends on !S390 && !UML
        help
          ISDN ("Integrated Services Digital Network", called RNIS in France)
          is a fully digital telephone service that can be used for voice and
index 078eeadf707ae7ebd80b365b51b5966ff2fce098..a35bff8a93f5d2f5069a37ad554736f84fe5c2b7 100644 (file)
@@ -14,7 +14,7 @@ config MISDN_HFCPCI
 
 config MISDN_HFCMULTI
        tristate "Support for HFC multiport cards (HFC-4S/8S/E1)"
-       depends on PCI || CPM1
+       depends on (PCI || CPM1) && HAS_IOPORT
        depends on MISDN
        help
          Enable support for cards with Cologne Chip AG's HFC multiport
@@ -43,7 +43,7 @@ config MISDN_HFCUSB
 config MISDN_AVMFRITZ
        tristate "Support for AVM FRITZ!CARD PCI"
        depends on MISDN
-       depends on PCI
+       depends on PCI && HAS_IOPORT
        select MISDN_IPAC
        help
          Enable support for AVMs FRITZ!CARD PCI cards
@@ -51,7 +51,7 @@ config MISDN_AVMFRITZ
 config MISDN_SPEEDFAX
        tristate "Support for Sedlbauer Speedfax+"
        depends on MISDN
-       depends on PCI
+       depends on PCI && HAS_IOPORT
        select MISDN_IPAC
        select MISDN_ISAR
        help
@@ -60,7 +60,7 @@ config MISDN_SPEEDFAX
 config MISDN_INFINEON
        tristate "Support for cards with Infineon chipset"
        depends on MISDN
-       depends on PCI
+       depends on PCI && HAS_IOPORT
        select MISDN_IPAC
        help
          Enable support for cards with ISAC + HSCX, IPAC or IPAC-SX
@@ -69,14 +69,14 @@ config MISDN_INFINEON
 config MISDN_W6692
        tristate "Support for cards with Winbond 6692"
        depends on MISDN
-       depends on PCI
+       depends on PCI && HAS_IOPORT
        help
          Enable support for Winbond 6692 PCI chip based cards.
 
 config MISDN_NETJET
        tristate "Support for NETJet cards"
        depends on MISDN
-       depends on PCI
+       depends on PCI && HAS_IOPORT
        depends on TTY
        select MISDN_IPAC
        select MISDN_HDLC
index 55a037234df1b07c44fab18846bfa17e705c1af1..1c849814a4917fe5805a3f1aa8bf87831366a759 100644 (file)
@@ -312,14 +312,14 @@ static int lpg_calc_freq(struct lpg_channel *chan, uint64_t period)
                max_res = LPG_RESOLUTION_9BIT;
        }
 
-       min_period = (u64)NSEC_PER_SEC *
-                       div64_u64((1 << pwm_resolution_arr[0]), clk_rate_arr[clk_len - 1]);
+       min_period = div64_u64((u64)NSEC_PER_SEC * (1 << pwm_resolution_arr[0]),
+                              clk_rate_arr[clk_len - 1]);
        if (period <= min_period)
                return -EINVAL;
 
        /* Limit period to largest possible value, to avoid overflows */
-       max_period = (u64)NSEC_PER_SEC * max_res * LPG_MAX_PREDIV *
-                       div64_u64((1 << LPG_MAX_M), 1024);
+       max_period = div64_u64((u64)NSEC_PER_SEC * max_res * LPG_MAX_PREDIV * (1 << LPG_MAX_M),
+                              1024);
        if (period > max_period)
                period = max_period;
 
index c4a705c30331421e08e31606a12285d56a6d8682..fc6a12a51b403863d7dcb36a63a54b5a76c2f135 100644 (file)
@@ -98,6 +98,7 @@ static ssize_t mbox_test_message_write(struct file *filp,
                                       size_t count, loff_t *ppos)
 {
        struct mbox_test_device *tdev = filp->private_data;
+       char *message;
        void *data;
        int ret;
 
@@ -113,12 +114,13 @@ static ssize_t mbox_test_message_write(struct file *filp,
                return -EINVAL;
        }
 
-       mutex_lock(&tdev->mutex);
-
-       tdev->message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL);
-       if (!tdev->message)
+       message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL);
+       if (!message)
                return -ENOMEM;
 
+       mutex_lock(&tdev->mutex);
+
+       tdev->message = message;
        ret = copy_from_user(tdev->message, userbuf, count);
        if (ret) {
                ret = -EFAULT;
index 4739ed891e756eb3a8af3e7c48c6be0950b82db7..9ea285fbc4a654703f363f7d450c903d5e8c6d77 100644 (file)
@@ -5516,7 +5516,7 @@ static int raid5_read_one_chunk(struct mddev *mddev, struct bio *raid_bio)
 
        sector = raid5_compute_sector(conf, raid_bio->bi_iter.bi_sector, 0,
                                      &dd_idx, NULL);
-       end_sector = bio_end_sector(raid_bio);
+       end_sector = sector + bio_sectors(raid_bio);
 
        rcu_read_lock();
        if (r5c_big_stripe_cached(conf, sector))
index 769ea6b2e1d0b6776f16e78a0ccb71d4c03e8668..241b1621b197c4f64677a6a16108f72b7322db11 100644 (file)
@@ -1091,7 +1091,8 @@ void cec_received_msg_ts(struct cec_adapter *adap,
        mutex_lock(&adap->lock);
        dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg);
 
-       adap->last_initiator = 0xff;
+       if (!adap->transmit_in_progress)
+               adap->last_initiator = 0xff;
 
        /* Check if this message was for us (directed or broadcast). */
        if (!cec_msg_is_broadcast(msg)) {
@@ -1585,7 +1586,7 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
  *
  * This function is called with adap->lock held.
  */
-static int cec_adap_enable(struct cec_adapter *adap)
+int cec_adap_enable(struct cec_adapter *adap)
 {
        bool enable;
        int ret = 0;
@@ -1595,6 +1596,9 @@ static int cec_adap_enable(struct cec_adapter *adap)
        if (adap->needs_hpd)
                enable = enable && adap->phys_addr != CEC_PHYS_ADDR_INVALID;
 
+       if (adap->devnode.unregistered)
+               enable = false;
+
        if (enable == adap->is_enabled)
                return 0;
 
index af358e901b5f35c6cf05f7a7bc5fd954ae3b5854..7e153c5cad04f50d58824da520cc019409bd4a87 100644 (file)
@@ -191,6 +191,8 @@ static void cec_devnode_unregister(struct cec_adapter *adap)
        mutex_lock(&adap->lock);
        __cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false);
        __cec_s_log_addrs(adap, NULL, false);
+       // Disable the adapter (since adap->devnode.unregistered is true)
+       cec_adap_enable(adap);
        mutex_unlock(&adap->lock);
 
        cdev_device_del(&devnode->cdev, &devnode->dev);
index b78df931aa74b04a2699bbb11f0c140cccf7de46..ed1f8c67626bf9cee44f4596307b9c95aa62e4e5 100644 (file)
@@ -47,6 +47,7 @@ int cec_monitor_pin_cnt_inc(struct cec_adapter *adap);
 void cec_monitor_pin_cnt_dec(struct cec_adapter *adap);
 int cec_adap_status(struct seq_file *file, void *priv);
 int cec_thread_func(void *_adap);
+int cec_adap_enable(struct cec_adapter *adap);
 void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block);
 int __cec_s_log_addrs(struct cec_adapter *adap,
                      struct cec_log_addrs *log_addrs, bool block);
index c2d2792227f865ff934f0effa3eda98ecef7802d..baf64540dc00a127c5f781034b1fec192e7e4ca2 100644 (file)
@@ -151,6 +151,12 @@ struct dvb_ca_private {
 
        /* mutex serializing ioctls */
        struct mutex ioctl_mutex;
+
+       /* A mutex used when a device is disconnected */
+       struct mutex remove_mutex;
+
+       /* Whether the device is disconnected */
+       int exit;
 };
 
 static void dvb_ca_private_free(struct dvb_ca_private *ca)
@@ -187,7 +193,7 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca);
 static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
                                    u8 *ebuf, int ecount);
 static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
-                                    u8 *ebuf, int ecount);
+                                    u8 *ebuf, int ecount, int size_write_flag);
 
 /**
  * findstr - Safely find needle in haystack.
@@ -370,7 +376,7 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
        ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10);
        if (ret)
                return ret;
-       ret = dvb_ca_en50221_write_data(ca, slot, buf, 2);
+       ret = dvb_ca_en50221_write_data(ca, slot, buf, 2, CMDREG_SW);
        if (ret != 2)
                return -EIO;
        ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
@@ -778,11 +784,13 @@ exit:
  * @buf: The data in this buffer is treated as a complete link-level packet to
  *      be written.
  * @bytes_write: Size of ebuf.
+ * @size_write_flag: A flag on Command Register which says whether the link size
+ * information will be writen or not.
  *
  * return: Number of bytes written, or < 0 on error.
  */
 static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
-                                    u8 *buf, int bytes_write)
+                                    u8 *buf, int bytes_write, int size_write_flag)
 {
        struct dvb_ca_slot *sl = &ca->slot_info[slot];
        int status;
@@ -817,7 +825,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
 
        /* OK, set HC bit */
        status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND,
-                                           IRQEN | CMDREG_HC);
+                                           IRQEN | CMDREG_HC | size_write_flag);
        if (status)
                goto exit;
 
@@ -1508,7 +1516,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
 
                        mutex_lock(&sl->slot_lock);
                        status = dvb_ca_en50221_write_data(ca, slot, fragbuf,
-                                                          fraglen + 2);
+                                                          fraglen + 2, 0);
                        mutex_unlock(&sl->slot_lock);
                        if (status == (fraglen + 2)) {
                                written = 1;
@@ -1709,12 +1717,22 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
 
        dprintk("%s\n", __func__);
 
-       if (!try_module_get(ca->pub->owner))
+       mutex_lock(&ca->remove_mutex);
+
+       if (ca->exit) {
+               mutex_unlock(&ca->remove_mutex);
+               return -ENODEV;
+       }
+
+       if (!try_module_get(ca->pub->owner)) {
+               mutex_unlock(&ca->remove_mutex);
                return -EIO;
+       }
 
        err = dvb_generic_open(inode, file);
        if (err < 0) {
                module_put(ca->pub->owner);
+               mutex_unlock(&ca->remove_mutex);
                return err;
        }
 
@@ -1739,6 +1757,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
 
        dvb_ca_private_get(ca);
 
+       mutex_unlock(&ca->remove_mutex);
        return 0;
 }
 
@@ -1758,6 +1777,8 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
 
        dprintk("%s\n", __func__);
 
+       mutex_lock(&ca->remove_mutex);
+
        /* mark the CA device as closed */
        ca->open = 0;
        dvb_ca_en50221_thread_update_delay(ca);
@@ -1768,6 +1789,13 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
 
        dvb_ca_private_put(ca);
 
+       if (dvbdev->users == 1 && ca->exit == 1) {
+               mutex_unlock(&ca->remove_mutex);
+               wake_up(&dvbdev->wait_queue);
+       } else {
+               mutex_unlock(&ca->remove_mutex);
+       }
+
        return err;
 }
 
@@ -1891,6 +1919,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
        }
 
        mutex_init(&ca->ioctl_mutex);
+       mutex_init(&ca->remove_mutex);
 
        if (signal_pending(current)) {
                ret = -EINTR;
@@ -1933,6 +1962,14 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
 
        dprintk("%s\n", __func__);
 
+       mutex_lock(&ca->remove_mutex);
+       ca->exit = 1;
+       mutex_unlock(&ca->remove_mutex);
+
+       if (ca->dvbdev->users < 1)
+               wait_event(ca->dvbdev->wait_queue,
+                               ca->dvbdev->users == 1);
+
        /* shutdown the thread if there was one */
        kthread_stop(ca->thread);
 
index 398c86279b5b09555590c5c3ac4d3a8798c9c103..7c4d86bfdd6c9d259ab99b57cd3ce355f3b341ad 100644 (file)
@@ -115,12 +115,12 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
 
        cc = buf[3] & 0x0f;
        ccok = ((feed->cc + 1) & 0x0f) == cc;
-       feed->cc = cc;
        if (!ccok) {
                set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
                dprintk_sect_loss("missed packet: %d instead of %d!\n",
                                  cc, (feed->cc + 1) & 0x0f);
        }
+       feed->cc = cc;
 
        if (buf[1] & 0x40)      // PUSI ?
                feed->peslen = 0xfffa;
@@ -300,7 +300,6 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
 
        cc = buf[3] & 0x0f;
        ccok = ((feed->cc + 1) & 0x0f) == cc;
-       feed->cc = cc;
 
        if (buf[3] & 0x20) {
                /* adaption field present, check for discontinuity_indicator */
@@ -336,6 +335,7 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
                feed->pusi_seen = false;
                dvb_dmx_swfilter_section_new(feed);
        }
+       feed->cc = cc;
 
        if (buf[1] & 0x40) {
                /* PUSI=1 (is set), section boundary is here */
index cc0a789f09ae5360c43aaaa8d989704790ff6d17..bc6950a5740f6a56b971a9c6d372989e705312a4 100644 (file)
@@ -293,14 +293,22 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
        }
 
        if (events->eventw == events->eventr) {
-               int ret;
+               struct wait_queue_entry wait;
+               int ret = 0;
 
                if (flags & O_NONBLOCK)
                        return -EWOULDBLOCK;
 
-               ret = wait_event_interruptible(events->wait_queue,
-                                              dvb_frontend_test_event(fepriv, events));
-
+               init_waitqueue_entry(&wait, current);
+               add_wait_queue(&events->wait_queue, &wait);
+               while (!dvb_frontend_test_event(fepriv, events)) {
+                       wait_woken(&wait, TASK_INTERRUPTIBLE, 0);
+                       if (signal_pending(current)) {
+                               ret = -ERESTARTSYS;
+                               break;
+                       }
+               }
+               remove_wait_queue(&events->wait_queue, &wait);
                if (ret < 0)
                        return ret;
        }
@@ -809,15 +817,26 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
 
        dev_dbg(fe->dvb->device, "%s:\n", __func__);
 
+       mutex_lock(&fe->remove_mutex);
+
        if (fe->exit != DVB_FE_DEVICE_REMOVED)
                fe->exit = DVB_FE_NORMAL_EXIT;
        mb();
 
-       if (!fepriv->thread)
+       if (!fepriv->thread) {
+               mutex_unlock(&fe->remove_mutex);
                return;
+       }
 
        kthread_stop(fepriv->thread);
 
+       mutex_unlock(&fe->remove_mutex);
+
+       if (fepriv->dvbdev->users < -1) {
+               wait_event(fepriv->dvbdev->wait_queue,
+                          fepriv->dvbdev->users == -1);
+       }
+
        sema_init(&fepriv->sem, 1);
        fepriv->state = FESTATE_IDLE;
 
@@ -2761,9 +2780,13 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
        struct dvb_adapter *adapter = fe->dvb;
        int ret;
 
+       mutex_lock(&fe->remove_mutex);
+
        dev_dbg(fe->dvb->device, "%s:\n", __func__);
-       if (fe->exit == DVB_FE_DEVICE_REMOVED)
-               return -ENODEV;
+       if (fe->exit == DVB_FE_DEVICE_REMOVED) {
+               ret = -ENODEV;
+               goto err_remove_mutex;
+       }
 
        if (adapter->mfe_shared == 2) {
                mutex_lock(&adapter->mfe_lock);
@@ -2771,7 +2794,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
                        if (adapter->mfe_dvbdev &&
                            !adapter->mfe_dvbdev->writers) {
                                mutex_unlock(&adapter->mfe_lock);
-                               return -EBUSY;
+                               ret = -EBUSY;
+                               goto err_remove_mutex;
                        }
                        adapter->mfe_dvbdev = dvbdev;
                }
@@ -2794,8 +2818,10 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
                        while (mferetry-- && (mfedev->users != -1 ||
                                              mfepriv->thread)) {
                                if (msleep_interruptible(500)) {
-                                       if (signal_pending(current))
-                                               return -EINTR;
+                                       if (signal_pending(current)) {
+                                               ret = -EINTR;
+                                               goto err_remove_mutex;
+                                       }
                                }
                        }
 
@@ -2807,7 +2833,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
                                if (mfedev->users != -1 ||
                                    mfepriv->thread) {
                                        mutex_unlock(&adapter->mfe_lock);
-                                       return -EBUSY;
+                                       ret = -EBUSY;
+                                       goto err_remove_mutex;
                                }
                                adapter->mfe_dvbdev = dvbdev;
                        }
@@ -2866,6 +2893,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
 
        if (adapter->mfe_shared)
                mutex_unlock(&adapter->mfe_lock);
+
+       mutex_unlock(&fe->remove_mutex);
        return ret;
 
 err3:
@@ -2887,6 +2916,9 @@ err1:
 err0:
        if (adapter->mfe_shared)
                mutex_unlock(&adapter->mfe_lock);
+
+err_remove_mutex:
+       mutex_unlock(&fe->remove_mutex);
        return ret;
 }
 
@@ -2897,6 +2929,8 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        int ret;
 
+       mutex_lock(&fe->remove_mutex);
+
        dev_dbg(fe->dvb->device, "%s:\n", __func__);
 
        if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
@@ -2918,10 +2952,18 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
                }
                mutex_unlock(&fe->dvb->mdev_lock);
 #endif
-               if (fe->exit != DVB_FE_NO_EXIT)
-                       wake_up(&dvbdev->wait_queue);
                if (fe->ops.ts_bus_ctrl)
                        fe->ops.ts_bus_ctrl(fe, 0);
+
+               if (fe->exit != DVB_FE_NO_EXIT) {
+                       mutex_unlock(&fe->remove_mutex);
+                       wake_up(&dvbdev->wait_queue);
+               } else {
+                       mutex_unlock(&fe->remove_mutex);
+               }
+
+       } else {
+               mutex_unlock(&fe->remove_mutex);
        }
 
        dvb_frontend_put(fe);
@@ -3022,6 +3064,7 @@ int dvb_register_frontend(struct dvb_adapter *dvb,
        fepriv = fe->frontend_priv;
 
        kref_init(&fe->refcount);
+       mutex_init(&fe->remove_mutex);
 
        /*
         * After initialization, there need to be two references: one
index 8a2febf33ce28fde43676e66f7381e59d032f4d1..8bb8dd34c223e91119059965851de57cac9af8e5 100644 (file)
@@ -1564,15 +1564,43 @@ static long dvb_net_ioctl(struct file *file,
        return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
 }
 
+static int locked_dvb_net_open(struct inode *inode, struct file *file)
+{
+       struct dvb_device *dvbdev = file->private_data;
+       struct dvb_net *dvbnet = dvbdev->priv;
+       int ret;
+
+       if (mutex_lock_interruptible(&dvbnet->remove_mutex))
+               return -ERESTARTSYS;
+
+       if (dvbnet->exit) {
+               mutex_unlock(&dvbnet->remove_mutex);
+               return -ENODEV;
+       }
+
+       ret = dvb_generic_open(inode, file);
+
+       mutex_unlock(&dvbnet->remove_mutex);
+
+       return ret;
+}
+
 static int dvb_net_close(struct inode *inode, struct file *file)
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dvb_net *dvbnet = dvbdev->priv;
 
+       mutex_lock(&dvbnet->remove_mutex);
+
        dvb_generic_release(inode, file);
 
-       if(dvbdev->users == 1 && dvbnet->exit == 1)
+       if (dvbdev->users == 1 && dvbnet->exit == 1) {
+               mutex_unlock(&dvbnet->remove_mutex);
                wake_up(&dvbdev->wait_queue);
+       } else {
+               mutex_unlock(&dvbnet->remove_mutex);
+       }
+
        return 0;
 }
 
@@ -1580,7 +1608,7 @@ static int dvb_net_close(struct inode *inode, struct file *file)
 static const struct file_operations dvb_net_fops = {
        .owner = THIS_MODULE,
        .unlocked_ioctl = dvb_net_ioctl,
-       .open = dvb_generic_open,
+       .open = locked_dvb_net_open,
        .release = dvb_net_close,
        .llseek = noop_llseek,
 };
@@ -1599,10 +1627,13 @@ void dvb_net_release (struct dvb_net *dvbnet)
 {
        int i;
 
+       mutex_lock(&dvbnet->remove_mutex);
        dvbnet->exit = 1;
+       mutex_unlock(&dvbnet->remove_mutex);
+
        if (dvbnet->dvbdev->users < 1)
                wait_event(dvbnet->dvbdev->wait_queue,
-                               dvbnet->dvbdev->users==1);
+                               dvbnet->dvbdev->users == 1);
 
        dvb_unregister_device(dvbnet->dvbdev);
 
@@ -1621,6 +1652,7 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
        int i;
 
        mutex_init(&dvbnet->ioctl_mutex);
+       mutex_init(&dvbnet->remove_mutex);
        dvbnet->demux = dmx;
 
        for (i=0; i<DVB_NET_DEVICES_MAX; i++)
index e9b3ce09e534c1698a28e4ba52b1e38f9f54cf15..a4b05e366cccde2fd0c78d3990bf5710b1fb0ac9 100644 (file)
@@ -27,6 +27,7 @@
 #include <media/tuner.h>
 
 static DEFINE_MUTEX(dvbdev_mutex);
+static LIST_HEAD(dvbdevfops_list);
 static int dvbdev_debug;
 
 module_param(dvbdev_debug, int, 0644);
@@ -453,14 +454,15 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
                        enum dvb_device_type type, int demux_sink_pads)
 {
        struct dvb_device *dvbdev;
-       struct file_operations *dvbdevfops;
+       struct file_operations *dvbdevfops = NULL;
+       struct dvbdevfops_node *node = NULL, *new_node = NULL;
        struct device *clsdev;
        int minor;
        int id, ret;
 
        mutex_lock(&dvbdev_register_lock);
 
-       if ((id = dvbdev_get_free_id (adap, type)) < 0){
+       if ((id = dvbdev_get_free_id (adap, type)) < 0) {
                mutex_unlock(&dvbdev_register_lock);
                *pdvbdev = NULL;
                pr_err("%s: couldn't find free device id\n", __func__);
@@ -468,18 +470,45 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
        }
 
        *pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL);
-
        if (!dvbdev){
                mutex_unlock(&dvbdev_register_lock);
                return -ENOMEM;
        }
 
-       dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL);
+       /*
+        * When a device of the same type is probe()d more than once,
+        * the first allocated fops are used. This prevents memory leaks
+        * that can occur when the same device is probe()d repeatedly.
+        */
+       list_for_each_entry(node, &dvbdevfops_list, list_head) {
+               if (node->fops->owner == adap->module &&
+                               node->type == type &&
+                               node->template == template) {
+                       dvbdevfops = node->fops;
+                       break;
+               }
+       }
 
-       if (!dvbdevfops){
-               kfree (dvbdev);
-               mutex_unlock(&dvbdev_register_lock);
-               return -ENOMEM;
+       if (dvbdevfops == NULL) {
+               dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL);
+               if (!dvbdevfops) {
+                       kfree(dvbdev);
+                       mutex_unlock(&dvbdev_register_lock);
+                       return -ENOMEM;
+               }
+
+               new_node = kzalloc(sizeof(struct dvbdevfops_node), GFP_KERNEL);
+               if (!new_node) {
+                       kfree(dvbdevfops);
+                       kfree(dvbdev);
+                       mutex_unlock(&dvbdev_register_lock);
+                       return -ENOMEM;
+               }
+
+               new_node->fops = dvbdevfops;
+               new_node->type = type;
+               new_node->template = template;
+               list_add_tail (&new_node->list_head, &dvbdevfops_list);
        }
 
        memcpy(dvbdev, template, sizeof(struct dvb_device));
@@ -490,20 +519,20 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
        dvbdev->priv = priv;
        dvbdev->fops = dvbdevfops;
        init_waitqueue_head (&dvbdev->wait_queue);
-
        dvbdevfops->owner = adap->module;
-
        list_add_tail (&dvbdev->list_head, &adap->device_list);
-
        down_write(&minor_rwsem);
 #ifdef CONFIG_DVB_DYNAMIC_MINORS
        for (minor = 0; minor < MAX_DVB_MINORS; minor++)
                if (dvb_minors[minor] == NULL)
                        break;
-
        if (minor == MAX_DVB_MINORS) {
+               if (new_node) {
+                       list_del (&new_node->list_head);
+                       kfree(dvbdevfops);
+                       kfree(new_node);
+               }
                list_del (&dvbdev->list_head);
-               kfree(dvbdevfops);
                kfree(dvbdev);
                up_write(&minor_rwsem);
                mutex_unlock(&dvbdev_register_lock);
@@ -512,41 +541,47 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 #else
        minor = nums2minor(adap->num, type, id);
 #endif
-
        dvbdev->minor = minor;
        dvb_minors[minor] = dvb_device_get(dvbdev);
        up_write(&minor_rwsem);
-
        ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
        if (ret) {
                pr_err("%s: dvb_register_media_device failed to create the mediagraph\n",
                      __func__);
-
+               if (new_node) {
+                       list_del (&new_node->list_head);
+                       kfree(dvbdevfops);
+                       kfree(new_node);
+               }
                dvb_media_device_free(dvbdev);
                list_del (&dvbdev->list_head);
-               kfree(dvbdevfops);
                kfree(dvbdev);
                mutex_unlock(&dvbdev_register_lock);
                return ret;
        }
 
-       mutex_unlock(&dvbdev_register_lock);
-
        clsdev = device_create(dvb_class, adap->device,
                               MKDEV(DVB_MAJOR, minor),
                               dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
        if (IS_ERR(clsdev)) {
                pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n",
                       __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
+               if (new_node) {
+                       list_del (&new_node->list_head);
+                       kfree(dvbdevfops);
+                       kfree(new_node);
+               }
                dvb_media_device_free(dvbdev);
                list_del (&dvbdev->list_head);
-               kfree(dvbdevfops);
                kfree(dvbdev);
+               mutex_unlock(&dvbdev_register_lock);
                return PTR_ERR(clsdev);
        }
+
        dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
                adap->num, dnames[type], id, minor, minor);
 
+       mutex_unlock(&dvbdev_register_lock);
        return 0;
 }
 EXPORT_SYMBOL(dvb_register_device);
@@ -575,7 +610,6 @@ static void dvb_free_device(struct kref *ref)
 {
        struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref);
 
-       kfree (dvbdev->fops);
        kfree (dvbdev);
 }
 
@@ -1081,9 +1115,17 @@ error:
 
 static void __exit exit_dvbdev(void)
 {
+       struct dvbdevfops_node *node, *next;
+
        class_destroy(dvb_class);
        cdev_del(&dvb_device_cdev);
        unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
+
+       list_for_each_entry_safe(node, next, &dvbdevfops_list, list_head) {
+               list_del (&node->list_head);
+               kfree(node->fops);
+               kfree(node);
+       }
 }
 
 subsys_initcall(init_dvbdev);
index 1f1753f2ab1a3ed5f1b52a87d9848e132cb94645..0782f8377eb2f333731fe93de70f0804d95ffcc5 100644 (file)
@@ -798,7 +798,7 @@ MODULE_DEVICE_TABLE(i2c, mn88443x_i2c_id);
 static struct i2c_driver mn88443x_driver = {
        .driver = {
                .name = "mn88443x",
-               .of_match_table = of_match_ptr(mn88443x_of_match),
+               .of_match_table = mn88443x_of_match,
        },
        .probe_new = mn88443x_probe,
        .remove   = mn88443x_remove,
index 8287851b5ffdc8d591bc2f1354eaa136168e057d..d85bfbb77a2509eaf5da9b4716d86eb3d05e3bc1 100644 (file)
@@ -697,7 +697,7 @@ static void netup_unidvb_dma_fini(struct netup_unidvb_dev *ndev, int num)
        netup_unidvb_dma_enable(dma, 0);
        msleep(50);
        cancel_work_sync(&dma->work);
-       del_timer(&dma->timeout);
+       del_timer_sync(&dma->timeout);
 }
 
 static int netup_unidvb_dma_setup(struct netup_unidvb_dev *ndev)
@@ -887,12 +887,7 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev,
                ndev->lmmio0, (u32)pci_resource_len(pci_dev, 0),
                ndev->lmmio1, (u32)pci_resource_len(pci_dev, 1),
                pci_dev->irq);
-       if (request_irq(pci_dev->irq, netup_unidvb_isr, IRQF_SHARED,
-                       "netup_unidvb", pci_dev) < 0) {
-               dev_err(&pci_dev->dev,
-                       "%s(): can't get IRQ %d\n", __func__, pci_dev->irq);
-               goto irq_request_err;
-       }
+
        ndev->dma_size = 2 * 188 *
                NETUP_DMA_BLOCKS_COUNT * NETUP_DMA_PACKETS_COUNT;
        ndev->dma_virt = dma_alloc_coherent(&pci_dev->dev,
@@ -933,6 +928,14 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev,
                dev_err(&pci_dev->dev, "netup_unidvb: DMA setup failed\n");
                goto dma_setup_err;
        }
+
+       if (request_irq(pci_dev->irq, netup_unidvb_isr, IRQF_SHARED,
+                       "netup_unidvb", pci_dev) < 0) {
+               dev_err(&pci_dev->dev,
+                       "%s(): can't get IRQ %d\n", __func__, pci_dev->irq);
+               goto dma_setup_err;
+       }
+
        dev_info(&pci_dev->dev,
                "netup_unidvb: device has been initialized\n");
        return 0;
@@ -951,8 +954,6 @@ spi_setup_err:
        dma_free_coherent(&pci_dev->dev, ndev->dma_size,
                        ndev->dma_virt, ndev->dma_phys);
 dma_alloc_err:
-       free_irq(pci_dev->irq, pci_dev);
-irq_request_err:
        iounmap(ndev->lmmio1);
 pci_bar1_error:
        iounmap(ndev->lmmio0);
index 75c92e282fa298d9f9367020302c31fba11031c6..19a4a085f73a1dc540e92da8a08c91f718981cda 100644 (file)
@@ -1035,7 +1035,6 @@ static int mdp_comp_sub_create(struct mdp_dev *mdp)
 {
        struct device *dev = &mdp->pdev->dev;
        struct device_node *node, *parent;
-       const struct mtk_mdp_driver_data *data = mdp->mdp_data;
 
        parent = dev->of_node->parent;
 
@@ -1045,7 +1044,7 @@ static int mdp_comp_sub_create(struct mdp_dev *mdp)
                int id, alias_id;
                struct mdp_comp *comp;
 
-               of_id = of_match_node(data->mdp_sub_comp_dt_ids, node);
+               of_id = of_match_node(mdp->mdp_data->mdp_sub_comp_dt_ids, node);
                if (!of_id)
                        continue;
                if (!of_device_is_available(node)) {
index 29991551cf6140671e486490ff648871b0860250..0fbd030026c729620314e7f15355bb9c24f2797a 100644 (file)
@@ -584,6 +584,9 @@ static void mtk_init_vdec_params(struct mtk_vcodec_ctx *ctx)
 
        if (!(ctx->dev->dec_capability & VCODEC_CAPABILITY_4K_DISABLED)) {
                for (i = 0; i < num_supported_formats; i++) {
+                       if (mtk_video_formats[i].type != MTK_FMT_DEC)
+                               continue;
+
                        mtk_video_formats[i].frmsize.max_width =
                                VCODEC_DEC_4K_CODED_WIDTH;
                        mtk_video_formats[i].frmsize.max_height =
index 238521622b75068bca2b49fbb3ef3d49d6e0e57d..253e77189b69f6722bb1c52f7dbb96b0cc31bf18 100644 (file)
@@ -378,8 +378,8 @@ static int mxc_isi_runtime_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops mxc_isi_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(mxc_isi_pm_suspend, mxc_isi_pm_resume)
-       SET_RUNTIME_PM_OPS(mxc_isi_runtime_suspend, mxc_isi_runtime_resume, NULL)
+       SYSTEM_SLEEP_PM_OPS(mxc_isi_pm_suspend, mxc_isi_pm_resume)
+       RUNTIME_PM_OPS(mxc_isi_runtime_suspend, mxc_isi_runtime_resume, NULL)
 };
 
 /* -----------------------------------------------------------------------------
@@ -528,7 +528,7 @@ static struct platform_driver mxc_isi_driver = {
        .driver = {
                .of_match_table = mxc_isi_of_match,
                .name           = MXC_ISI_DRIVER_NAME,
-               .pm             = &mxc_isi_pm_ops,
+               .pm             = pm_ptr(&mxc_isi_pm_ops),
        }
 };
 module_platform_driver(mxc_isi_driver);
index db538f3d88ecec9de56120a4dab51e781664049f..19e80b95ffeaa39ce7c02366b30c97b34f31d08c 100644 (file)
@@ -29,11 +29,10 @@ static inline void mxc_isi_write(struct mxc_isi_pipe *pipe, u32 reg, u32 val)
 
 void mxc_isi_channel_set_inbuf(struct mxc_isi_pipe *pipe, dma_addr_t dma_addr)
 {
-       mxc_isi_write(pipe, CHNL_IN_BUF_ADDR, dma_addr);
-#if CONFIG_ARCH_DMA_ADDR_T_64BIT
+       mxc_isi_write(pipe, CHNL_IN_BUF_ADDR, lower_32_bits(dma_addr));
        if (pipe->isi->pdata->has_36bit_dma)
-               mxc_isi_write(pipe, CHNL_IN_BUF_XTND_ADDR, dma_addr >> 32);
-#endif
+               mxc_isi_write(pipe, CHNL_IN_BUF_XTND_ADDR,
+                             upper_32_bits(dma_addr));
 }
 
 void mxc_isi_channel_set_outbuf(struct mxc_isi_pipe *pipe,
@@ -45,34 +44,36 @@ void mxc_isi_channel_set_outbuf(struct mxc_isi_pipe *pipe,
        val = mxc_isi_read(pipe, CHNL_OUT_BUF_CTRL);
 
        if (buf_id == MXC_ISI_BUF1) {
-               mxc_isi_write(pipe, CHNL_OUT_BUF1_ADDR_Y, dma_addrs[0]);
-               mxc_isi_write(pipe, CHNL_OUT_BUF1_ADDR_U, dma_addrs[1]);
-               mxc_isi_write(pipe, CHNL_OUT_BUF1_ADDR_V, dma_addrs[2]);
-#if CONFIG_ARCH_DMA_ADDR_T_64BIT
+               mxc_isi_write(pipe, CHNL_OUT_BUF1_ADDR_Y,
+                             lower_32_bits(dma_addrs[0]));
+               mxc_isi_write(pipe, CHNL_OUT_BUF1_ADDR_U,
+                             lower_32_bits(dma_addrs[1]));
+               mxc_isi_write(pipe, CHNL_OUT_BUF1_ADDR_V,
+                             lower_32_bits(dma_addrs[2]));
                if (pipe->isi->pdata->has_36bit_dma) {
                        mxc_isi_write(pipe, CHNL_Y_BUF1_XTND_ADDR,
-                                     dma_addrs[0] >> 32);
+                                     upper_32_bits(dma_addrs[0]));
                        mxc_isi_write(pipe, CHNL_U_BUF1_XTND_ADDR,
-                                     dma_addrs[1] >> 32);
+                                     upper_32_bits(dma_addrs[1]));
                        mxc_isi_write(pipe, CHNL_V_BUF1_XTND_ADDR,
-                                     dma_addrs[2] >> 32);
+                                     upper_32_bits(dma_addrs[2]));
                }
-#endif
                val ^= CHNL_OUT_BUF_CTRL_LOAD_BUF1_ADDR;
        } else  {
-               mxc_isi_write(pipe, CHNL_OUT_BUF2_ADDR_Y, dma_addrs[0]);
-               mxc_isi_write(pipe, CHNL_OUT_BUF2_ADDR_U, dma_addrs[1]);
-               mxc_isi_write(pipe, CHNL_OUT_BUF2_ADDR_V, dma_addrs[2]);
-#if CONFIG_ARCH_DMA_ADDR_T_64BIT
+               mxc_isi_write(pipe, CHNL_OUT_BUF2_ADDR_Y,
+                             lower_32_bits(dma_addrs[0]));
+               mxc_isi_write(pipe, CHNL_OUT_BUF2_ADDR_U,
+                             lower_32_bits(dma_addrs[1]));
+               mxc_isi_write(pipe, CHNL_OUT_BUF2_ADDR_V,
+                             lower_32_bits(dma_addrs[2]));
                if (pipe->isi->pdata->has_36bit_dma) {
                        mxc_isi_write(pipe, CHNL_Y_BUF2_XTND_ADDR,
-                                     dma_addrs[0] >> 32);
+                                     upper_32_bits(dma_addrs[0]));
                        mxc_isi_write(pipe, CHNL_U_BUF2_XTND_ADDR,
-                                     dma_addrs[1] >> 32);
+                                     upper_32_bits(dma_addrs[1]));
                        mxc_isi_write(pipe, CHNL_V_BUF2_XTND_ADDR,
-                                     dma_addrs[2] >> 32);
+                                     upper_32_bits(dma_addrs[2]));
                }
-#endif
                val ^= CHNL_OUT_BUF_CTRL_LOAD_BUF2_ADDR;
        }
 
index 898f32177b12a5cc2b6aa6a65b9c7f1b8719bd45..8640db306026804270e82cb4642f9592f51b5c0b 100644 (file)
@@ -353,7 +353,6 @@ static int video_get_subdev_format(struct camss_video *video,
        if (subdev == NULL)
                return -EPIPE;
 
-       memset(&fmt, 0, sizeof(fmt));
        fmt.pad = pad;
 
        ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
index 98bfd445a649bcc4d32a217988dfcac0b6e51912..2a77353f10b59262e9f7ed3640dea07104fe7584 100644 (file)
@@ -728,11 +728,9 @@ static int rvin_setup(struct rvin_dev *vin)
        case V4L2_FIELD_SEQ_TB:
        case V4L2_FIELD_SEQ_BT:
        case V4L2_FIELD_NONE:
-               vnmc = VNMC_IM_ODD_EVEN;
-               progressive = true;
-               break;
        case V4L2_FIELD_ALTERNATE:
                vnmc = VNMC_IM_ODD_EVEN;
+               progressive = true;
                break;
        default:
                vnmc = VNMC_IM_ODD;
@@ -1312,12 +1310,23 @@ static int rvin_mc_validate_format(struct rvin_dev *vin, struct v4l2_subdev *sd,
        }
 
        if (rvin_scaler_needed(vin)) {
+               /* Gen3 can't scale NV12 */
+               if (vin->info->model == RCAR_GEN3 &&
+                   vin->format.pixelformat == V4L2_PIX_FMT_NV12)
+                       return -EPIPE;
+
                if (!vin->scaler)
                        return -EPIPE;
        } else {
-               if (fmt.format.width != vin->format.width ||
-                   fmt.format.height != vin->format.height)
-                       return -EPIPE;
+               if (vin->format.pixelformat == V4L2_PIX_FMT_NV12) {
+                       if (ALIGN(fmt.format.width, 32) != vin->format.width ||
+                           ALIGN(fmt.format.height, 32) != vin->format.height)
+                               return -EPIPE;
+               } else {
+                       if (fmt.format.width != vin->format.width ||
+                           fmt.format.height != vin->format.height)
+                               return -EPIPE;
+               }
        }
 
        if (fmt.format.code != vin->mbus_code)
index 835518534e3b94dc6f352cf3a8fe0330db4d79c5..61cfaaf4e927b35a81e55ccae6e2d4b8b2f13dd5 100644 (file)
@@ -397,10 +397,12 @@ hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth)
        if (!raw_vpu_fmt)
                return -EINVAL;
 
-       if (ctx->is_encoder)
+       if (ctx->is_encoder) {
                encoded_fmt = &ctx->dst_fmt;
-       else
+               ctx->vpu_src_fmt = raw_vpu_fmt;
+       } else {
                encoded_fmt = &ctx->src_fmt;
+       }
 
        hantro_reset_fmt(&raw_fmt, raw_vpu_fmt);
        raw_fmt.width = encoded_fmt->width;
index 44540de1a206686fcc366a2a8701bf15fe5b221b..d3b5cb4a24daf9c47a4903a3618aee977abeafd3 100644 (file)
@@ -101,6 +101,10 @@ static int ce6230_i2c_master_xfer(struct i2c_adapter *adap,
                if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
                        if (msg[i].addr ==
                                ce6230_zl10353_config.demod_address) {
+                               if (msg[i].len < 1) {
+                                       i = -EOPNOTSUPP;
+                                       break;
+                               }
                                req.cmd = DEMOD_READ;
                                req.value = msg[i].addr >> 1;
                                req.index = msg[i].buf[0];
@@ -117,6 +121,10 @@ static int ce6230_i2c_master_xfer(struct i2c_adapter *adap,
                } else {
                        if (msg[i].addr ==
                                ce6230_zl10353_config.demod_address) {
+                               if (msg[i].len < 1) {
+                                       i = -EOPNOTSUPP;
+                                       break;
+                               }
                                req.cmd = DEMOD_WRITE;
                                req.value = msg[i].addr >> 1;
                                req.index = msg[i].buf[0];
index 7ed0ab9e429b1457abc5e91b9f4795e96cdda631..0e4773fc025c9e74f8c86a451e9df60b513ccc8f 100644 (file)
@@ -115,6 +115,10 @@ static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
        while (i < num) {
                if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
                        if (msg[i].addr == ec168_ec100_config.demod_address) {
+                               if (msg[i].len < 1) {
+                                       i = -EOPNOTSUPP;
+                                       break;
+                               }
                                req.cmd = READ_DEMOD;
                                req.value = 0;
                                req.index = 0xff00 + msg[i].buf[0]; /* reg */
@@ -131,6 +135,10 @@ static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
                        }
                } else {
                        if (msg[i].addr == ec168_ec100_config.demod_address) {
+                               if (msg[i].len < 1) {
+                                       i = -EOPNOTSUPP;
+                                       break;
+                               }
                                req.cmd = WRITE_DEMOD;
                                req.value = msg[i].buf[1]; /* val */
                                req.index = 0xff00 + msg[i].buf[0]; /* reg */
@@ -139,6 +147,10 @@ static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
                                ret = ec168_ctrl_msg(d, &req);
                                i += 1;
                        } else {
+                               if (msg[i].len < 1) {
+                                       i = -EOPNOTSUPP;
+                                       break;
+                               }
                                req.cmd = WRITE_I2C;
                                req.value = msg[i].buf[0]; /* val */
                                req.index = 0x0100 + msg[i].addr; /* I2C addr */
index 795a012d402002de74559c0aab4e0d80dc826e3e..f7884bb56fccff29205c95f20b00fd098cec3ee3 100644 (file)
@@ -176,6 +176,10 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
                        ret = -EOPNOTSUPP;
                        goto err_mutex_unlock;
                } else if (msg[0].addr == 0x10) {
+                       if (msg[0].len < 1 || msg[1].len < 1) {
+                               ret = -EOPNOTSUPP;
+                               goto err_mutex_unlock;
+                       }
                        /* method 1 - integrated demod */
                        if (msg[0].buf[0] == 0x00) {
                                /* return demod page from driver cache */
@@ -189,6 +193,10 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
                                ret = rtl28xxu_ctrl_msg(d, &req);
                        }
                } else if (msg[0].len < 2) {
+                       if (msg[0].len < 1) {
+                               ret = -EOPNOTSUPP;
+                               goto err_mutex_unlock;
+                       }
                        /* method 2 - old I2C */
                        req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
                        req.index = CMD_I2C_RD;
@@ -217,8 +225,16 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
                        ret = -EOPNOTSUPP;
                        goto err_mutex_unlock;
                } else if (msg[0].addr == 0x10) {
+                       if (msg[0].len < 1) {
+                               ret = -EOPNOTSUPP;
+                               goto err_mutex_unlock;
+                       }
                        /* method 1 - integrated demod */
                        if (msg[0].buf[0] == 0x00) {
+                               if (msg[0].len < 2) {
+                                       ret = -EOPNOTSUPP;
+                                       goto err_mutex_unlock;
+                               }
                                /* save demod page for later demod access */
                                dev->page = msg[0].buf[1];
                                ret = 0;
@@ -231,6 +247,10 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
                                ret = rtl28xxu_ctrl_msg(d, &req);
                        }
                } else if ((msg[0].len < 23) && (!dev->new_i2c_write)) {
+                       if (msg[0].len < 1) {
+                               ret = -EOPNOTSUPP;
+                               goto err_mutex_unlock;
+                       }
                        /* method 2 - old I2C */
                        req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
                        req.index = CMD_I2C_WR;
index 7d78ee09be5e1dc40d813777d5e26e2abeb8aba3..a31c6f82f4e90fbcd08bc600ada4948180a9970f 100644 (file)
@@ -988,6 +988,10 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
                        /* write/read request */
                        if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) {
                                req = 0xB9;
+                               if (msg[i].len < 1) {
+                                       i = -EOPNOTSUPP;
+                                       break;
+                               }
                                index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
                                value = msg[i].addr + (msg[i].len << 8);
                                length = msg[i + 1].len + 6;
@@ -1001,6 +1005,10 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
 
                                /* demod 16bit addr */
                                req = 0xBD;
+                               if (msg[i].len < 1) {
+                                       i = -EOPNOTSUPP;
+                                       break;
+                               }
                                index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
                                value = msg[i].addr + (2 << 8);
                                length = msg[i].len - 2;
@@ -1026,6 +1034,10 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
                        } else {
 
                                req = 0xBD;
+                               if (msg[i].len < 1) {
+                                       i = -EOPNOTSUPP;
+                                       break;
+                               }
                                index = msg[i].buf[0] & 0x00FF;
                                value = msg[i].addr + (1 << 8);
                                length = msg[i].len - 1;
index 2756815a780bca7e2c2fc07f549d0c3ca99651a4..32134be1691489fa3bed90cc97f68f8eea8179a0 100644 (file)
@@ -63,6 +63,10 @@ static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
                warn("more than 2 i2c messages at a time is not handled yet. TODO.");
 
        for (i = 0; i < num; i++) {
+               if (msg[i].len < 1) {
+                       i = -EOPNOTSUPP;
+                       break;
+               }
                /* write/read request */
                if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
                        if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0,
index 0ca764282c767eb1b12aa7cb515453068fb2d4a7..8747960e614611a71f2d5ec78ecac77f633207f9 100644 (file)
@@ -946,7 +946,7 @@ static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
        for (i = 0; i < 6; i++) {
                obuf[1] = 0xf0 + i;
                if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
-                       break;
+                       return -1;
                else
                        mac[i] = ibuf[0];
        }
index 9501b10b31aa57d1683f7ace1a0c05ebc7c604e8..0df10270dbdfcf47a1e428d095182e42cfc686ee 100644 (file)
@@ -37,6 +37,7 @@ config VIDEO_PVRUSB2_DVB
        bool "pvrusb2 ATSC/DVB support"
        default y
        depends on VIDEO_PVRUSB2 && DVB_CORE
+       depends on VIDEO_PVRUSB2=m || DVB_CORE=y
        select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
        select DVB_S5H1409 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
index 38822cedd93a97c23486de57fa8931f9723f92fa..c4474d4c44e28adc84a26265ac45dd619bef3df2 100644 (file)
@@ -1544,8 +1544,7 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
        dvb_dmx_release(&dec->demux);
        if (dec->fe) {
                dvb_unregister_frontend(dec->fe);
-               if (dec->fe->ops.release)
-                       dec->fe->ops.release(dec->fe);
+               dvb_frontend_detach(dec->fe);
        }
        dvb_unregister_adapter(&dec->adapter);
 }
index 7aefa76a42b316f30cb6643d833a92b94547e9bc..d631ce4f9f7bb298d2b4c309d0bf242cdbd61a93 100644 (file)
@@ -251,14 +251,17 @@ static int uvc_parse_format(struct uvc_device *dev,
                /* Find the format descriptor from its GUID. */
                fmtdesc = uvc_format_by_guid(&buffer[5]);
 
-               if (fmtdesc != NULL) {
-                       format->fcc = fmtdesc->fcc;
-               } else {
+               if (!fmtdesc) {
+                       /*
+                        * Unknown video formats are not fatal errors, the
+                        * caller will skip this descriptor.
+                        */
                        dev_info(&streaming->intf->dev,
                                 "Unknown video format %pUl\n", &buffer[5]);
-                       format->fcc = 0;
+                       return 0;
                }
 
+               format->fcc = fmtdesc->fcc;
                format->bpp = buffer[21];
 
                /*
@@ -675,7 +678,7 @@ static int uvc_parse_streaming(struct uvc_device *dev,
        interval = (u32 *)&frame[nframes];
 
        streaming->format = format;
-       streaming->nformats = nformats;
+       streaming->nformats = 0;
 
        /* Parse the format descriptors. */
        while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE) {
@@ -689,7 +692,10 @@ static int uvc_parse_streaming(struct uvc_device *dev,
                                &interval, buffer, buflen);
                        if (ret < 0)
                                goto error;
+                       if (!ret)
+                               break;
 
+                       streaming->nformats++;
                        frame += format->nframes;
                        format++;
 
index bf0c18100664f56366a188ee22a1f354184d3b39..22fe08fce0a9abe8a3fb359a014b2471acab2ac3 100644 (file)
@@ -314,8 +314,7 @@ int v4l2_create_fwnode_links_to_pad(struct v4l2_subdev *src_sd,
 {
        struct fwnode_handle *endpoint;
 
-       if (!(sink->flags & MEDIA_PAD_FL_SINK) ||
-           !is_media_entity_v4l2_subdev(sink->entity))
+       if (!(sink->flags & MEDIA_PAD_FL_SINK))
                return -EINVAL;
 
        fwnode_graph_for_each_endpoint(dev_fwnode(src_sd->dev), endpoint) {
index e90463c4441ce325e17d8cf11f2b34d88c59149d..de67fe83efd37b7c5a4c74fecf826d93d3c77f3e 100644 (file)
@@ -1679,6 +1679,38 @@ config MFD_TPS65912_SPI
          If you say yes here you get support for the TPS65912 series of
          PM chips with SPI interface.
 
+config MFD_TPS6594
+       tristate
+       select MFD_CORE
+       select REGMAP
+       select REGMAP_IRQ
+
+config MFD_TPS6594_I2C
+       tristate "TI TPS6594 Power Management chip with I2C"
+       select MFD_TPS6594
+       select REGMAP_I2C
+       select CRC8
+       depends on I2C
+       help
+         If you say yes here you get support for the TPS6594 series of
+         PM chips with I2C interface.
+
+         This driver can also be built as a module.  If so, the module
+         will be called tps6594-i2c.
+
+config MFD_TPS6594_SPI
+       tristate "TI TPS6594 Power Management chip with SPI"
+       select MFD_TPS6594
+       select REGMAP_SPI
+       select CRC8
+       depends on SPI_MASTER
+       help
+         If you say yes here you get support for the TPS6594 series of
+         PM chips with SPI interface.
+
+         This driver can also be built as a module.  If so, the module
+         will be called tps6594-spi.
+
 config TWL4030_CORE
        bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 Support"
        depends on I2C=y
index 1d2392f06f78a84ad5ed919ee9b0c063a58935ca..40b0bf8eace6afec74d4f21aafcd3ff8e0d85ab1 100644 (file)
@@ -96,6 +96,9 @@ obj-$(CONFIG_MFD_TPS65910)    += tps65910.o
 obj-$(CONFIG_MFD_TPS65912)     += tps65912-core.o
 obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o
 obj-$(CONFIG_MFD_TPS65912_SPI)  += tps65912-spi.o
+obj-$(CONFIG_MFD_TPS6594)      += tps6594-core.o
+obj-$(CONFIG_MFD_TPS6594_I2C)  += tps6594-i2c.o
+obj-$(CONFIG_MFD_TPS6594_SPI)  += tps6594-spi.o
 obj-$(CONFIG_MENELAUS)         += menelaus.o
 
 obj-$(CONFIG_TWL4030_CORE)     += twl-core.o twl4030-irq.o twl6030-irq.o
diff --git a/drivers/mfd/tps6594-core.c b/drivers/mfd/tps6594-core.c
new file mode 100644 (file)
index 0000000..15f3148
--- /dev/null
@@ -0,0 +1,462 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Core functions for TI TPS6594/TPS6593/LP8764 PMICs
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps6594.h>
+
+#define TPS6594_CRC_SYNC_TIMEOUT_MS 150
+
+/* Completion to synchronize CRC feature enabling on all PMICs */
+static DECLARE_COMPLETION(tps6594_crc_comp);
+
+static const struct resource tps6594_regulator_resources[] = {
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_OV, TPS6594_IRQ_NAME_BUCK1_OV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_UV, TPS6594_IRQ_NAME_BUCK1_UV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_SC, TPS6594_IRQ_NAME_BUCK1_SC),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_ILIM, TPS6594_IRQ_NAME_BUCK1_ILIM),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_OV, TPS6594_IRQ_NAME_BUCK2_OV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_UV, TPS6594_IRQ_NAME_BUCK2_UV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_SC, TPS6594_IRQ_NAME_BUCK2_SC),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_ILIM, TPS6594_IRQ_NAME_BUCK2_ILIM),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_OV, TPS6594_IRQ_NAME_BUCK3_OV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_UV, TPS6594_IRQ_NAME_BUCK3_UV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_SC, TPS6594_IRQ_NAME_BUCK3_SC),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_ILIM, TPS6594_IRQ_NAME_BUCK3_ILIM),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_OV, TPS6594_IRQ_NAME_BUCK4_OV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_UV, TPS6594_IRQ_NAME_BUCK4_UV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_SC, TPS6594_IRQ_NAME_BUCK4_SC),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_ILIM, TPS6594_IRQ_NAME_BUCK4_ILIM),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_OV, TPS6594_IRQ_NAME_BUCK5_OV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_UV, TPS6594_IRQ_NAME_BUCK5_UV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_SC, TPS6594_IRQ_NAME_BUCK5_SC),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_ILIM, TPS6594_IRQ_NAME_BUCK5_ILIM),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_OV, TPS6594_IRQ_NAME_LDO1_OV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_UV, TPS6594_IRQ_NAME_LDO1_UV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_SC, TPS6594_IRQ_NAME_LDO1_SC),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_ILIM, TPS6594_IRQ_NAME_LDO1_ILIM),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_OV, TPS6594_IRQ_NAME_LDO2_OV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_UV, TPS6594_IRQ_NAME_LDO2_UV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_SC, TPS6594_IRQ_NAME_LDO2_SC),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_ILIM, TPS6594_IRQ_NAME_LDO2_ILIM),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_OV, TPS6594_IRQ_NAME_LDO3_OV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_UV, TPS6594_IRQ_NAME_LDO3_UV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_SC, TPS6594_IRQ_NAME_LDO3_SC),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_ILIM, TPS6594_IRQ_NAME_LDO3_ILIM),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_OV, TPS6594_IRQ_NAME_LDO4_OV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_UV, TPS6594_IRQ_NAME_LDO4_UV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_SC, TPS6594_IRQ_NAME_LDO4_SC),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_ILIM, TPS6594_IRQ_NAME_LDO4_ILIM),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VCCA_OV, TPS6594_IRQ_NAME_VCCA_OV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VCCA_UV, TPS6594_IRQ_NAME_VCCA_UV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON1_OV, TPS6594_IRQ_NAME_VMON1_OV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON1_UV, TPS6594_IRQ_NAME_VMON1_UV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON1_RV, TPS6594_IRQ_NAME_VMON1_RV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON2_OV, TPS6594_IRQ_NAME_VMON2_OV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON2_UV, TPS6594_IRQ_NAME_VMON2_UV),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON2_RV, TPS6594_IRQ_NAME_VMON2_RV),
+};
+
+static const struct resource tps6594_pinctrl_resources[] = {
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO9, TPS6594_IRQ_NAME_GPIO9),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO10, TPS6594_IRQ_NAME_GPIO10),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO11, TPS6594_IRQ_NAME_GPIO11),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO1, TPS6594_IRQ_NAME_GPIO1),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO2, TPS6594_IRQ_NAME_GPIO2),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO3, TPS6594_IRQ_NAME_GPIO3),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO4, TPS6594_IRQ_NAME_GPIO4),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO5, TPS6594_IRQ_NAME_GPIO5),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO6, TPS6594_IRQ_NAME_GPIO6),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO7, TPS6594_IRQ_NAME_GPIO7),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO8, TPS6594_IRQ_NAME_GPIO8),
+};
+
+static const struct resource tps6594_pfsm_resources[] = {
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NPWRON_START, TPS6594_IRQ_NAME_NPWRON_START),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ENABLE, TPS6594_IRQ_NAME_ENABLE),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_FSD, TPS6594_IRQ_NAME_FSD),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_SOFT_REBOOT, TPS6594_IRQ_NAME_SOFT_REBOOT),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BIST_PASS, TPS6594_IRQ_NAME_BIST_PASS),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_EXT_CLK, TPS6594_IRQ_NAME_EXT_CLK),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TWARN, TPS6594_IRQ_NAME_TWARN),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TSD_ORD, TPS6594_IRQ_NAME_TSD_ORD),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BIST_FAIL, TPS6594_IRQ_NAME_BIST_FAIL),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_REG_CRC_ERR, TPS6594_IRQ_NAME_REG_CRC_ERR),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_RECOV_CNT, TPS6594_IRQ_NAME_RECOV_CNT),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_SPMI_ERR, TPS6594_IRQ_NAME_SPMI_ERR),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NPWRON_LONG, TPS6594_IRQ_NAME_NPWRON_LONG),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NINT_READBACK, TPS6594_IRQ_NAME_NINT_READBACK),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NRSTOUT_READBACK, TPS6594_IRQ_NAME_NRSTOUT_READBACK),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TSD_IMM, TPS6594_IRQ_NAME_TSD_IMM),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VCCA_OVP, TPS6594_IRQ_NAME_VCCA_OVP),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_PFSM_ERR, TPS6594_IRQ_NAME_PFSM_ERR),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_IMM_SHUTDOWN, TPS6594_IRQ_NAME_IMM_SHUTDOWN),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ORD_SHUTDOWN, TPS6594_IRQ_NAME_ORD_SHUTDOWN),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_MCU_PWR_ERR, TPS6594_IRQ_NAME_MCU_PWR_ERR),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_SOC_PWR_ERR, TPS6594_IRQ_NAME_SOC_PWR_ERR),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_COMM_FRM_ERR, TPS6594_IRQ_NAME_COMM_FRM_ERR),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_COMM_CRC_ERR, TPS6594_IRQ_NAME_COMM_CRC_ERR),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_COMM_ADR_ERR, TPS6594_IRQ_NAME_COMM_ADR_ERR),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_EN_DRV_READBACK, TPS6594_IRQ_NAME_EN_DRV_READBACK),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NRSTOUT_SOC_READBACK,
+                            TPS6594_IRQ_NAME_NRSTOUT_SOC_READBACK),
+};
+
+static const struct resource tps6594_esm_resources[] = {
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ESM_SOC_PIN, TPS6594_IRQ_NAME_ESM_SOC_PIN),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ESM_SOC_FAIL, TPS6594_IRQ_NAME_ESM_SOC_FAIL),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ESM_SOC_RST, TPS6594_IRQ_NAME_ESM_SOC_RST),
+};
+
+static const struct resource tps6594_rtc_resources[] = {
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TIMER, TPS6594_IRQ_NAME_TIMER),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ALARM, TPS6594_IRQ_NAME_ALARM),
+       DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_POWER_UP, TPS6594_IRQ_NAME_POWERUP),
+};
+
+static const struct mfd_cell tps6594_common_cells[] = {
+       MFD_CELL_RES("tps6594-regulator", tps6594_regulator_resources),
+       MFD_CELL_RES("tps6594-pinctrl", tps6594_pinctrl_resources),
+       MFD_CELL_RES("tps6594-pfsm", tps6594_pfsm_resources),
+       MFD_CELL_RES("tps6594-esm", tps6594_esm_resources),
+};
+
+static const struct mfd_cell tps6594_rtc_cells[] = {
+       MFD_CELL_RES("tps6594-rtc", tps6594_rtc_resources),
+};
+
+static const struct regmap_irq tps6594_irqs[] = {
+       /* INT_BUCK1_2 register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_OV, 0, TPS6594_BIT_BUCKX_OV_INT(0)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_UV, 0, TPS6594_BIT_BUCKX_UV_INT(0)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_SC, 0, TPS6594_BIT_BUCKX_SC_INT(0)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_ILIM, 0, TPS6594_BIT_BUCKX_ILIM_INT(0)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_OV, 0, TPS6594_BIT_BUCKX_OV_INT(1)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_UV, 0, TPS6594_BIT_BUCKX_UV_INT(1)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_SC, 0, TPS6594_BIT_BUCKX_SC_INT(1)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_ILIM, 0, TPS6594_BIT_BUCKX_ILIM_INT(1)),
+
+       /* INT_BUCK3_4 register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_OV, 1, TPS6594_BIT_BUCKX_OV_INT(2)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_UV, 1, TPS6594_BIT_BUCKX_UV_INT(2)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_SC, 1, TPS6594_BIT_BUCKX_SC_INT(2)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_ILIM, 1, TPS6594_BIT_BUCKX_ILIM_INT(2)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_OV, 1, TPS6594_BIT_BUCKX_OV_INT(3)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_UV, 1, TPS6594_BIT_BUCKX_UV_INT(3)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_SC, 1, TPS6594_BIT_BUCKX_SC_INT(3)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_ILIM, 1, TPS6594_BIT_BUCKX_ILIM_INT(3)),
+
+       /* INT_BUCK5 register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_OV, 2, TPS6594_BIT_BUCKX_OV_INT(4)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_UV, 2, TPS6594_BIT_BUCKX_UV_INT(4)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_SC, 2, TPS6594_BIT_BUCKX_SC_INT(4)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_ILIM, 2, TPS6594_BIT_BUCKX_ILIM_INT(4)),
+
+       /* INT_LDO1_2 register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_OV, 3, TPS6594_BIT_LDOX_OV_INT(0)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_UV, 3, TPS6594_BIT_LDOX_UV_INT(0)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_SC, 3, TPS6594_BIT_LDOX_SC_INT(0)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_ILIM, 3, TPS6594_BIT_LDOX_ILIM_INT(0)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_OV, 3, TPS6594_BIT_LDOX_OV_INT(1)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_UV, 3, TPS6594_BIT_LDOX_UV_INT(1)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_SC, 3, TPS6594_BIT_LDOX_SC_INT(1)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_ILIM, 3, TPS6594_BIT_LDOX_ILIM_INT(1)),
+
+       /* INT_LDO3_4 register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_OV, 4, TPS6594_BIT_LDOX_OV_INT(2)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_UV, 4, TPS6594_BIT_LDOX_UV_INT(2)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_SC, 4, TPS6594_BIT_LDOX_SC_INT(2)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_ILIM, 4, TPS6594_BIT_LDOX_ILIM_INT(2)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_OV, 4, TPS6594_BIT_LDOX_OV_INT(3)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_UV, 4, TPS6594_BIT_LDOX_UV_INT(3)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_SC, 4, TPS6594_BIT_LDOX_SC_INT(3)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_ILIM, 4, TPS6594_BIT_LDOX_ILIM_INT(3)),
+
+       /* INT_VMON register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_VCCA_OV, 5, TPS6594_BIT_VCCA_OV_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_VCCA_UV, 5, TPS6594_BIT_VCCA_UV_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_VMON1_OV, 5, TPS6594_BIT_VMON1_OV_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_VMON1_UV, 5, TPS6594_BIT_VMON1_UV_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_VMON1_RV, 5, TPS6594_BIT_VMON1_RV_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_VMON2_OV, 5, TPS6594_BIT_VMON2_OV_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_VMON2_UV, 5, TPS6594_BIT_VMON2_UV_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_VMON2_RV, 5, TPS6594_BIT_VMON2_RV_INT),
+
+       /* INT_GPIO register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_GPIO9, 6, TPS6594_BIT_GPIO9_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_GPIO10, 6, TPS6594_BIT_GPIO10_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_GPIO11, 6, TPS6594_BIT_GPIO11_INT),
+
+       /* INT_GPIO1_8 register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_GPIO1, 7, TPS6594_BIT_GPIOX_INT(0)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_GPIO2, 7, TPS6594_BIT_GPIOX_INT(1)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_GPIO3, 7, TPS6594_BIT_GPIOX_INT(2)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_GPIO4, 7, TPS6594_BIT_GPIOX_INT(3)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_GPIO5, 7, TPS6594_BIT_GPIOX_INT(4)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_GPIO6, 7, TPS6594_BIT_GPIOX_INT(5)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_GPIO7, 7, TPS6594_BIT_GPIOX_INT(6)),
+       REGMAP_IRQ_REG(TPS6594_IRQ_GPIO8, 7, TPS6594_BIT_GPIOX_INT(7)),
+
+       /* INT_STARTUP register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_NPWRON_START, 8, TPS6594_BIT_NPWRON_START_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_ENABLE, 8, TPS6594_BIT_ENABLE_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_FSD, 8, TPS6594_BIT_FSD_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_SOFT_REBOOT, 8, TPS6594_BIT_SOFT_REBOOT_INT),
+
+       /* INT_MISC register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_BIST_PASS, 9, TPS6594_BIT_BIST_PASS_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_EXT_CLK, 9, TPS6594_BIT_EXT_CLK_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_TWARN, 9, TPS6594_BIT_TWARN_INT),
+
+       /* INT_MODERATE_ERR register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_TSD_ORD, 10, TPS6594_BIT_TSD_ORD_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_BIST_FAIL, 10, TPS6594_BIT_BIST_FAIL_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_REG_CRC_ERR, 10, TPS6594_BIT_REG_CRC_ERR_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_RECOV_CNT, 10, TPS6594_BIT_RECOV_CNT_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_SPMI_ERR, 10, TPS6594_BIT_SPMI_ERR_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_NPWRON_LONG, 10, TPS6594_BIT_NPWRON_LONG_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_NINT_READBACK, 10, TPS6594_BIT_NINT_READBACK_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_NRSTOUT_READBACK, 10, TPS6594_BIT_NRSTOUT_READBACK_INT),
+
+       /* INT_SEVERE_ERR register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_TSD_IMM, 11, TPS6594_BIT_TSD_IMM_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_VCCA_OVP, 11, TPS6594_BIT_VCCA_OVP_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_PFSM_ERR, 11, TPS6594_BIT_PFSM_ERR_INT),
+
+       /* INT_FSM_ERR register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_IMM_SHUTDOWN, 12, TPS6594_BIT_IMM_SHUTDOWN_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_ORD_SHUTDOWN, 12, TPS6594_BIT_ORD_SHUTDOWN_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_MCU_PWR_ERR, 12, TPS6594_BIT_MCU_PWR_ERR_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_SOC_PWR_ERR, 12, TPS6594_BIT_SOC_PWR_ERR_INT),
+
+       /* INT_COMM_ERR register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_COMM_FRM_ERR, 13, TPS6594_BIT_COMM_FRM_ERR_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_COMM_CRC_ERR, 13, TPS6594_BIT_COMM_CRC_ERR_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_COMM_ADR_ERR, 13, TPS6594_BIT_COMM_ADR_ERR_INT),
+
+       /* INT_READBACK_ERR register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_EN_DRV_READBACK, 14, TPS6594_BIT_EN_DRV_READBACK_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_NRSTOUT_SOC_READBACK, 14, TPS6594_BIT_NRSTOUT_SOC_READBACK_INT),
+
+       /* INT_ESM register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_ESM_SOC_PIN, 15, TPS6594_BIT_ESM_SOC_PIN_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_ESM_SOC_FAIL, 15, TPS6594_BIT_ESM_SOC_FAIL_INT),
+       REGMAP_IRQ_REG(TPS6594_IRQ_ESM_SOC_RST, 15, TPS6594_BIT_ESM_SOC_RST_INT),
+
+       /* RTC_STATUS register */
+       REGMAP_IRQ_REG(TPS6594_IRQ_TIMER, 16, TPS6594_BIT_TIMER),
+       REGMAP_IRQ_REG(TPS6594_IRQ_ALARM, 16, TPS6594_BIT_ALARM),
+       REGMAP_IRQ_REG(TPS6594_IRQ_POWER_UP, 16, TPS6594_BIT_POWER_UP),
+};
+
+static const unsigned int tps6594_irq_reg[] = {
+       TPS6594_REG_INT_BUCK1_2,
+       TPS6594_REG_INT_BUCK3_4,
+       TPS6594_REG_INT_BUCK5,
+       TPS6594_REG_INT_LDO1_2,
+       TPS6594_REG_INT_LDO3_4,
+       TPS6594_REG_INT_VMON,
+       TPS6594_REG_INT_GPIO,
+       TPS6594_REG_INT_GPIO1_8,
+       TPS6594_REG_INT_STARTUP,
+       TPS6594_REG_INT_MISC,
+       TPS6594_REG_INT_MODERATE_ERR,
+       TPS6594_REG_INT_SEVERE_ERR,
+       TPS6594_REG_INT_FSM_ERR,
+       TPS6594_REG_INT_COMM_ERR,
+       TPS6594_REG_INT_READBACK_ERR,
+       TPS6594_REG_INT_ESM,
+       TPS6594_REG_RTC_STATUS,
+};
+
+static inline unsigned int tps6594_get_irq_reg(struct regmap_irq_chip_data *data,
+                                              unsigned int base, int index)
+{
+       return tps6594_irq_reg[index];
+};
+
+static int tps6594_handle_post_irq(void *irq_drv_data)
+{
+       struct tps6594 *tps = irq_drv_data;
+       int ret = 0;
+
+       /*
+        * When CRC is enabled, writing to a read-only bit triggers an error,
+        * and COMM_ADR_ERR_INT bit is set. Besides, bits indicating interrupts
+        * (that must be cleared) and read-only bits are sometimes grouped in
+        * the same register.
+        * Since regmap clears interrupts by doing a write per register, clearing
+        * an interrupt bit in a register containing also a read-only bit makes
+        * COMM_ADR_ERR_INT bit set. Clear immediately this bit to avoid raising
+        * a new interrupt.
+        */
+       if (tps->use_crc)
+               ret = regmap_write_bits(tps->regmap, TPS6594_REG_INT_COMM_ERR,
+                                       TPS6594_BIT_COMM_ADR_ERR_INT,
+                                       TPS6594_BIT_COMM_ADR_ERR_INT);
+
+       return ret;
+};
+
+static struct regmap_irq_chip tps6594_irq_chip = {
+       .ack_base = TPS6594_REG_INT_BUCK1_2,
+       .ack_invert = 1,
+       .clear_ack = 1,
+       .init_ack_masked = 1,
+       .num_regs = ARRAY_SIZE(tps6594_irq_reg),
+       .irqs = tps6594_irqs,
+       .num_irqs = ARRAY_SIZE(tps6594_irqs),
+       .get_irq_reg = tps6594_get_irq_reg,
+       .handle_post_irq = tps6594_handle_post_irq,
+};
+
+bool tps6594_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+       return (reg >= TPS6594_REG_INT_TOP && reg <= TPS6594_REG_STAT_READBACK_ERR) ||
+              reg == TPS6594_REG_RTC_STATUS;
+}
+EXPORT_SYMBOL_GPL(tps6594_is_volatile_reg);
+
+static int tps6594_check_crc_mode(struct tps6594 *tps, bool primary_pmic)
+{
+       int ret;
+
+       /*
+        * Check if CRC is enabled.
+        * Once CRC is enabled, it can't be disabled until next power cycle.
+        */
+       tps->use_crc = true;
+       ret = regmap_test_bits(tps->regmap, TPS6594_REG_SERIAL_IF_CONFIG,
+                              TPS6594_BIT_I2C1_SPI_CRC_EN);
+       if (ret == 0) {
+               ret = -EIO;
+       } else if (ret > 0) {
+               dev_info(tps->dev, "CRC feature enabled on %s PMIC",
+                        primary_pmic ? "primary" : "secondary");
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static int tps6594_set_crc_feature(struct tps6594 *tps)
+{
+       int ret;
+
+       ret = tps6594_check_crc_mode(tps, true);
+       if (ret) {
+               /*
+                * If CRC is not already enabled, force PFSM I2C_2 trigger to enable it
+                * on primary PMIC.
+                */
+               tps->use_crc = false;
+               ret = regmap_write_bits(tps->regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+                                       TPS6594_BIT_TRIGGER_I2C(2), TPS6594_BIT_TRIGGER_I2C(2));
+               if (ret)
+                       return ret;
+
+               /*
+                * Wait for PFSM to process trigger.
+                * The datasheet indicates 2 ms, and clock specification is +/-5%.
+                * 4 ms should provide sufficient margin.
+                */
+               usleep_range(4000, 5000);
+
+               ret = tps6594_check_crc_mode(tps, true);
+       }
+
+       return ret;
+}
+
+static int tps6594_enable_crc(struct tps6594 *tps)
+{
+       struct device *dev = tps->dev;
+       unsigned int is_primary;
+       unsigned long timeout = msecs_to_jiffies(TPS6594_CRC_SYNC_TIMEOUT_MS);
+       int ret;
+
+       /*
+        * CRC mode can be used with I2C or SPI protocols.
+        * If this mode is specified for primary PMIC, it will also be applied to secondary PMICs
+        * through SPMI serial interface.
+        * In this multi-PMIC synchronization scheme, the primary PMIC is the controller device
+        * on the SPMI bus, and the secondary PMICs are the target devices on the SPMI bus.
+        */
+       is_primary = of_property_read_bool(dev->of_node, "ti,primary-pmic");
+       if (is_primary) {
+               /* Enable CRC feature on primary PMIC */
+               ret = tps6594_set_crc_feature(tps);
+               if (ret)
+                       return ret;
+
+               /* Notify secondary PMICs that CRC feature is enabled */
+               complete_all(&tps6594_crc_comp);
+       } else {
+               /* Wait for CRC feature enabling event from primary PMIC */
+               ret = wait_for_completion_interruptible_timeout(&tps6594_crc_comp, timeout);
+               if (ret == 0)
+                       ret = -ETIMEDOUT;
+               else if (ret > 0)
+                       ret = tps6594_check_crc_mode(tps, false);
+       }
+
+       return ret;
+}
+
+int tps6594_device_init(struct tps6594 *tps, bool enable_crc)
+{
+       struct device *dev = tps->dev;
+       int ret;
+
+       if (enable_crc) {
+               ret = tps6594_enable_crc(tps);
+               if (ret)
+                       return dev_err_probe(dev, ret, "Failed to enable CRC\n");
+       }
+
+       /* Keep PMIC in ACTIVE state */
+       ret = regmap_set_bits(tps->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
+                             TPS6594_BIT_NSLEEP1B | TPS6594_BIT_NSLEEP2B);
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to set PMIC state\n");
+
+       tps6594_irq_chip.irq_drv_data = tps;
+       tps6594_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL, "%s-%ld-0x%02x",
+                                              dev->driver->name, tps->chip_id, tps->reg);
+
+       ret = devm_regmap_add_irq_chip(dev, tps->regmap, tps->irq, IRQF_SHARED | IRQF_ONESHOT,
+                                      0, &tps6594_irq_chip, &tps->irq_data);
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to add regmap IRQ\n");
+
+       ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, tps6594_common_cells,
+                                  ARRAY_SIZE(tps6594_common_cells), NULL, 0,
+                                  regmap_irq_get_domain(tps->irq_data));
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to add common child devices\n");
+
+       /* No RTC for LP8764 */
+       if (tps->chip_id != LP8764) {
+               ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, tps6594_rtc_cells,
+                                          ARRAY_SIZE(tps6594_rtc_cells), NULL, 0,
+                                          regmap_irq_get_domain(tps->irq_data));
+               if (ret)
+                       return dev_err_probe(dev, ret, "Failed to add RTC child device\n");
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tps6594_device_init);
+
+MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/tps6594-i2c.c b/drivers/mfd/tps6594-i2c.c
new file mode 100644 (file)
index 0000000..449d5c6
--- /dev/null
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * I2C access driver for TI TPS6594/TPS6593/LP8764 PMICs
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/crc8.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/tps6594.h>
+
+static bool enable_crc;
+module_param(enable_crc, bool, 0444);
+MODULE_PARM_DESC(enable_crc, "Enable CRC feature for I2C interface");
+
+DECLARE_CRC8_TABLE(tps6594_i2c_crc_table);
+
+static int tps6594_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+       int ret = i2c_transfer(adap, msgs, num);
+
+       if (ret == num)
+               return 0;
+       else if (ret < 0)
+               return ret;
+       else
+               return -EIO;
+}
+
+static int tps6594_i2c_reg_read_with_crc(struct i2c_client *client, u8 page, u8 reg, u8 *val)
+{
+       struct i2c_msg msgs[2];
+       u8 buf_rx[] = { 0, 0 };
+       /* I2C address = I2C base address + Page index */
+       const u8 addr = client->addr + page;
+       /*
+        * CRC is calculated from every bit included in the protocol
+        * except the ACK bits from the target. Byte stream is:
+        * - B0: (I2C_addr_7bits << 1) | WR_bit, with WR_bit = 0
+        * - B1: reg
+        * - B2: (I2C_addr_7bits << 1) | RD_bit, with RD_bit = 1
+        * - B3: val
+        * - B4: CRC from B0-B1-B2-B3
+        */
+       u8 crc_data[] = { addr << 1, reg, addr << 1 | 1, 0 };
+       int ret;
+
+       /* Write register */
+       msgs[0].addr = addr;
+       msgs[0].flags = 0;
+       msgs[0].len = 1;
+       msgs[0].buf = &reg;
+
+       /* Read data and CRC */
+       msgs[1].addr = msgs[0].addr;
+       msgs[1].flags = I2C_M_RD;
+       msgs[1].len = 2;
+       msgs[1].buf = buf_rx;
+
+       ret = tps6594_i2c_transfer(client->adapter, msgs, 2);
+       if (ret < 0)
+               return ret;
+
+       crc_data[sizeof(crc_data) - 1] = *val = buf_rx[0];
+       if (buf_rx[1] != crc8(tps6594_i2c_crc_table, crc_data, sizeof(crc_data), CRC8_INIT_VALUE))
+               return -EIO;
+
+       return ret;
+}
+
+static int tps6594_i2c_reg_write_with_crc(struct i2c_client *client, u8 page, u8 reg, u8 val)
+{
+       struct i2c_msg msg;
+       u8 buf[] = { reg, val, 0 };
+       /* I2C address = I2C base address + Page index */
+       const u8 addr = client->addr + page;
+       /*
+        * CRC is calculated from every bit included in the protocol
+        * except the ACK bits from the target. Byte stream is:
+        * - B0: (I2C_addr_7bits << 1) | WR_bit, with WR_bit = 0
+        * - B1: reg
+        * - B2: val
+        * - B3: CRC from B0-B1-B2
+        */
+       const u8 crc_data[] = { addr << 1, reg, val };
+
+       /* Write register, data and CRC */
+       msg.addr = addr;
+       msg.flags = client->flags & I2C_M_TEN;
+       msg.len = sizeof(buf);
+       msg.buf = buf;
+
+       buf[msg.len - 1] = crc8(tps6594_i2c_crc_table, crc_data, sizeof(crc_data), CRC8_INIT_VALUE);
+
+       return tps6594_i2c_transfer(client->adapter, &msg, 1);
+}
+
+static int tps6594_i2c_read(void *context, const void *reg_buf, size_t reg_size,
+                           void *val_buf, size_t val_size)
+{
+       struct i2c_client *client = context;
+       struct tps6594 *tps = i2c_get_clientdata(client);
+       struct i2c_msg msgs[2];
+       const u8 *reg_bytes = reg_buf;
+       u8 *val_bytes = val_buf;
+       const u8 page = reg_bytes[1];
+       u8 reg = reg_bytes[0];
+       int ret = 0;
+       int i;
+
+       if (tps->use_crc) {
+               /*
+                * Auto-increment feature does not support CRC protocol.
+                * Converts the bulk read operation into a series of single read operations.
+                */
+               for (i = 0 ; ret == 0 && i < val_size ; i++)
+                       ret = tps6594_i2c_reg_read_with_crc(client, page, reg + i, val_bytes + i);
+
+               return ret;
+       }
+
+       /* Write register: I2C address = I2C base address + Page index */
+       msgs[0].addr = client->addr + page;
+       msgs[0].flags = 0;
+       msgs[0].len = 1;
+       msgs[0].buf = &reg;
+
+       /* Read data */
+       msgs[1].addr = msgs[0].addr;
+       msgs[1].flags = I2C_M_RD;
+       msgs[1].len = val_size;
+       msgs[1].buf = val_bytes;
+
+       return tps6594_i2c_transfer(client->adapter, msgs, 2);
+}
+
+static int tps6594_i2c_write(void *context, const void *data, size_t count)
+{
+       struct i2c_client *client = context;
+       struct tps6594 *tps = i2c_get_clientdata(client);
+       struct i2c_msg msg;
+       const u8 *bytes = data;
+       u8 *buf;
+       const u8 page = bytes[1];
+       const u8 reg = bytes[0];
+       int ret = 0;
+       int i;
+
+       if (tps->use_crc) {
+               /*
+                * Auto-increment feature does not support CRC protocol.
+                * Converts the bulk write operation into a series of single write operations.
+                */
+               for (i = 0 ; ret == 0 && i < count - 2 ; i++)
+                       ret = tps6594_i2c_reg_write_with_crc(client, page, reg + i, bytes[i + 2]);
+
+               return ret;
+       }
+
+       /* Setup buffer: page byte is not sent */
+       buf = kzalloc(--count, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       buf[0] = reg;
+       for (i = 0 ; i < count - 1 ; i++)
+               buf[i + 1] = bytes[i + 2];
+
+       /* Write register and data: I2C address = I2C base address + Page index */
+       msg.addr = client->addr + page;
+       msg.flags = client->flags & I2C_M_TEN;
+       msg.len = count;
+       msg.buf = buf;
+
+       ret = tps6594_i2c_transfer(client->adapter, &msg, 1);
+
+       kfree(buf);
+       return ret;
+}
+
+static const struct regmap_config tps6594_i2c_regmap_config = {
+       .reg_bits = 16,
+       .val_bits = 8,
+       .max_register = TPS6594_REG_DWD_FAIL_CNT_REG,
+       .volatile_reg = tps6594_is_volatile_reg,
+       .read = tps6594_i2c_read,
+       .write = tps6594_i2c_write,
+};
+
+static const struct of_device_id tps6594_i2c_of_match_table[] = {
+       { .compatible = "ti,tps6594-q1", .data = (void *)TPS6594, },
+       { .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, },
+       { .compatible = "ti,lp8764-q1",  .data = (void *)LP8764,  },
+       {}
+};
+MODULE_DEVICE_TABLE(of, tps6594_i2c_of_match_table);
+
+static int tps6594_i2c_probe(struct i2c_client *client)
+{
+       struct device *dev = &client->dev;
+       struct tps6594 *tps;
+       const struct of_device_id *match;
+
+       tps = devm_kzalloc(dev, sizeof(*tps), GFP_KERNEL);
+       if (!tps)
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, tps);
+
+       tps->dev = dev;
+       tps->reg = client->addr;
+       tps->irq = client->irq;
+
+       tps->regmap = devm_regmap_init(dev, NULL, client, &tps6594_i2c_regmap_config);
+       if (IS_ERR(tps->regmap))
+               return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
+
+       match = of_match_device(tps6594_i2c_of_match_table, dev);
+       if (!match)
+               return dev_err_probe(dev, PTR_ERR(match), "Failed to find matching chip ID\n");
+       tps->chip_id = (unsigned long)match->data;
+
+       crc8_populate_msb(tps6594_i2c_crc_table, TPS6594_CRC8_POLYNOMIAL);
+
+       return tps6594_device_init(tps, enable_crc);
+}
+
+static struct i2c_driver tps6594_i2c_driver = {
+       .driver = {
+               .name = "tps6594",
+               .of_match_table = tps6594_i2c_of_match_table,
+       },
+       .probe_new = tps6594_i2c_probe,
+};
+module_i2c_driver(tps6594_i2c_driver);
+
+MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 I2C Interface Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/tps6594-spi.c b/drivers/mfd/tps6594-spi.c
new file mode 100644 (file)
index 0000000..a938a19
--- /dev/null
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SPI access driver for TI TPS6594/TPS6593/LP8764 PMICs
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/crc8.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include <linux/mfd/tps6594.h>
+
+#define TPS6594_SPI_PAGE_SHIFT 5
+#define TPS6594_SPI_READ_BIT   BIT(4)
+
+static bool enable_crc;
+module_param(enable_crc, bool, 0444);
+MODULE_PARM_DESC(enable_crc, "Enable CRC feature for SPI interface");
+
+DECLARE_CRC8_TABLE(tps6594_spi_crc_table);
+
+static int tps6594_spi_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+       struct spi_device *spi = context;
+       struct tps6594 *tps = spi_get_drvdata(spi);
+       u8 buf[4] = { 0 };
+       size_t count_rx = 1;
+       int ret;
+
+       buf[0] = reg;
+       buf[1] = TPS6594_REG_TO_PAGE(reg) << TPS6594_SPI_PAGE_SHIFT | TPS6594_SPI_READ_BIT;
+
+       if (tps->use_crc)
+               count_rx++;
+
+       ret = spi_write_then_read(spi, buf, 2, buf + 2, count_rx);
+       if (ret < 0)
+               return ret;
+
+       if (tps->use_crc && buf[3] != crc8(tps6594_spi_crc_table, buf, 3, CRC8_INIT_VALUE))
+               return -EIO;
+
+       *val = buf[2];
+
+       return 0;
+}
+
+static int tps6594_spi_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+       struct spi_device *spi = context;
+       struct tps6594 *tps = spi_get_drvdata(spi);
+       u8 buf[4] = { 0 };
+       size_t count = 3;
+
+       buf[0] = reg;
+       buf[1] = TPS6594_REG_TO_PAGE(reg) << TPS6594_SPI_PAGE_SHIFT;
+       buf[2] = val;
+
+       if (tps->use_crc)
+               buf[3] = crc8(tps6594_spi_crc_table, buf, count++, CRC8_INIT_VALUE);
+
+       return spi_write(spi, buf, count);
+}
+
+static const struct regmap_config tps6594_spi_regmap_config = {
+       .reg_bits = 16,
+       .val_bits = 8,
+       .max_register = TPS6594_REG_DWD_FAIL_CNT_REG,
+       .volatile_reg = tps6594_is_volatile_reg,
+       .reg_read = tps6594_spi_reg_read,
+       .reg_write = tps6594_spi_reg_write,
+       .use_single_read = true,
+       .use_single_write = true,
+};
+
+static const struct of_device_id tps6594_spi_of_match_table[] = {
+       { .compatible = "ti,tps6594-q1", .data = (void *)TPS6594, },
+       { .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, },
+       { .compatible = "ti,lp8764-q1",  .data = (void *)LP8764,  },
+       {}
+};
+MODULE_DEVICE_TABLE(of, tps6594_spi_of_match_table);
+
+static int tps6594_spi_probe(struct spi_device *spi)
+{
+       struct device *dev = &spi->dev;
+       struct tps6594 *tps;
+       const struct of_device_id *match;
+
+       tps = devm_kzalloc(dev, sizeof(*tps), GFP_KERNEL);
+       if (!tps)
+               return -ENOMEM;
+
+       spi_set_drvdata(spi, tps);
+
+       tps->dev = dev;
+       tps->reg = spi->chip_select;
+       tps->irq = spi->irq;
+
+       tps->regmap = devm_regmap_init(dev, NULL, spi, &tps6594_spi_regmap_config);
+       if (IS_ERR(tps->regmap))
+               return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
+
+       match = of_match_device(tps6594_spi_of_match_table, dev);
+       if (!match)
+               return dev_err_probe(dev, PTR_ERR(match), "Failed to find matching chip ID\n");
+       tps->chip_id = (unsigned long)match->data;
+
+       crc8_populate_msb(tps6594_spi_crc_table, TPS6594_CRC8_POLYNOMIAL);
+
+       return tps6594_device_init(tps, enable_crc);
+}
+
+static struct spi_driver tps6594_spi_driver = {
+       .driver = {
+               .name = "tps6594",
+               .of_match_table = tps6594_spi_of_match_table,
+       },
+       .probe = tps6594_spi_probe,
+};
+module_spi_driver(tps6594_spi_driver);
+
+MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 SPI Interface Driver");
+MODULE_LICENSE("GPL");
index 433aa41977852af6ca1aabeb62de68783d8dece7..75e427f124b286e40d89d6e863b950a7634798af 100644 (file)
@@ -538,6 +538,29 @@ config TMR_INJECT
 
          Say N here unless you know what you are doing.
 
+config TPS6594_ESM
+       tristate "TI TPS6594 Error Signal Monitor support"
+       depends on MFD_TPS6594
+       default MFD_TPS6594
+       help
+         Support ESM (Error Signal Monitor) on TPS6594 PMIC devices.
+         ESM is used typically to reboot the board in error condition.
+
+         This driver can also be built as a module.  If so, the module
+         will be called tps6594-esm.
+
+config TPS6594_PFSM
+       tristate "TI TPS6594 Pre-configurable Finite State Machine support"
+       depends on MFD_TPS6594
+       default MFD_TPS6594
+       help
+         Support PFSM (Pre-configurable Finite State Machine) on TPS6594 PMIC devices.
+         These devices integrate a finite state machine engine, which manages the state
+         of the device during operating state transition.
+
+         This driver can also be built as a module.  If so, the module
+         will be called tps6594-pfsm.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
index 56de43943cd512694194901dff57e5b751e852a8..f2a4d1ff65d46a2a014b6e40ed737d26a68a25d0 100644 (file)
@@ -65,3 +65,5 @@ obj-$(CONFIG_GP_PCI1XXXX)     += mchp_pci1xxxx/
 obj-$(CONFIG_VCPU_STALL_DETECTOR)      += vcpu_stall_detector.o
 obj-$(CONFIG_TMR_MANAGER)      += xilinx_tmr_manager.o
 obj-$(CONFIG_TMR_INJECT)       += xilinx_tmr_inject.o
+obj-$(CONFIG_TPS6594_ESM)      += tps6594-esm.o
+obj-$(CONFIG_TPS6594_PFSM)     += tps6594-pfsm.o
index 3856d5c04c5fdca66df37d175e785b7a7208afe1..469478f7a1d3313333e0ca20c9c5c793957b5bc0 100644 (file)
@@ -106,7 +106,7 @@ static struct i2c_driver ad_dpot_i2c_driver = {
        .driver = {
                .name   = "ad_dpot",
        },
-       .probe_new      = ad_dpot_i2c_probe,
+       .probe          = ad_dpot_i2c_probe,
        .remove         = ad_dpot_i2c_remove,
        .id_table       = ad_dpot_id,
 };
index dd0f8189666bef7e57e9e5f35c65d1b246b3b100..90f18e7bf9b0d90023acd64504897b0fce20e36b 100644 (file)
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
-altera-stapl-objs = altera-lpt.o altera-jtag.o altera-comp.o altera.o
+altera-stapl-y = altera-jtag.o altera-comp.o altera.o
+altera-stapl-$(CONFIG_HAS_IOPORT) += altera-lpt.o
 
 obj-$(CONFIG_ALTERA_STAPL) += altera-stapl.o
index a58b7cb81d98148d4f99713719f70e8bc374bba5..587427b73914c5da285958b5b5753edbaeccc2b1 100644 (file)
@@ -2407,6 +2407,10 @@ int altera_init(struct altera_config *config, const struct firmware *fw)
 
        astate->config = config;
        if (!astate->config->jtag_io) {
+               if (!IS_ENABLED(CONFIG_HAS_IOPORT)) {
+                       retval = -ENODEV;
+                       goto free_state;
+               }
                dprintk("%s: using byteblaster!\n", __func__);
                astate->config->jtag_io = netup_jtag_io_lpt;
        }
@@ -2481,7 +2485,7 @@ int altera_init(struct altera_config *config, const struct firmware *fw)
 
        } else if (exec_result)
                printk(KERN_ERR "%s: error %d\n", __func__, exec_result);
-
+free_state:
        kfree(astate);
 free_value:
        kfree(value);
index 0526c55d5cd5cb9f817c658a29c8e9171e9da772..693f0e539f37a55d6ca12fa397c389c3a34a9e26 100644 (file)
@@ -296,7 +296,7 @@ static struct i2c_driver apds9802als_driver = {
                .name = DRIVER_NAME,
                .pm = APDS9802ALS_PM_OPS,
        },
-       .probe_new = apds9802als_probe,
+       .probe = apds9802als_probe,
        .remove = apds9802als_remove,
        .id_table = apds9802als_id,
 };
index 0024503ea6dbbfd6ce5e64a8ddaa3f8b994c6746..92b92be91d6021a621220ebcd0681365633e17aa 100644 (file)
@@ -1267,11 +1267,11 @@ static const struct dev_pm_ops apds990x_pm_ops = {
 };
 
 static struct i2c_driver apds990x_driver = {
-       .driver  = {
+       .driver   = {
                .name   = "apds990x",
                .pm     = &apds990x_pm_ops,
        },
-       .probe_new = apds990x_probe,
+       .probe    = apds990x_probe,
        .remove   = apds990x_remove,
        .id_table = apds990x_id,
 };
index bedbe0efb330e7cfb16eba071c602ee6777cedbd..1629b62fd0524a9a5df25721f52cb9fd633c7b59 100644 (file)
@@ -1374,11 +1374,11 @@ static const struct dev_pm_ops bh1770_pm_ops = {
 };
 
 static struct i2c_driver bh1770_driver = {
-       .driver  = {
+       .driver   = {
                .name   = "bh1770glc",
                .pm     = &bh1770_pm_ops,
        },
-       .probe_new = bh1770_probe,
+       .probe    = bh1770_probe,
        .remove   = bh1770_remove,
        .id_table = bh1770_id,
 };
index d517eed32971c42495ea23b29ccf4e5c52892190..21fc5bc85c5c8cc198c86135484ab802fc94eb68 100644 (file)
@@ -250,7 +250,7 @@ static struct i2c_driver ds1682_driver = {
                .name = "ds1682",
                .of_match_table = ds1682_of_match,
        },
-       .probe_new = ds1682_probe,
+       .probe = ds1682_probe,
        .remove = ds1682_remove,
        .id_table = ds1682_id,
 };
index 938c4f41b98c7a2eaacb88ab5fc287c99df07f56..d93fbb1cb43ea75b9a4e7a43366523fcf6d88339 100644 (file)
@@ -832,7 +832,7 @@ static struct i2c_driver at24_driver = {
                .of_match_table = at24_of_match,
                .acpi_match_table = ACPI_PTR(at24_acpi_ids),
        },
-       .probe_new = at24_probe,
+       .probe = at24_probe,
        .remove = at24_remove,
        .id_table = at24_ids,
        .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
index c8c6deb7ed8943dbcb7e97c559e75c0985088f91..a1acd77130f26de8217efbcdb45b16abd58aaabf 100644 (file)
@@ -234,7 +234,7 @@ static struct i2c_driver ee1004_driver = {
                .name = "ee1004",
                .dev_groups = ee1004_groups,
        },
-       .probe_new = ee1004_probe,
+       .probe = ee1004_probe,
        .remove = ee1004_remove,
        .id_table = ee1004_ids,
 };
index 32611100d5cd332380dafe34f0ee0657f712ce2a..ccb7c2f7ee2fbfdc125222b1ab7705e5ba058a11 100644 (file)
@@ -196,7 +196,7 @@ static struct i2c_driver eeprom_driver = {
        .driver = {
                .name   = "eeprom",
        },
-       .probe_new      = eeprom_probe,
+       .probe          = eeprom_probe,
        .remove         = eeprom_remove,
        .id_table       = eeprom_id,
 
index 7075d0b378811bb1329e86d204078878f35dbbf9..740c06382b8347f898a9e6424b9ce32e0438074f 100644 (file)
@@ -1556,7 +1556,7 @@ static struct i2c_driver idt_driver = {
                .name = IDT_NAME,
                .of_match_table = idt_of_match,
        },
-       .probe_new = idt_probe,
+       .probe = idt_probe,
        .remove = idt_remove,
        .id_table = idt_ids,
 };
index 79cf8afcef2e81150771e371c7fc489bd89d4477..cb6b1efeafe0fe86416be16bd57bdc8424d3b7de 100644 (file)
@@ -192,7 +192,7 @@ static struct i2c_driver max6875_driver = {
        .driver = {
                .name   = "max6875",
        },
-       .probe_new      = max6875_probe,
+       .probe          = max6875_probe,
        .remove         = max6875_remove,
        .id_table       = max6875_id,
 };
index f48466960f1b9c0f9b78ff4c6d0038c7719e124f..9666d28037e1806ce6022840d383ef7e4b429f68 100644 (file)
@@ -316,12 +316,14 @@ static void fastrpc_free_map(struct kref *ref)
        if (map->table) {
                if (map->attr & FASTRPC_ATTR_SECUREMAP) {
                        struct qcom_scm_vmperm perm;
+                       int vmid = map->fl->cctx->vmperms[0].vmid;
+                       u64 src_perms = BIT(QCOM_SCM_VMID_HLOS) | BIT(vmid);
                        int err = 0;
 
                        perm.vmid = QCOM_SCM_VMID_HLOS;
                        perm.perm = QCOM_SCM_PERM_RWX;
                        err = qcom_scm_assign_mem(map->phys, map->size,
-                               &map->fl->cctx->perms, &perm, 1);
+                               &src_perms, &perm, 1);
                        if (err) {
                                dev_err(map->fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d",
                                                map->phys, map->size, err);
@@ -787,8 +789,12 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
                goto map_err;
        }
 
-       map->phys = sg_dma_address(map->table->sgl);
-       map->phys += ((u64)fl->sctx->sid << 32);
+       if (attr & FASTRPC_ATTR_SECUREMAP) {
+               map->phys = sg_phys(map->table->sgl);
+       } else {
+               map->phys = sg_dma_address(map->table->sgl);
+               map->phys += ((u64)fl->sctx->sid << 32);
+       }
        map->size = len;
        map->va = sg_virt(map->table->sgl);
        map->len = len;
@@ -798,9 +804,15 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
                 * If subsystem VMIDs are defined in DTSI, then do
                 * hyp_assign from HLOS to those VM(s)
                 */
+               u64 src_perms = BIT(QCOM_SCM_VMID_HLOS);
+               struct qcom_scm_vmperm dst_perms[2] = {0};
+
+               dst_perms[0].vmid = QCOM_SCM_VMID_HLOS;
+               dst_perms[0].perm = QCOM_SCM_PERM_RW;
+               dst_perms[1].vmid = fl->cctx->vmperms[0].vmid;
+               dst_perms[1].perm = QCOM_SCM_PERM_RWX;
                map->attr = attr;
-               err = qcom_scm_assign_mem(map->phys, (u64)map->size, &fl->cctx->perms,
-                               fl->cctx->vmperms, fl->cctx->vmcount);
+               err = qcom_scm_assign_mem(map->phys, (u64)map->size, &src_perms, dst_perms, 2);
                if (err) {
                        dev_err(sess->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d",
                                        map->phys, map->size, err);
@@ -1425,7 +1437,7 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl,
 
        sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE, 4, 0);
        if (init.attrs)
-               sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_ATTR, 6, 0);
+               sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_ATTR, 4, 0);
 
        err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE,
                                      sc, args);
@@ -1892,7 +1904,7 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
        req.vaddrout = rsp_msg.vaddr;
 
        /* Add memory to static PD pool, protection thru hypervisor */
-       if (req.flags != ADSP_MMAP_REMOTE_HEAP_ADDR && fl->cctx->vmcount) {
+       if (req.flags == ADSP_MMAP_REMOTE_HEAP_ADDR && fl->cctx->vmcount) {
                struct qcom_scm_vmperm perm;
 
                perm.vmid = QCOM_SCM_VMID_HLOS;
@@ -2213,6 +2225,9 @@ static int fastrpc_device_register(struct device *dev, struct fastrpc_channel_ct
        fdev->miscdev.fops = &fastrpc_fops;
        fdev->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "fastrpc-%s%s",
                                            domain, is_secured ? "-secure" : "");
+       if (!fdev->miscdev.name)
+               return -ENOMEM;
+
        err = misc_register(&fdev->miscdev);
        if (!err) {
                if (is_secured)
@@ -2337,8 +2352,10 @@ static void fastrpc_notify_users(struct fastrpc_user *user)
        struct fastrpc_invoke_ctx *ctx;
 
        spin_lock(&user->lock);
-       list_for_each_entry(ctx, &user->pending, node)
+       list_for_each_entry(ctx, &user->pending, node) {
+               ctx->retval = -EPIPE;
                complete(&ctx->work);
+       }
        spin_unlock(&user->lock);
 }
 
@@ -2349,7 +2366,9 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
        struct fastrpc_user *user;
        unsigned long flags;
 
+       /* No invocations past this point */
        spin_lock_irqsave(&cctx->lock, flags);
+       cctx->rpdev = NULL;
        list_for_each_entry(user, &cctx->users, user)
                fastrpc_notify_users(user);
        spin_unlock_irqrestore(&cctx->lock, flags);
@@ -2368,7 +2387,6 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
 
        of_platform_depopulate(&rpdev->dev);
 
-       cctx->rpdev = NULL;
        fastrpc_channel_ctx_put(cctx);
 }
 
index 8967940ecd1e8ae9bc6def638b909498372618de..759eaeb64307cd38b4cb4d869a02356ea14f4220 100644 (file)
@@ -131,7 +131,7 @@ static struct i2c_driver hmc6352_driver = {
        .driver = {
                .name = "hmc6352",
        },
-       .probe_new = hmc6352_probe,
+       .probe = hmc6352_probe,
        .remove = hmc6352_remove,
        .id_table = hmc6352_id,
 };
index 12108a7b9b40df7c4b879644d90e8dfe44192621..ee6296b9807823727db7a8d63608718481c8cb72 100644 (file)
@@ -105,7 +105,7 @@ static struct i2c_driver ics932s401_driver = {
        .driver = {
                .name   = "ics932s401",
        },
-       .probe_new      = ics932s401_probe,
+       .probe          = ics932s401_probe,
        .remove         = ics932s401_remove,
        .id_table       = ics932s401_id,
        .detect         = ics932s401_detect,
index 147b58f7968da8fca5b9ed2ed47eacaebf19c1bc..ebf0635aee64a8d856ff496373d99c277cc7dd2a 100644 (file)
@@ -459,7 +459,7 @@ static struct i2c_driver isl29003_driver = {
                .name   = ISL29003_DRV_NAME,
                .pm     = ISL29003_PM_OPS,
        },
-       .probe_new = isl29003_probe,
+       .probe = isl29003_probe,
        .remove = isl29003_remove,
        .id_table = isl29003_id,
 };
index 3be02093368cf951e5eec2f7bda77d9097f563bc..c5976fa8c825053b8d01a1fde81c9503f9e9713c 100644 (file)
@@ -214,7 +214,7 @@ static struct i2c_driver isl29020_driver = {
                .name = "isl29020",
                .pm = ISL29020_PM_OPS,
        },
-       .probe_new = isl29020_probe,
+       .probe = isl29020_probe,
        .remove = isl29020_remove,
        .id_table = isl29020_id,
 };
index 7071412d6bf63ea1eb7196cdef52f01ccbe8e5e9..3882e97e96a70f580a599f940d6a400a42469c8c 100644 (file)
@@ -262,7 +262,7 @@ static struct i2c_driver lis3lv02d_i2c_driver = {
                .pm     = &lis3_pm_ops,
                .of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids),
        },
-       .probe_new = lis3lv02d_i2c_probe,
+       .probe = lis3lv02d_i2c_probe,
        .remove = lis3lv02d_i2c_remove,
        .id_table = lis3lv02d_id,
 };
index b4712ff196b4e59bf76347f01213ac43344d98b5..0772e4a4757e9f47a32abb6a76dc613261b2a642 100644 (file)
@@ -79,7 +79,7 @@ static struct crashpoint crashpoints[] = {
        CRASHPOINT("INT_HARDWARE_ENTRY", "do_IRQ"),
        CRASHPOINT("INT_HW_IRQ_EN",      "handle_irq_event"),
        CRASHPOINT("INT_TASKLET_ENTRY",  "tasklet_action"),
-       CRASHPOINT("FS_DEVRW",           "ll_rw_block"),
+       CRASHPOINT("FS_SUBMIT_BH",               "submit_bh"),
        CRASHPOINT("MEM_SWAPOUT",        "shrink_inactive_list"),
        CRASHPOINT("TIMERADD",           "hrtimer_start"),
        CRASHPOINT("SCSI_QUEUE_RQ",      "scsi_queue_rq"),
index 31e3c74ca1f1e4a377592fb8e76b2ce327684063..b8b716faf1921914fad9fcc7228b8a07c6d545e3 100644 (file)
@@ -108,7 +108,7 @@ struct mkhi_fw_ver {
 static int mei_osver(struct mei_cl_device *cldev)
 {
        const size_t size = MKHI_OSVER_BUF_LEN;
-       char buf[MKHI_OSVER_BUF_LEN];
+       u8 buf[MKHI_OSVER_BUF_LEN];
        struct mkhi_msg *req;
        struct mkhi_fwcaps *fwcaps;
        struct mei_os_ver *os_ver;
@@ -137,7 +137,7 @@ static int mei_osver(struct mei_cl_device *cldev)
                               sizeof(struct mkhi_fw_ver_block) * (__num))
 static int mei_fwver(struct mei_cl_device *cldev)
 {
-       char buf[MKHI_FWVER_BUF_LEN];
+       u8 buf[MKHI_FWVER_BUF_LEN];
        struct mkhi_msg req;
        struct mkhi_msg *rsp;
        struct mkhi_fw_ver *fwver;
index 5d7a68674d9b20b32c415fe8c132ea3c558f03e0..33ec6424dfee25aacd862fd00b2b2f806fbd426c 100644 (file)
@@ -1046,9 +1046,6 @@ static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
        const struct mei_cl_driver *cldrv = to_mei_cl_driver(drv);
        const struct mei_cl_device_id *found_id;
 
-       if (!cldev)
-               return 0;
-
        if (!cldev->do_match)
                return 0;
 
@@ -1079,9 +1076,6 @@ static int mei_cl_device_probe(struct device *dev)
        cldev = to_mei_cl_device(dev);
        cldrv = to_mei_cl_driver(dev->driver);
 
-       if (!cldev)
-               return 0;
-
        if (!cldrv || !cldrv->probe)
                return -ENODEV;
 
@@ -1276,9 +1270,6 @@ static void mei_cl_bus_dev_release(struct device *dev)
 {
        struct mei_cl_device *cldev = to_mei_cl_device(dev);
 
-       if (!cldev)
-               return;
-
        mei_cl_flush_queues(cldev->cl, NULL);
        mei_me_cl_put(cldev->me_cl);
        mei_dev_bus_put(cldev->bus);
index a1f0b2c77fac34299fe7a8984fd32caa8cd0cb4e..c12035a465854ddd5077340b8c7bedbf6f1cd993 100644 (file)
@@ -6,7 +6,6 @@
  *
  */
 
-#include <linux/i2c.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
index 99413310956bbee8a86fbc7396c7b0fff9451a07..5757adf418b1de0f0aeee60edaed035b2d241d01 100644 (file)
@@ -235,10 +235,11 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
                                goto err_chunks;
                        }
                        if (!label)
-                               label = child->name;
-
-                       block->label = devm_kstrdup(sram->dev,
-                                                   label, GFP_KERNEL);
+                               block->label = devm_kasprintf(sram->dev, GFP_KERNEL,
+                                                             "%s", dev_name(sram->dev));
+                       else
+                               block->label = devm_kstrdup(sram->dev,
+                                                           label, GFP_KERNEL);
                        if (!block->label) {
                                ret = -ENOMEM;
                                goto err_chunks;
diff --git a/drivers/misc/tps6594-esm.c b/drivers/misc/tps6594-esm.c
new file mode 100644 (file)
index 0000000..b488f70
--- /dev/null
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ESM (Error Signal Monitor) driver for TI TPS6594/TPS6593/LP8764 PMICs
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/tps6594.h>
+
+static irqreturn_t tps6594_esm_isr(int irq, void *dev_id)
+{
+       struct platform_device *pdev = dev_id;
+       int i;
+
+       for (i = 0 ; i < pdev->num_resources ; i++) {
+               if (irq == platform_get_irq_byname(pdev, pdev->resource[i].name)) {
+                       dev_err(pdev->dev.parent, "%s error detected\n", pdev->resource[i].name);
+                       return IRQ_HANDLED;
+               }
+       }
+
+       return IRQ_NONE;
+}
+
+static int tps6594_esm_probe(struct platform_device *pdev)
+{
+       struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
+       struct device *dev = &pdev->dev;
+       int irq;
+       int ret;
+       int i;
+
+       for (i = 0 ; i < pdev->num_resources ; i++) {
+               irq = platform_get_irq_byname(pdev, pdev->resource[i].name);
+               if (irq < 0)
+                       return dev_err_probe(dev, irq, "Failed to get %s irq\n",
+                                            pdev->resource[i].name);
+
+               ret = devm_request_threaded_irq(dev, irq, NULL,
+                                               tps6594_esm_isr, IRQF_ONESHOT,
+                                               pdev->resource[i].name, pdev);
+               if (ret)
+                       return dev_err_probe(dev, ret, "Failed to request irq\n");
+       }
+
+       ret = regmap_set_bits(tps->regmap, TPS6594_REG_ESM_SOC_MODE_CFG,
+                             TPS6594_BIT_ESM_SOC_EN | TPS6594_BIT_ESM_SOC_ENDRV);
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to configure ESM\n");
+
+       ret = regmap_set_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
+                             TPS6594_BIT_ESM_SOC_START);
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to start ESM\n");
+
+       pm_runtime_enable(dev);
+       pm_runtime_get_sync(dev);
+
+       return 0;
+}
+
+static int tps6594_esm_remove(struct platform_device *pdev)
+{
+       struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
+       struct device *dev = &pdev->dev;
+       int ret;
+
+       ret = regmap_clear_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
+                               TPS6594_BIT_ESM_SOC_START);
+       if (ret) {
+               dev_err(dev, "Failed to stop ESM\n");
+               goto out;
+       }
+
+       ret = regmap_clear_bits(tps->regmap, TPS6594_REG_ESM_SOC_MODE_CFG,
+                               TPS6594_BIT_ESM_SOC_EN | TPS6594_BIT_ESM_SOC_ENDRV);
+       if (ret)
+               dev_err(dev, "Failed to unconfigure ESM\n");
+
+out:
+       pm_runtime_put_sync(dev);
+       pm_runtime_disable(dev);
+
+       return ret;
+}
+
+static int tps6594_esm_suspend(struct device *dev)
+{
+       struct tps6594 *tps = dev_get_drvdata(dev->parent);
+       int ret;
+
+       ret = regmap_clear_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
+                               TPS6594_BIT_ESM_SOC_START);
+
+       pm_runtime_put_sync(dev);
+
+       return ret;
+}
+
+static int tps6594_esm_resume(struct device *dev)
+{
+       struct tps6594 *tps = dev_get_drvdata(dev->parent);
+
+       pm_runtime_get_sync(dev);
+
+       return regmap_set_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
+                              TPS6594_BIT_ESM_SOC_START);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(tps6594_esm_pm_ops, tps6594_esm_suspend, tps6594_esm_resume);
+
+static struct platform_driver tps6594_esm_driver = {
+       .driver = {
+               .name = "tps6594-esm",
+               .pm = pm_sleep_ptr(&tps6594_esm_pm_ops),
+       },
+       .probe = tps6594_esm_probe,
+       .remove = tps6594_esm_remove,
+};
+
+module_platform_driver(tps6594_esm_driver);
+
+MODULE_ALIAS("platform:tps6594-esm");
+MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 Error Signal Monitor Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/tps6594-pfsm.c b/drivers/misc/tps6594-pfsm.c
new file mode 100644 (file)
index 0000000..5223d15
--- /dev/null
@@ -0,0 +1,306 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PFSM (Pre-configurable Finite State Machine) driver for TI TPS6594/TPS6593/LP8764 PMICs
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/ioctl.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/tps6594.h>
+
+#include <linux/tps6594_pfsm.h>
+
+#define TPS6594_STARTUP_DEST_MCU_ONLY_VAL 2
+#define TPS6594_STARTUP_DEST_ACTIVE_VAL   3
+#define TPS6594_STARTUP_DEST_SHIFT       5
+#define TPS6594_STARTUP_DEST_MCU_ONLY    (TPS6594_STARTUP_DEST_MCU_ONLY_VAL \
+                                          << TPS6594_STARTUP_DEST_SHIFT)
+#define TPS6594_STARTUP_DEST_ACTIVE      (TPS6594_STARTUP_DEST_ACTIVE_VAL \
+                                          << TPS6594_STARTUP_DEST_SHIFT)
+
+/*
+ * To update the PMIC firmware, the user must be able to access
+ * page 0 (user registers) and page 1 (NVM control and configuration).
+ */
+#define TPS6594_PMIC_MAX_POS 0x200
+
+#define TPS6594_FILE_TO_PFSM(f) container_of((f)->private_data, struct tps6594_pfsm, miscdev)
+
+/**
+ * struct tps6594_pfsm - device private data structure
+ *
+ * @miscdev: misc device infos
+ * @regmap:  regmap for accessing the device registers
+ */
+struct tps6594_pfsm {
+       struct miscdevice miscdev;
+       struct regmap *regmap;
+};
+
+static ssize_t tps6594_pfsm_read(struct file *f, char __user *buf,
+                                size_t count, loff_t *ppos)
+{
+       struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f);
+       loff_t pos = *ppos;
+       unsigned int val;
+       int ret;
+       int i;
+
+       if (pos < 0)
+               return -EINVAL;
+       if (pos >= TPS6594_PMIC_MAX_POS)
+               return 0;
+       if (count > TPS6594_PMIC_MAX_POS - pos)
+               count = TPS6594_PMIC_MAX_POS - pos;
+
+       for (i = 0 ; i < count ; i++) {
+               ret = regmap_read(pfsm->regmap, pos + i, &val);
+               if (ret)
+                       return ret;
+
+               if (put_user(val, buf + i))
+                       return -EFAULT;
+       }
+
+       *ppos = pos + count;
+
+       return count;
+}
+
+static ssize_t tps6594_pfsm_write(struct file *f, const char __user *buf,
+                                 size_t count, loff_t *ppos)
+{
+       struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f);
+       loff_t pos = *ppos;
+       char val;
+       int ret;
+       int i;
+
+       if (pos < 0)
+               return -EINVAL;
+       if (pos >= TPS6594_PMIC_MAX_POS || !count)
+               return 0;
+       if (count > TPS6594_PMIC_MAX_POS - pos)
+               count = TPS6594_PMIC_MAX_POS - pos;
+
+       for (i = 0 ; i < count ; i++) {
+               if (get_user(val, buf + i))
+                       return -EFAULT;
+
+               ret = regmap_write(pfsm->regmap, pos + i, val);
+               if (ret)
+                       return ret;
+       }
+
+       *ppos = pos + count;
+
+       return count;
+}
+
+static int tps6594_pfsm_configure_ret_trig(struct regmap *regmap, u8 gpio_ret, u8 ddr_ret)
+{
+       int ret;
+
+       if (gpio_ret)
+               ret = regmap_set_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+                                     TPS6594_BIT_TRIGGER_I2C(5) | TPS6594_BIT_TRIGGER_I2C(6));
+       else
+               ret = regmap_clear_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+                                       TPS6594_BIT_TRIGGER_I2C(5) | TPS6594_BIT_TRIGGER_I2C(6));
+       if (ret)
+               return ret;
+
+       if (ddr_ret)
+               ret = regmap_set_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+                                     TPS6594_BIT_TRIGGER_I2C(7));
+       else
+               ret = regmap_clear_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+                                       TPS6594_BIT_TRIGGER_I2C(7));
+
+       return ret;
+}
+
+static long tps6594_pfsm_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+       struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f);
+       struct pmic_state_opt state_opt;
+       void __user *argp = (void __user *)arg;
+       int ret = -ENOIOCTLCMD;
+
+       switch (cmd) {
+       case PMIC_GOTO_STANDBY:
+               /* Disable LP mode */
+               ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
+                                       TPS6594_BIT_LP_STANDBY_SEL);
+               if (ret)
+                       return ret;
+
+               /* Force trigger */
+               ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+                                       TPS6594_BIT_TRIGGER_I2C(0), TPS6594_BIT_TRIGGER_I2C(0));
+               break;
+       case PMIC_GOTO_LP_STANDBY:
+               /* Enable LP mode */
+               ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
+                                     TPS6594_BIT_LP_STANDBY_SEL);
+               if (ret)
+                       return ret;
+
+               /* Force trigger */
+               ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+                                       TPS6594_BIT_TRIGGER_I2C(0), TPS6594_BIT_TRIGGER_I2C(0));
+               break;
+       case PMIC_UPDATE_PGM:
+               /* Force trigger */
+               ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+                                       TPS6594_BIT_TRIGGER_I2C(3), TPS6594_BIT_TRIGGER_I2C(3));
+               break;
+       case PMIC_SET_ACTIVE_STATE:
+               /* Modify NSLEEP1-2 bits */
+               ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
+                                     TPS6594_BIT_NSLEEP1B | TPS6594_BIT_NSLEEP2B);
+               break;
+       case PMIC_SET_MCU_ONLY_STATE:
+               if (copy_from_user(&state_opt, argp, sizeof(state_opt)))
+                       return -EFAULT;
+
+               /* Configure retention triggers */
+               ret = tps6594_pfsm_configure_ret_trig(pfsm->regmap, state_opt.gpio_retention,
+                                                     state_opt.ddr_retention);
+               if (ret)
+                       return ret;
+
+               /* Modify NSLEEP1-2 bits */
+               ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
+                                       TPS6594_BIT_NSLEEP1B);
+               if (ret)
+                       return ret;
+
+               ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
+                                     TPS6594_BIT_NSLEEP2B);
+               break;
+       case PMIC_SET_RETENTION_STATE:
+               if (copy_from_user(&state_opt, argp, sizeof(state_opt)))
+                       return -EFAULT;
+
+               /* Configure wake-up destination */
+               if (state_opt.mcu_only_startup_dest)
+                       ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
+                                               TPS6594_MASK_STARTUP_DEST,
+                                               TPS6594_STARTUP_DEST_MCU_ONLY);
+               else
+                       ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
+                                               TPS6594_MASK_STARTUP_DEST,
+                                               TPS6594_STARTUP_DEST_ACTIVE);
+               if (ret)
+                       return ret;
+
+               /* Configure retention triggers */
+               ret = tps6594_pfsm_configure_ret_trig(pfsm->regmap, state_opt.gpio_retention,
+                                                     state_opt.ddr_retention);
+               if (ret)
+                       return ret;
+
+               /* Modify NSLEEP1-2 bits */
+               ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
+                                       TPS6594_BIT_NSLEEP2B);
+               break;
+       }
+
+       return ret;
+}
+
+static const struct file_operations tps6594_pfsm_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = generic_file_llseek,
+       .read           = tps6594_pfsm_read,
+       .write          = tps6594_pfsm_write,
+       .unlocked_ioctl = tps6594_pfsm_ioctl,
+       .compat_ioctl   = compat_ptr_ioctl,
+};
+
+static irqreturn_t tps6594_pfsm_isr(int irq, void *dev_id)
+{
+       struct platform_device *pdev = dev_id;
+       int i;
+
+       for (i = 0 ; i < pdev->num_resources ; i++) {
+               if (irq == platform_get_irq_byname(pdev, pdev->resource[i].name)) {
+                       dev_err(pdev->dev.parent, "%s event detected\n", pdev->resource[i].name);
+                       return IRQ_HANDLED;
+               }
+       }
+
+       return IRQ_NONE;
+}
+
+static int tps6594_pfsm_probe(struct platform_device *pdev)
+{
+       struct tps6594_pfsm *pfsm;
+       struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
+       struct device *dev = &pdev->dev;
+       int irq;
+       int ret;
+       int i;
+
+       pfsm = devm_kzalloc(dev, sizeof(struct tps6594_pfsm), GFP_KERNEL);
+       if (!pfsm)
+               return -ENOMEM;
+
+       pfsm->regmap = tps->regmap;
+
+       pfsm->miscdev.minor = MISC_DYNAMIC_MINOR;
+       pfsm->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "pfsm-%ld-0x%02x",
+                                           tps->chip_id, tps->reg);
+       pfsm->miscdev.fops = &tps6594_pfsm_fops;
+       pfsm->miscdev.parent = dev->parent;
+
+       for (i = 0 ; i < pdev->num_resources ; i++) {
+               irq = platform_get_irq_byname(pdev, pdev->resource[i].name);
+               if (irq < 0)
+                       return dev_err_probe(dev, irq, "Failed to get %s irq\n",
+                                            pdev->resource[i].name);
+
+               ret = devm_request_threaded_irq(dev, irq, NULL,
+                                               tps6594_pfsm_isr, IRQF_ONESHOT,
+                                               pdev->resource[i].name, pdev);
+               if (ret)
+                       return dev_err_probe(dev, ret, "Failed to request irq\n");
+       }
+
+       platform_set_drvdata(pdev, pfsm);
+
+       return misc_register(&pfsm->miscdev);
+}
+
+static int tps6594_pfsm_remove(struct platform_device *pdev)
+{
+       struct tps6594_pfsm *pfsm = platform_get_drvdata(pdev);
+
+       misc_deregister(&pfsm->miscdev);
+
+       return 0;
+}
+
+static struct platform_driver tps6594_pfsm_driver = {
+       .driver = {
+               .name = "tps6594-pfsm",
+       },
+       .probe = tps6594_pfsm_probe,
+       .remove = tps6594_pfsm_remove,
+};
+
+module_platform_driver(tps6594_pfsm_driver);
+
+MODULE_ALIAS("platform:tps6594-pfsm");
+MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 Pre-configurable Finite State Machine Driver");
+MODULE_LICENSE("GPL");
index 6c62b94e0acdb3c79d461ac445363fb6f92e84e5..a3bc2823143ebc23e949eb32790580c1d87ae0c7 100644 (file)
@@ -437,7 +437,7 @@ static struct i2c_driver tsl2550_driver = {
                .of_match_table = tsl2550_of_match,
                .pm     = TSL2550_PM_OPS,
        },
-       .probe_new = tsl2550_probe,
+       .probe = tsl2550_probe,
        .remove = tsl2550_remove,
        .id_table = tsl2550_id,
 };
index 346bd7cf2e94f5a1fbcde7d1ab7f68983cf07801..930c252753a073ac13b8a8d09899f60d37c46b47 100644 (file)
@@ -166,8 +166,8 @@ static int uacce_fops_open(struct inode *inode, struct file *filep)
 
        init_waitqueue_head(&q->wait);
        filep->private_data = q;
-       uacce->inode = inode;
        q->state = UACCE_Q_INIT;
+       q->mapping = filep->f_mapping;
        mutex_init(&q->mutex);
        list_add(&q->list, &uacce->queues);
        mutex_unlock(&uacce->mutex);
@@ -200,12 +200,15 @@ static int uacce_fops_release(struct inode *inode, struct file *filep)
 static void uacce_vma_close(struct vm_area_struct *vma)
 {
        struct uacce_queue *q = vma->vm_private_data;
-       struct uacce_qfile_region *qfr = NULL;
 
-       if (vma->vm_pgoff < UACCE_MAX_REGION)
-               qfr = q->qfrs[vma->vm_pgoff];
+       if (vma->vm_pgoff < UACCE_MAX_REGION) {
+               struct uacce_qfile_region *qfr = q->qfrs[vma->vm_pgoff];
 
-       kfree(qfr);
+               mutex_lock(&q->mutex);
+               q->qfrs[vma->vm_pgoff] = NULL;
+               mutex_unlock(&q->mutex);
+               kfree(qfr);
+       }
 }
 
 static const struct vm_operations_struct uacce_vm_ops = {
@@ -574,12 +577,6 @@ void uacce_remove(struct uacce_device *uacce)
 
        if (!uacce)
                return;
-       /*
-        * unmap remaining mapping from user space, preventing user still
-        * access the mmaped area while parent device is already removed
-        */
-       if (uacce->inode)
-               unmap_mapping_range(uacce->inode->i_mapping, 0, 0, 1);
 
        /*
         * uacce_fops_open() may be running concurrently, even after we remove
@@ -597,6 +594,12 @@ void uacce_remove(struct uacce_device *uacce)
                uacce_put_queue(q);
                mutex_unlock(&q->mutex);
                uacce_unbind_queue(q);
+
+               /*
+                * unmap remaining mapping from user space, preventing user still
+                * access the mmaped area while parent device is already removed
+                */
+               unmap_mapping_range(q->mapping, 0, 0, 1);
        }
 
        /* disable sva now since no opened queues */
index cb9506f9cbd07077756625a9621580a6ec6269b9..270ff4c5971a1ab186d5500a8631fe1d80fe199f 100644 (file)
@@ -855,16 +855,6 @@ static int xsdfec_cfg_axi_streams(struct xsdfec_dev *xsdfec)
        return 0;
 }
 
-static int xsdfec_dev_open(struct inode *iptr, struct file *fptr)
-{
-       return 0;
-}
-
-static int xsdfec_dev_release(struct inode *iptr, struct file *fptr)
-{
-       return 0;
-}
-
 static int xsdfec_start(struct xsdfec_dev *xsdfec)
 {
        u32 regread;
@@ -1030,8 +1020,6 @@ static __poll_t xsdfec_poll(struct file *file, poll_table *wait)
 
 static const struct file_operations xsdfec_fops = {
        .owner = THIS_MODULE,
-       .open = xsdfec_dev_open,
-       .release = xsdfec_dev_release,
        .unlocked_ioctl = xsdfec_dev_ioctl,
        .poll = xsdfec_poll,
        .compat_ioctl = compat_ptr_ioctl,
index 00c33edb9fb94ed4c6cd7c4f0830ea5d71d901e1..d920c417838930214b7d9c77fc4208d66c177e6e 100644 (file)
@@ -264,6 +264,7 @@ static ssize_t power_ro_lock_store(struct device *dev,
                goto out_put;
        }
        req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_BOOT_WP;
+       req_to_mmc_queue_req(req)->drv_op_result = -EIO;
        blk_execute_rq(req, false);
        ret = req_to_mmc_queue_req(req)->drv_op_result;
        blk_mq_free_request(req);
@@ -651,6 +652,7 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
        idatas[0] = idata;
        req_to_mmc_queue_req(req)->drv_op =
                rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
+       req_to_mmc_queue_req(req)->drv_op_result = -EIO;
        req_to_mmc_queue_req(req)->drv_op_data = idatas;
        req_to_mmc_queue_req(req)->ioc_count = 1;
        blk_execute_rq(req, false);
@@ -722,6 +724,7 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
        }
        req_to_mmc_queue_req(req)->drv_op =
                rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
+       req_to_mmc_queue_req(req)->drv_op_result = -EIO;
        req_to_mmc_queue_req(req)->drv_op_data = idata;
        req_to_mmc_queue_req(req)->ioc_count = n;
        blk_execute_rq(req, false);
@@ -2806,6 +2809,7 @@ static int mmc_dbg_card_status_get(void *data, u64 *val)
        if (IS_ERR(req))
                return PTR_ERR(req);
        req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_CARD_STATUS;
+       req_to_mmc_queue_req(req)->drv_op_result = -EIO;
        blk_execute_rq(req, false);
        ret = req_to_mmc_queue_req(req)->drv_op_result;
        if (ret >= 0) {
@@ -2844,6 +2848,7 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
                goto out_free;
        }
        req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_EXT_CSD;
+       req_to_mmc_queue_req(req)->drv_op_result = -EIO;
        req_to_mmc_queue_req(req)->drv_op_data = &ext_csd;
        blk_execute_rq(req, false);
        err = req_to_mmc_queue_req(req)->drv_op_result;
index 2e120ad83020f8f51d4bb529b1a470f9de65bf78..0c5f5e371e1f8311f3454e1fc0c462cde2841787 100644 (file)
@@ -28,7 +28,6 @@ struct mmc_pwrseq_sd8787 {
        struct mmc_pwrseq pwrseq;
        struct gpio_desc *reset_gpio;
        struct gpio_desc *pwrdn_gpio;
-       u32 reset_pwrdwn_delay_ms;
 };
 
 #define to_pwrseq_sd8787(p) container_of(p, struct mmc_pwrseq_sd8787, pwrseq)
@@ -39,7 +38,7 @@ static void mmc_pwrseq_sd8787_pre_power_on(struct mmc_host *host)
 
        gpiod_set_value_cansleep(pwrseq->reset_gpio, 1);
 
-       msleep(pwrseq->reset_pwrdwn_delay_ms);
+       msleep(300);
        gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 1);
 }
 
@@ -51,17 +50,37 @@ static void mmc_pwrseq_sd8787_power_off(struct mmc_host *host)
        gpiod_set_value_cansleep(pwrseq->reset_gpio, 0);
 }
 
+static void mmc_pwrseq_wilc1000_pre_power_on(struct mmc_host *host)
+{
+       struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
+
+       /* The pwrdn_gpio is really CHIP_EN, reset_gpio is RESETN */
+       gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 1);
+       msleep(5);
+       gpiod_set_value_cansleep(pwrseq->reset_gpio, 1);
+}
+
+static void mmc_pwrseq_wilc1000_power_off(struct mmc_host *host)
+{
+       struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
+
+       gpiod_set_value_cansleep(pwrseq->reset_gpio, 0);
+       gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 0);
+}
+
 static const struct mmc_pwrseq_ops mmc_pwrseq_sd8787_ops = {
        .pre_power_on = mmc_pwrseq_sd8787_pre_power_on,
        .power_off = mmc_pwrseq_sd8787_power_off,
 };
 
-static const u32 sd8787_delay_ms = 300;
-static const u32 wilc1000_delay_ms = 5;
+static const struct mmc_pwrseq_ops mmc_pwrseq_wilc1000_ops = {
+       .pre_power_on = mmc_pwrseq_wilc1000_pre_power_on,
+       .power_off = mmc_pwrseq_wilc1000_power_off,
+};
 
 static const struct of_device_id mmc_pwrseq_sd8787_of_match[] = {
-       { .compatible = "mmc-pwrseq-sd8787", .data = &sd8787_delay_ms },
-       { .compatible = "mmc-pwrseq-wilc1000", .data = &wilc1000_delay_ms },
+       { .compatible = "mmc-pwrseq-sd8787", .data = &mmc_pwrseq_sd8787_ops },
+       { .compatible = "mmc-pwrseq-wilc1000", .data = &mmc_pwrseq_wilc1000_ops },
        {/* sentinel */},
 };
 MODULE_DEVICE_TABLE(of, mmc_pwrseq_sd8787_of_match);
@@ -77,7 +96,6 @@ static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        match = of_match_node(mmc_pwrseq_sd8787_of_match, pdev->dev.of_node);
-       pwrseq->reset_pwrdwn_delay_ms = *(u32 *)match->data;
 
        pwrseq->pwrdn_gpio = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_LOW);
        if (IS_ERR(pwrseq->pwrdn_gpio))
@@ -88,7 +106,7 @@ static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev)
                return PTR_ERR(pwrseq->reset_gpio);
 
        pwrseq->pwrseq.dev = dev;
-       pwrseq->pwrseq.ops = &mmc_pwrseq_sd8787_ops;
+       pwrseq->pwrseq.ops = match->data;
        pwrseq->pwrseq.owner = THIS_MODULE;
        platform_set_drvdata(pdev, pwrseq);
 
index b24aa27da50c40dd861212d8b7e7cfc848e962cd..d2f62505468932b069e3411f2a4b7418ffece517 100644 (file)
@@ -540,9 +540,11 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
 
        if (host->mmc->caps & MMC_CAP_HW_RESET) {
                priv->rst_hw = devm_reset_control_get_optional_exclusive(dev, NULL);
-               if (IS_ERR(priv->rst_hw))
-                       return dev_err_probe(mmc_dev(host->mmc), PTR_ERR(priv->rst_hw),
-                                            "reset controller error\n");
+               if (IS_ERR(priv->rst_hw)) {
+                       ret = dev_err_probe(mmc_dev(host->mmc), PTR_ERR(priv->rst_hw),
+                                           "reset controller error\n");
+                       goto free;
+               }
                if (priv->rst_hw)
                        host->mmc_host_ops.card_hw_reset = sdhci_cdns_mmc_hw_reset;
        }
index d7c0c0b9e26c5e10563337cfbfca23d739956dd6..eebf94604a7fdd45dc578bb1fa7d4217ad996927 100644 (file)
@@ -1634,6 +1634,10 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
        if (ret)
                return ret;
 
+       /* HS400/HS400ES require 8 bit bus */
+       if (!(host->mmc->caps & MMC_CAP_8_BIT_DATA))
+               host->mmc->caps2 &= ~(MMC_CAP2_HS400 | MMC_CAP2_HS400_ES);
+
        if (mmc_gpio_get_cd(host->mmc) >= 0)
                host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
 
@@ -1724,10 +1728,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
                host->mmc_host_ops.init_card = usdhc_init_card;
        }
 
-       err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
-       if (err)
-               goto disable_ahb_clk;
-
        if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
                sdhci_esdhc_ops.platform_execute_tuning =
                                        esdhc_executing_tuning;
@@ -1735,15 +1735,13 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
        if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
                host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
 
-       if (host->mmc->caps & MMC_CAP_8_BIT_DATA &&
-           imx_data->socdata->flags & ESDHC_FLAG_HS400)
+       if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
                host->mmc->caps2 |= MMC_CAP2_HS400;
 
        if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23)
                host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN;
 
-       if (host->mmc->caps & MMC_CAP_8_BIT_DATA &&
-           imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) {
+       if (imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) {
                host->mmc->caps2 |= MMC_CAP2_HS400_ES;
                host->mmc_host_ops.hs400_enhanced_strobe =
                                        esdhc_hs400_enhanced_strobe;
@@ -1765,6 +1763,10 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
                        goto disable_ahb_clk;
        }
 
+       err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
+       if (err)
+               goto disable_ahb_clk;
+
        sdhci_esdhc_imx_hwinit(host);
 
        err = sdhci_add_host(host);
index e4c4bfac3763bae1ec808dcdb3d06bb9fb049769..9ec593d52f0fa930daee67dbf2bf6979695e7e5e 100644 (file)
@@ -1713,6 +1713,9 @@ static void construct_request_response(struct vub300_mmc_host *vub300,
        int bytes = 3 & less_cmd;
        int words = less_cmd >> 2;
        u8 *r = vub300->resp.response.command_response;
+
+       if (!resp_len)
+               return;
        if (bytes == 3) {
                cmd->resp[words] = (r[1 + (words << 2)] << 24)
                        | (r[2 + (words << 2)] << 16)
index 01f1c6792df9c790622d2b039ee0fab992e6d0da..8dc4f5c493fcbac3abe17818cd5f7b2adcc70dd9 100644 (file)
@@ -590,8 +590,8 @@ static void adjust_oob_length(struct mtd_info *mtd, uint64_t start,
                            (end_page - start_page + 1) * oob_per_page);
 }
 
-static int mtdchar_write_ioctl(struct mtd_info *mtd,
-               struct mtd_write_req __user *argp)
+static noinline_for_stack int
+mtdchar_write_ioctl(struct mtd_info *mtd, struct mtd_write_req __user *argp)
 {
        struct mtd_info *master = mtd_get_master(mtd);
        struct mtd_write_req req;
@@ -688,8 +688,8 @@ static int mtdchar_write_ioctl(struct mtd_info *mtd,
        return ret;
 }
 
-static int mtdchar_read_ioctl(struct mtd_info *mtd,
-               struct mtd_read_req __user *argp)
+static noinline_for_stack int
+mtdchar_read_ioctl(struct mtd_info *mtd, struct mtd_read_req __user *argp)
 {
        struct mtd_info *master = mtd_get_master(mtd);
        struct mtd_read_req req;
index 2cda439b5e11bff0fc091a4ba31109b27cfdbb98..017868f59f2221611256b3f34edc09a196ea2581 100644 (file)
@@ -36,25 +36,25 @@ int ingenic_ecc_correct(struct ingenic_ecc *ecc,
 void ingenic_ecc_release(struct ingenic_ecc *ecc);
 struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *np);
 #else /* CONFIG_MTD_NAND_INGENIC_ECC */
-int ingenic_ecc_calculate(struct ingenic_ecc *ecc,
+static inline int ingenic_ecc_calculate(struct ingenic_ecc *ecc,
                          struct ingenic_ecc_params *params,
                          const u8 *buf, u8 *ecc_code)
 {
        return -ENODEV;
 }
 
-int ingenic_ecc_correct(struct ingenic_ecc *ecc,
+static inline int ingenic_ecc_correct(struct ingenic_ecc *ecc,
                        struct ingenic_ecc_params *params, u8 *buf,
                        u8 *ecc_code)
 {
        return -ENODEV;
 }
 
-void ingenic_ecc_release(struct ingenic_ecc *ecc)
+static inline void ingenic_ecc_release(struct ingenic_ecc *ecc)
 {
 }
 
-struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *np)
+static inline struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *np)
 {
        return ERR_PTR(-ENODEV);
 }
index afb424579f0b89777037726f54060fd21c2e0e73..30c15e4e1cc0d2899bf2fa943c1f7b95cc1d0e79 100644 (file)
@@ -2457,6 +2457,12 @@ static int marvell_nfc_setup_interface(struct nand_chip *chip, int chipnr,
                        NDTR1_WAIT_MODE;
        }
 
+       /*
+        * Reset nfc->selected_chip so the next command will cause the timing
+        * registers to be updated in marvell_nfc_select_target().
+        */
+       nfc->selected_chip = NULL;
+
        return 0;
 }
 
@@ -2894,10 +2900,6 @@ static int marvell_nfc_init(struct marvell_nfc *nfc)
                regmap_update_bits(sysctrl_base, GENCONF_CLK_GATING_CTRL,
                                   GENCONF_CLK_GATING_CTRL_ND_GATE,
                                   GENCONF_CLK_GATING_CTRL_ND_GATE);
-
-               regmap_update_bits(sysctrl_base, GENCONF_ND_CLK_CTRL,
-                                  GENCONF_ND_CLK_CTRL_EN,
-                                  GENCONF_ND_CLK_CTRL_EN);
        }
 
        /* Configure the DMA if appropriate */
index 0bb0ad14a2fc01c97d8e20144f8844186aea17df..5f29fac8669a301e8010566eee02edfdcdb66620 100644 (file)
@@ -2018,6 +2018,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
 
 static const struct flash_info spi_nor_generic_flash = {
        .name = "spi-nor-generic",
+       .n_banks = 1,
        /*
         * JESD216 rev A doesn't specify the page size, therefore we need a
         * sane default.
@@ -2921,7 +2922,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
        if (nor->flags & SNOR_F_HAS_LOCK && !nor->params->locking_ops)
                spi_nor_init_default_locking_ops(nor);
 
-       nor->params->bank_size = div64_u64(nor->params->size, nor->info->n_banks);
+       if (nor->info->n_banks > 1)
+               params->bank_size = div64_u64(params->size, nor->info->n_banks);
 }
 
 /**
@@ -2987,6 +2989,7 @@ static void spi_nor_init_default_params(struct spi_nor *nor)
        /* Set SPI NOR sizes. */
        params->writesize = 1;
        params->size = (u64)info->sector_size * info->n_sectors;
+       params->bank_size = params->size;
        params->page_size = info->page_size;
 
        if (!(info->flags & SPI_NOR_NO_FR)) {
index 15f9a80c10b9bd58096d95214b921dee5c72f48f..36876aa849ede7cda8d9900589fccbcb879c6d93 100644 (file)
@@ -361,7 +361,7 @@ static int cypress_nor_determine_addr_mode_by_sr1(struct spi_nor *nor,
  */
 static int cypress_nor_set_addr_mode_nbytes(struct spi_nor *nor)
 {
-       struct spi_mem_op op;
+       struct spi_mem_op op = {};
        u8 addr_mode;
        int ret;
 
@@ -492,7 +492,7 @@ s25fs256t_post_bfpt_fixup(struct spi_nor *nor,
                          const struct sfdp_parameter_header *bfpt_header,
                          const struct sfdp_bfpt *bfpt)
 {
-       struct spi_mem_op op;
+       struct spi_mem_op op = {};
        int ret;
 
        ret = cypress_nor_set_addr_mode_nbytes(nor);
index e5c571fd232cc2f220d84e72339443c5176b272e..80f015cf6e54f635bdae45b791c0c51a73222bfc 100644 (file)
@@ -47,7 +47,7 @@ config MUX_GPIO
 
 config MUX_MMIO
        tristate "MMIO/Regmap register bitfield-controlled Multiplexer"
-       depends on OF || COMPILE_TEST
+       depends on OF
        help
          MMIO/Regmap register bitfield-controlled Multiplexer controller.
 
index e8fc2fc1ab090da7995fa93b74b47cfb833fef14..4da5aecb9fc62bc38c4ab67e839a8f86fa7be5e2 100644 (file)
@@ -143,7 +143,7 @@ static struct i2c_driver adg792a_driver = {
                .name           = "adg792a",
                .of_match_table = of_match_ptr(adg792a_of_match),
        },
-       .probe_new      = adg792a_probe,
+       .probe          = adg792a_probe,
        .id_table       = adg792a_id,
 };
 module_i2c_driver(adg792a_driver);
index 44a7a0e885b8dc0ab5b436ea6366a7a87a8ef59b..245bc07eee4ba12d2956024e6fcfb4741a3531af 100644 (file)
@@ -131,7 +131,7 @@ static int mux_mmio_probe(struct platform_device *pdev)
 static struct platform_driver mux_mmio_driver = {
        .driver = {
                .name = "mmio-mux",
-               .of_match_table = of_match_ptr(mux_mmio_dt_ids),
+               .of_match_table = mux_mmio_dt_ids,
        },
        .probe = mux_mmio_probe,
 };
index 3fed888629f7b5d08fede3187fb5639d74185c13..edbaa1444f8ecd9bf344a50f6f599d7eaaf4ff3e 100644 (file)
@@ -3947,7 +3947,11 @@ static int bond_slave_netdev_event(unsigned long event,
                unblock_netpoll_tx();
                break;
        case NETDEV_FEAT_CHANGE:
-               bond_compute_features(bond);
+               if (!bond->notifier_ctx) {
+                       bond->notifier_ctx = true;
+                       bond_compute_features(bond);
+                       bond->notifier_ctx = false;
+               }
                break;
        case NETDEV_RESEND_IGMP:
                /* Propagate to master device */
@@ -6342,6 +6346,8 @@ static int bond_init(struct net_device *bond_dev)
        if (!bond->wq)
                return -ENOMEM;
 
+       bond->notifier_ctx = false;
+
        spin_lock_init(&bond->stats_lock);
        netdev_lockdep_set_classes(bond_dev);
 
index c2d080fc4fc4ea67bd81476c485af69f72c7c4bd..27cbe148f0db5f82e988af3773fff1e3fce0997d 100644 (file)
@@ -84,6 +84,11 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
+/* Limit the max delay range to 300s */
+static struct netlink_range_validation delay_range = {
+       .max = 300000,
+};
+
 static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
        [IFLA_BOND_MODE]                = { .type = NLA_U8 },
        [IFLA_BOND_ACTIVE_SLAVE]        = { .type = NLA_U32 },
@@ -114,7 +119,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
        [IFLA_BOND_AD_ACTOR_SYSTEM]     = { .type = NLA_BINARY,
                                            .len  = ETH_ALEN },
        [IFLA_BOND_TLB_DYNAMIC_LB]      = { .type = NLA_U8 },
-       [IFLA_BOND_PEER_NOTIF_DELAY]    = { .type = NLA_U32 },
+       [IFLA_BOND_PEER_NOTIF_DELAY]    = NLA_POLICY_FULL_RANGE(NLA_U32, &delay_range),
        [IFLA_BOND_MISSED_MAX]          = { .type = NLA_U8 },
        [IFLA_BOND_NS_IP6_TARGET]       = { .type = NLA_NESTED },
 };
index 0498fc6731f898f6a238498d42a0f0ade6c67856..f3f27f0bd2a6cdd52d8c97e10a9b047af9f2da00 100644 (file)
@@ -169,6 +169,12 @@ static const struct bond_opt_value bond_num_peer_notif_tbl[] = {
        { NULL,      -1,  0}
 };
 
+static const struct bond_opt_value bond_peer_notif_delay_tbl[] = {
+       { "off",     0,   0},
+       { "maxval",  300000, BOND_VALFLAG_MAX},
+       { NULL,      -1,  0}
+};
+
 static const struct bond_opt_value bond_primary_reselect_tbl[] = {
        { "always",  BOND_PRI_RESELECT_ALWAYS,  BOND_VALFLAG_DEFAULT},
        { "better",  BOND_PRI_RESELECT_BETTER,  0},
@@ -488,7 +494,7 @@ static const struct bond_option bond_opts[BOND_OPT_LAST] = {
                .id = BOND_OPT_PEER_NOTIF_DELAY,
                .name = "peer_notif_delay",
                .desc = "Delay between each peer notification on failover event, in milliseconds",
-               .values = bond_intmax_tbl,
+               .values = bond_peer_notif_delay_tbl,
                .set = bond_option_peer_notif_delay_set
        }
 };
index 3ceccafd701b2a319535791edd73d69513df45bc..b190007c01bec5f4e3b6bf11a60026560e09f333 100644 (file)
@@ -95,7 +95,7 @@ config CAN_AT91
 
 config CAN_BXCAN
        tristate "STM32 Basic Extended CAN (bxCAN) devices"
-       depends on OF || ARCH_STM32 || COMPILE_TEST
+       depends on ARCH_STM32 || COMPILE_TEST
        depends on HAS_IOMEM
        select CAN_RX_OFFLOAD
        help
index e26ccd41e3cba5ae4a13256e3b4dd3bca4ba3b0b..027a8a162fe49fb3457dd943b8d84cd55e4f319e 100644 (file)
 #define BXCAN_FiR1_REG(b) (0x40 + (b) * 8)
 #define BXCAN_FiR2_REG(b) (0x44 + (b) * 8)
 
-#define BXCAN_FILTER_ID(primary) (primary ? 0 : 14)
+#define BXCAN_FILTER_ID(cfg) ((cfg) == BXCAN_CFG_DUAL_SECONDARY ? 14 : 0)
 
 /* Filter primary register (FMR) bits */
 #define BXCAN_FMR_CANSB_MASK GENMASK(13, 8)
@@ -135,6 +135,12 @@ enum bxcan_lec_code {
        BXCAN_LEC_UNUSED
 };
 
+enum bxcan_cfg {
+       BXCAN_CFG_SINGLE = 0,
+       BXCAN_CFG_DUAL_PRIMARY,
+       BXCAN_CFG_DUAL_SECONDARY
+};
+
 /* Structure of the message buffer */
 struct bxcan_mb {
        u32 id;                 /* can identifier */
@@ -167,7 +173,7 @@ struct bxcan_priv {
        struct regmap *gcan;
        int tx_irq;
        int sce_irq;
-       bool primary;
+       enum bxcan_cfg cfg;
        struct clk *clk;
        spinlock_t rmw_lock;    /* lock for read-modify-write operations */
        unsigned int tx_head;
@@ -202,17 +208,17 @@ static inline void bxcan_rmw(struct bxcan_priv *priv, void __iomem *addr,
        spin_unlock_irqrestore(&priv->rmw_lock, flags);
 }
 
-static void bxcan_disable_filters(struct bxcan_priv *priv, bool primary)
+static void bxcan_disable_filters(struct bxcan_priv *priv, enum bxcan_cfg cfg)
 {
-       unsigned int fid = BXCAN_FILTER_ID(primary);
+       unsigned int fid = BXCAN_FILTER_ID(cfg);
        u32 fmask = BIT(fid);
 
        regmap_update_bits(priv->gcan, BXCAN_FA1R_REG, fmask, 0);
 }
 
-static void bxcan_enable_filters(struct bxcan_priv *priv, bool primary)
+static void bxcan_enable_filters(struct bxcan_priv *priv, enum bxcan_cfg cfg)
 {
-       unsigned int fid = BXCAN_FILTER_ID(primary);
+       unsigned int fid = BXCAN_FILTER_ID(cfg);
        u32 fmask = BIT(fid);
 
        /* Filter settings:
@@ -680,7 +686,7 @@ static int bxcan_chip_start(struct net_device *ndev)
                  BXCAN_BTR_BRP_MASK | BXCAN_BTR_TS1_MASK | BXCAN_BTR_TS2_MASK |
                  BXCAN_BTR_SJW_MASK, set);
 
-       bxcan_enable_filters(priv, priv->primary);
+       bxcan_enable_filters(priv, priv->cfg);
 
        /* Clear all internal status */
        priv->tx_head = 0;
@@ -806,7 +812,7 @@ static void bxcan_chip_stop(struct net_device *ndev)
                  BXCAN_IER_EPVIE | BXCAN_IER_EWGIE | BXCAN_IER_FOVIE1 |
                  BXCAN_IER_FFIE1 | BXCAN_IER_FMPIE1 | BXCAN_IER_FOVIE0 |
                  BXCAN_IER_FFIE0 | BXCAN_IER_FMPIE0 | BXCAN_IER_TMEIE, 0);
-       bxcan_disable_filters(priv, priv->primary);
+       bxcan_disable_filters(priv, priv->cfg);
        bxcan_enter_sleep_mode(priv);
        priv->can.state = CAN_STATE_STOPPED;
 }
@@ -931,7 +937,7 @@ static int bxcan_probe(struct platform_device *pdev)
        struct clk *clk = NULL;
        void __iomem *regs;
        struct regmap *gcan;
-       bool primary;
+       enum bxcan_cfg cfg;
        int err, rx_irq, tx_irq, sce_irq;
 
        regs = devm_platform_ioremap_resource(pdev, 0);
@@ -946,7 +952,13 @@ static int bxcan_probe(struct platform_device *pdev)
                return PTR_ERR(gcan);
        }
 
-       primary = of_property_read_bool(np, "st,can-primary");
+       if (of_property_read_bool(np, "st,can-primary"))
+               cfg = BXCAN_CFG_DUAL_PRIMARY;
+       else if (of_property_read_bool(np, "st,can-secondary"))
+               cfg = BXCAN_CFG_DUAL_SECONDARY;
+       else
+               cfg = BXCAN_CFG_SINGLE;
+
        clk = devm_clk_get(dev, NULL);
        if (IS_ERR(clk)) {
                dev_err(dev, "failed to get clock\n");
@@ -992,7 +1004,7 @@ static int bxcan_probe(struct platform_device *pdev)
        priv->clk = clk;
        priv->tx_irq = tx_irq;
        priv->sce_irq = sce_irq;
-       priv->primary = primary;
+       priv->cfg = cfg;
        priv->can.clock.freq = clk_get_rate(clk);
        spin_lock_init(&priv->rmw_lock);
        priv->tx_head = 0;
index 241ec636e91fd09f5006b694a3f32fec46662af6..f6d05b3ef59abf85a0bd7f40f9333983b44e4a90 100644 (file)
@@ -54,7 +54,8 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
        /* check flag whether this packet has to be looped back */
        if (!(dev->flags & IFF_ECHO) ||
            (skb->protocol != htons(ETH_P_CAN) &&
-            skb->protocol != htons(ETH_P_CANFD))) {
+            skb->protocol != htons(ETH_P_CANFD) &&
+            skb->protocol != htons(ETH_P_CANXL))) {
                kfree_skb(skb);
                return 0;
        }
index 53e8a914c88b57884b76a81c9a8750535550ca92..be189edb256ceb13590b170e3294ef72264a5092 100644 (file)
@@ -71,10 +71,12 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
 #define KVASER_PCIEFD_SYSID_BUILD_REG (KVASER_PCIEFD_SYSID_BASE + 0x14)
 /* Shared receive buffer registers */
 #define KVASER_PCIEFD_SRB_BASE 0x1f200
+#define KVASER_PCIEFD_SRB_FIFO_LAST_REG (KVASER_PCIEFD_SRB_BASE + 0x1f4)
 #define KVASER_PCIEFD_SRB_CMD_REG (KVASER_PCIEFD_SRB_BASE + 0x200)
 #define KVASER_PCIEFD_SRB_IEN_REG (KVASER_PCIEFD_SRB_BASE + 0x204)
 #define KVASER_PCIEFD_SRB_IRQ_REG (KVASER_PCIEFD_SRB_BASE + 0x20c)
 #define KVASER_PCIEFD_SRB_STAT_REG (KVASER_PCIEFD_SRB_BASE + 0x210)
+#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG (KVASER_PCIEFD_SRB_BASE + 0x214)
 #define KVASER_PCIEFD_SRB_CTRL_REG (KVASER_PCIEFD_SRB_BASE + 0x218)
 /* EPCS flash controller registers */
 #define KVASER_PCIEFD_SPI_BASE 0x1fc00
@@ -111,6 +113,9 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
 /* DMA support */
 #define KVASER_PCIEFD_SRB_STAT_DMA BIT(24)
 
+/* SRB current packet level */
+#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK 0xff
+
 /* DMA Enable */
 #define KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE BIT(0)
 
@@ -526,7 +531,7 @@ static int kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can)
              KVASER_PCIEFD_KCAN_IRQ_TOF | KVASER_PCIEFD_KCAN_IRQ_ABD |
              KVASER_PCIEFD_KCAN_IRQ_TAE | KVASER_PCIEFD_KCAN_IRQ_TAL |
              KVASER_PCIEFD_KCAN_IRQ_FDIC | KVASER_PCIEFD_KCAN_IRQ_BPP |
-             KVASER_PCIEFD_KCAN_IRQ_TAR | KVASER_PCIEFD_KCAN_IRQ_TFD;
+             KVASER_PCIEFD_KCAN_IRQ_TAR;
 
        iowrite32(msk, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 
@@ -554,6 +559,8 @@ static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can)
 
        if (can->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
                mode |= KVASER_PCIEFD_KCAN_MODE_LOM;
+       else
+               mode &= ~KVASER_PCIEFD_KCAN_MODE_LOM;
 
        mode |= KVASER_PCIEFD_KCAN_MODE_EEN;
        mode |= KVASER_PCIEFD_KCAN_MODE_EPEN;
@@ -572,7 +579,7 @@ static void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can)
 
        spin_lock_irqsave(&can->lock, irq);
        iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
-       iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD | KVASER_PCIEFD_KCAN_IRQ_TFD,
+       iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
                  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 
        status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
@@ -615,7 +622,7 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can)
        iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
        iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
 
-       iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD | KVASER_PCIEFD_KCAN_IRQ_TFD,
+       iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
                  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 
        mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
@@ -719,6 +726,7 @@ static int kvaser_pciefd_stop(struct net_device *netdev)
                iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
                del_timer(&can->bec_poll_timer);
        }
+       can->can.state = CAN_STATE_STOPPED;
        close_candev(netdev);
 
        return ret;
@@ -1007,8 +1015,7 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
                SET_NETDEV_DEV(netdev, &pcie->pci->dev);
 
                iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
-               iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD |
-                         KVASER_PCIEFD_KCAN_IRQ_TFD,
+               iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
                          can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 
                pcie->can[i] = can;
@@ -1058,6 +1065,7 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
 {
        int i;
        u32 srb_status;
+       u32 srb_packet_count;
        dma_addr_t dma_addr[KVASER_PCIEFD_DMA_COUNT];
 
        /* Disable the DMA */
@@ -1085,6 +1093,15 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
                  KVASER_PCIEFD_SRB_CMD_RDB1,
                  pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG);
 
+       /* Empty Rx FIFO */
+       srb_packet_count = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG) &
+                          KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK;
+       while (srb_packet_count) {
+               /* Drop current packet in FIFO */
+               ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_FIFO_LAST_REG);
+               srb_packet_count--;
+       }
+
        srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG);
        if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DI)) {
                dev_err(&pcie->pci->dev, "DMA not idle before enabling\n");
@@ -1425,9 +1442,6 @@ static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie,
                cmd = KVASER_PCIEFD_KCAN_CMD_AT;
                cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT;
                iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
-
-               iowrite32(KVASER_PCIEFD_KCAN_IRQ_TFD,
-                         can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
        } else if (p->header[0] & KVASER_PCIEFD_SPACK_IDET &&
                   p->header[0] & KVASER_PCIEFD_SPACK_IRM &&
                   cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) &&
@@ -1714,15 +1728,6 @@ static int kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can)
        if (irq & KVASER_PCIEFD_KCAN_IRQ_TOF)
                netdev_err(can->can.dev, "Tx FIFO overflow\n");
 
-       if (irq & KVASER_PCIEFD_KCAN_IRQ_TFD) {
-               u8 count = ioread32(can->reg_base +
-                                   KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff;
-
-               if (count == 0)
-                       iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH,
-                                 can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG);
-       }
-
        if (irq & KVASER_PCIEFD_KCAN_IRQ_BPP)
                netdev_err(can->can.dev,
                           "Fail to change bittiming, when not in reset mode\n");
@@ -1824,6 +1829,11 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
        if (err)
                goto err_teardown_can_ctrls;
 
+       err = request_irq(pcie->pci->irq, kvaser_pciefd_irq_handler,
+                         IRQF_SHARED, KVASER_PCIEFD_DRV_NAME, pcie);
+       if (err)
+               goto err_teardown_can_ctrls;
+
        iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1,
                  pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG);
 
@@ -1844,11 +1854,6 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
        iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1,
                  pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG);
 
-       err = request_irq(pcie->pci->irq, kvaser_pciefd_irq_handler,
-                         IRQF_SHARED, KVASER_PCIEFD_DRV_NAME, pcie);
-       if (err)
-               goto err_teardown_can_ctrls;
-
        err = kvaser_pciefd_reg_candev(pcie);
        if (err)
                goto err_free_irq;
@@ -1856,6 +1861,8 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
        return 0;
 
 err_free_irq:
+       /* Disable PCI interrupts */
+       iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG);
        free_irq(pcie->pci->irq, pcie);
 
 err_teardown_can_ctrls:
index 64a2f2f83735d04fdaa343cc80e24de8f1f3b97e..08a46ffd53af99524dc751dd05f2dbece4a6d71f 100644 (file)
@@ -7170,7 +7170,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
                goto out;
        }
        if (chip->reset)
-               usleep_range(1000, 2000);
+               usleep_range(10000, 20000);
 
        /* Detect if the device is configured in single chip addressing mode,
         * otherwise continue with address specific smi init/detection.
index aec9d4fd20e3631cbb9cc6eb3951b8e2d74ff644..d19b6303b91f0aafc6924d6098a93f93fc07213c 100644 (file)
 /* Offset 0x10: Extended Port Control Command */
 #define MV88E6393X_PORT_EPC_CMD                0x10
 #define MV88E6393X_PORT_EPC_CMD_BUSY   0x8000
-#define MV88E6393X_PORT_EPC_CMD_WRITE  0x0300
+#define MV88E6393X_PORT_EPC_CMD_WRITE  0x3000
 #define MV88E6393X_PORT_EPC_INDEX_PORT_ETYPE   0x02
 
 /* Offset 0x11: Extended Port Control Data */
index 919027cf20124350e31fcc9ca13f0a19071fee11..c37d2e5372302bd62a9f3c14cd0c768033946ec8 100644 (file)
@@ -120,6 +120,22 @@ static void a5psw_port_mgmtfwd_set(struct a5psw *a5psw, int port, bool enable)
        a5psw_port_pattern_set(a5psw, port, A5PSW_PATTERN_MGMTFWD, enable);
 }
 
+static void a5psw_port_tx_enable(struct a5psw *a5psw, int port, bool enable)
+{
+       u32 mask = A5PSW_PORT_ENA_TX(port);
+       u32 reg = enable ? mask : 0;
+
+       /* Even though the port TX is disabled through TXENA bit in the
+        * PORT_ENA register, it can still send BPDUs. This depends on the tag
+        * configuration added when sending packets from the CPU port to the
+        * switch port. Indeed, when using forced forwarding without filtering,
+        * even disabled ports will be able to send packets that are tagged.
+        * This allows to implement STP support when ports are in a state where
+        * forwarding traffic should be stopped but BPDUs should still be sent.
+        */
+       a5psw_reg_rmw(a5psw, A5PSW_PORT_ENA, mask, reg);
+}
+
 static void a5psw_port_enable_set(struct a5psw *a5psw, int port, bool enable)
 {
        u32 port_ena = 0;
@@ -292,6 +308,22 @@ static int a5psw_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
        return 0;
 }
 
+static void a5psw_port_learning_set(struct a5psw *a5psw, int port, bool learn)
+{
+       u32 mask = A5PSW_INPUT_LEARN_DIS(port);
+       u32 reg = !learn ? mask : 0;
+
+       a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, mask, reg);
+}
+
+static void a5psw_port_rx_block_set(struct a5psw *a5psw, int port, bool block)
+{
+       u32 mask = A5PSW_INPUT_LEARN_BLOCK(port);
+       u32 reg = block ? mask : 0;
+
+       a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, mask, reg);
+}
+
 static void a5psw_flooding_set_resolution(struct a5psw *a5psw, int port,
                                          bool set)
 {
@@ -308,6 +340,14 @@ static void a5psw_flooding_set_resolution(struct a5psw *a5psw, int port,
                a5psw_reg_writel(a5psw, offsets[i], a5psw->bridged_ports);
 }
 
+static void a5psw_port_set_standalone(struct a5psw *a5psw, int port,
+                                     bool standalone)
+{
+       a5psw_port_learning_set(a5psw, port, !standalone);
+       a5psw_flooding_set_resolution(a5psw, port, !standalone);
+       a5psw_port_mgmtfwd_set(a5psw, port, standalone);
+}
+
 static int a5psw_port_bridge_join(struct dsa_switch *ds, int port,
                                  struct dsa_bridge bridge,
                                  bool *tx_fwd_offload,
@@ -323,8 +363,7 @@ static int a5psw_port_bridge_join(struct dsa_switch *ds, int port,
        }
 
        a5psw->br_dev = bridge.dev;
-       a5psw_flooding_set_resolution(a5psw, port, true);
-       a5psw_port_mgmtfwd_set(a5psw, port, false);
+       a5psw_port_set_standalone(a5psw, port, false);
 
        return 0;
 }
@@ -334,8 +373,7 @@ static void a5psw_port_bridge_leave(struct dsa_switch *ds, int port,
 {
        struct a5psw *a5psw = ds->priv;
 
-       a5psw_flooding_set_resolution(a5psw, port, false);
-       a5psw_port_mgmtfwd_set(a5psw, port, true);
+       a5psw_port_set_standalone(a5psw, port, true);
 
        /* No more ports bridged */
        if (a5psw->bridged_ports == BIT(A5PSW_CPU_PORT))
@@ -344,28 +382,35 @@ static void a5psw_port_bridge_leave(struct dsa_switch *ds, int port,
 
 static void a5psw_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
 {
-       u32 mask = A5PSW_INPUT_LEARN_DIS(port) | A5PSW_INPUT_LEARN_BLOCK(port);
+       bool learning_enabled, rx_enabled, tx_enabled;
        struct a5psw *a5psw = ds->priv;
-       u32 reg = 0;
 
        switch (state) {
        case BR_STATE_DISABLED:
        case BR_STATE_BLOCKING:
-               reg |= A5PSW_INPUT_LEARN_DIS(port);
-               reg |= A5PSW_INPUT_LEARN_BLOCK(port);
-               break;
        case BR_STATE_LISTENING:
-               reg |= A5PSW_INPUT_LEARN_DIS(port);
+               rx_enabled = false;
+               tx_enabled = false;
+               learning_enabled = false;
                break;
        case BR_STATE_LEARNING:
-               reg |= A5PSW_INPUT_LEARN_BLOCK(port);
+               rx_enabled = false;
+               tx_enabled = false;
+               learning_enabled = true;
                break;
        case BR_STATE_FORWARDING:
-       default:
+               rx_enabled = true;
+               tx_enabled = true;
+               learning_enabled = true;
                break;
+       default:
+               dev_err(ds->dev, "invalid STP state: %d\n", state);
+               return;
        }
 
-       a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, mask, reg);
+       a5psw_port_learning_set(a5psw, port, learning_enabled);
+       a5psw_port_rx_block_set(a5psw, port, !rx_enabled);
+       a5psw_port_tx_enable(a5psw, port, tx_enabled);
 }
 
 static void a5psw_port_fast_age(struct dsa_switch *ds, int port)
@@ -673,7 +718,7 @@ static int a5psw_setup(struct dsa_switch *ds)
        }
 
        /* Configure management port */
-       reg = A5PSW_CPU_PORT | A5PSW_MGMT_CFG_DISCARD;
+       reg = A5PSW_CPU_PORT | A5PSW_MGMT_CFG_ENABLE;
        a5psw_reg_writel(a5psw, A5PSW_MGMT_CFG, reg);
 
        /* Set pattern 0 to forward all frame to mgmt port */
@@ -722,13 +767,15 @@ static int a5psw_setup(struct dsa_switch *ds)
                if (dsa_port_is_unused(dp))
                        continue;
 
-               /* Enable egress flooding for CPU port */
-               if (dsa_port_is_cpu(dp))
+               /* Enable egress flooding and learning for CPU port */
+               if (dsa_port_is_cpu(dp)) {
                        a5psw_flooding_set_resolution(a5psw, port, true);
+                       a5psw_port_learning_set(a5psw, port, true);
+               }
 
-               /* Enable management forward only for user ports */
+               /* Enable standalone mode for user ports */
                if (dsa_port_is_user(dp))
-                       a5psw_port_mgmtfwd_set(a5psw, port, true);
+                       a5psw_port_set_standalone(a5psw, port, true);
        }
 
        return 0;
index c67abd49c013d356a5d00c293070c4cdde8e1ce9..b869192eef3f71bb224b8308f3f6301e1efa5218 100644 (file)
@@ -19,6 +19,7 @@
 #define A5PSW_PORT_OFFSET(port)                (0x400 * (port))
 
 #define A5PSW_PORT_ENA                 0x8
+#define A5PSW_PORT_ENA_TX(port)                BIT(port)
 #define A5PSW_PORT_ENA_RX_SHIFT                16
 #define A5PSW_PORT_ENA_TX_RX(port)     (BIT((port) + A5PSW_PORT_ENA_RX_SHIFT) | \
                                         BIT(port))
@@ -36,7 +37,7 @@
 #define A5PSW_INPUT_LEARN_BLOCK(p)     BIT(p)
 
 #define A5PSW_MGMT_CFG                 0x20
-#define A5PSW_MGMT_CFG_DISCARD         BIT(7)
+#define A5PSW_MGMT_CFG_ENABLE          BIT(6)
 
 #define A5PSW_MODE_CFG                 0x24
 #define A5PSW_MODE_STATS_RESET         BIT(31)
index d2f4358cc5503e939d1fd23fbb37933bb494aa36..ba3e7aa1a28fb577185be24a6592d37f298e9eef 100644 (file)
@@ -66,8 +66,10 @@ static int max_interrupt_work = 20;
 #include <linux/timer.h>
 #include <linux/ethtool.h>
 #include <linux/bitops.h>
-
 #include <linux/uaccess.h>
+
+#include <net/Space.h>
+
 #include <asm/io.h>
 #include <asm/dma.h>
 
index 82f94b1635bf816150e5f3c4f7d3e71417d81263..5267e9dcd87ef90927e7806206dba7d108e96ddc 100644 (file)
@@ -195,6 +195,7 @@ static int tc589_probe(struct pcmcia_device *link)
 {
        struct el3_private *lp;
        struct net_device *dev;
+       int ret;
 
        dev_dbg(&link->dev, "3c589_attach()\n");
 
@@ -218,7 +219,15 @@ static int tc589_probe(struct pcmcia_device *link)
 
        dev->ethtool_ops = &netdev_ethtool_ops;
 
-       return tc589_config(link);
+       ret = tc589_config(link);
+       if (ret)
+               goto err_free_netdev;
+
+       return 0;
+
+err_free_netdev:
+       free_netdev(dev);
+       return ret;
 }
 
 static void tc589_detach(struct pcmcia_device *link)
index 0a9118b8be0c64b481f8e43988f5a8679c461e5c..bc9c81dc00fd20c37311da008e9d6bc04dc8f864 100644 (file)
@@ -52,6 +52,7 @@ static const char version2[] =
 #include <linux/etherdevice.h>
 #include <linux/jiffies.h>
 #include <linux/platform_device.h>
+#include <net/Space.h>
 
 #include <asm/io.h>
 
index 6e62c37c9400565616fd35a061aece8eb4beca8f..7465650c80780594203516d5a4915a9122d04448 100644 (file)
@@ -66,6 +66,7 @@ static const char version[] =
 #include <linux/isapnp.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <net/Space.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
index 5b00c452bede64a71519d34dfab79a0d50e05f64..119021d41451e88726af07852b587b4d33673efd 100644 (file)
@@ -37,6 +37,7 @@ static const char version[] =
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <net/Space.h>
 
 #include <asm/io.h>
 
index 8971665a4b2ac3adc53de5fd292dfe479deec304..6cf38180cc01934f6252d2dcc4a3b3b9c8fecfe1 100644 (file)
@@ -59,6 +59,7 @@ static const char version[] = "lance.c:v1.16 2006/11/09 dplatt@3do.com, becker@c
 #include <linux/skbuff.h>
 #include <linux/mm.h>
 #include <linux/bitops.h>
+#include <net/Space.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
index 33a9574e9e0434fbdfcfd022b9731329c6fbad8f..32d2c6fac65266baee9bc36477f21418b50f67e0 100644 (file)
@@ -1329,7 +1329,7 @@ static enum xgbe_mode xgbe_phy_status_aneg(struct xgbe_prv_data *pdata)
        return pdata->phy_if.phy_impl.an_outcome(pdata);
 }
 
-static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
+static bool xgbe_phy_status_result(struct xgbe_prv_data *pdata)
 {
        struct ethtool_link_ksettings *lks = &pdata->phy.lks;
        enum xgbe_mode mode;
@@ -1367,8 +1367,13 @@ static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
 
        pdata->phy.duplex = DUPLEX_FULL;
 
-       if (xgbe_set_mode(pdata, mode) && pdata->an_again)
+       if (!xgbe_set_mode(pdata, mode))
+               return false;
+
+       if (pdata->an_again)
                xgbe_phy_reconfig_aneg(pdata);
+
+       return true;
 }
 
 static void xgbe_phy_status(struct xgbe_prv_data *pdata)
@@ -1398,7 +1403,8 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata)
                        return;
                }
 
-               xgbe_phy_status_result(pdata);
+               if (xgbe_phy_status_result(pdata))
+                       return;
 
                if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
                        clear_bit(XGBE_LINK_INIT, &pdata->dev_state);
index f28ffc31df2200660954cbebea08a5e06232b947..eca0c92c0c84d86af22984b5e3ec7dd1f21c7632 100644 (file)
@@ -3450,7 +3450,7 @@ err_clk_disable:
        return ret;
 }
 
-static void bcmgenet_netif_stop(struct net_device *dev)
+static void bcmgenet_netif_stop(struct net_device *dev, bool stop_phy)
 {
        struct bcmgenet_priv *priv = netdev_priv(dev);
 
@@ -3465,6 +3465,8 @@ static void bcmgenet_netif_stop(struct net_device *dev)
        /* Disable MAC transmit. TX DMA disabled must be done before this */
        umac_enable_set(priv, CMD_TX_EN, false);
 
+       if (stop_phy)
+               phy_stop(dev->phydev);
        bcmgenet_disable_rx_napi(priv);
        bcmgenet_intr_disable(priv);
 
@@ -3485,7 +3487,7 @@ static int bcmgenet_close(struct net_device *dev)
 
        netif_dbg(priv, ifdown, dev, "bcmgenet_close\n");
 
-       bcmgenet_netif_stop(dev);
+       bcmgenet_netif_stop(dev, false);
 
        /* Really kill the PHY state machine and disconnect from it */
        phy_disconnect(dev->phydev);
@@ -4303,7 +4305,7 @@ static int bcmgenet_suspend(struct device *d)
 
        netif_device_detach(dev);
 
-       bcmgenet_netif_stop(dev);
+       bcmgenet_netif_stop(dev, true);
 
        if (!device_may_wakeup(d))
                phy_suspend(dev->phydev);
index 06a0c00af99c7562d334c4e391686233267b4671..276c32c3926a7d9ae12991cacf2ae1ee87e0f0d5 100644 (file)
@@ -72,6 +72,8 @@
 #include <linux/gfp.h>
 #include <linux/io.h>
 
+#include <net/Space.h>
+
 #include <asm/irq.h>
 #include <linux/atomic.h>
 #if ALLOW_DMA
index 42ec6ca3bf035a87e11a7dfc92b19483e843cae1..38e5b5abe067cf6ce8a2bf8144c9dd7245ae2e8c 100644 (file)
@@ -3798,7 +3798,6 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
        entries_free = fec_enet_get_free_txdesc_num(txq);
        if (entries_free < MAX_SKB_FRAGS + 1) {
                netdev_err(fep->netdev, "NOT enough BD for SG!\n");
-               xdp_return_frame(frame);
                return NETDEV_TX_BUSY;
        }
 
@@ -3835,6 +3834,11 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
        index = fec_enet_get_bd_index(last_bdp, &txq->bd);
        txq->tx_skbuff[index] = NULL;
 
+       /* Make sure the updates to rest of the descriptor are performed before
+        * transferring ownership.
+        */
+       dma_wmb();
+
        /* Send it on its way.  Tell FEC it's ready, interrupt when done,
         * it's the last BD of the frame, and to put the CRC on the end.
         */
@@ -3844,8 +3848,14 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
        /* If this was the last BD in the ring, start at the beginning again. */
        bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd);
 
+       /* Make sure the update to bdp are performed before txq->bd.cur. */
+       dma_wmb();
+
        txq->bd.cur = bdp;
 
+       /* Trigger transmission start */
+       writel(0, txq->bd.reg_desc_active);
+
        return 0;
 }
 
@@ -3874,12 +3884,6 @@ static int fec_enet_xdp_xmit(struct net_device *dev,
                sent_frames++;
        }
 
-       /* Make sure the update to bdp and tx_skbuff are performed. */
-       wmb();
-
-       /* Trigger transmission start */
-       writel(0, txq->bd.reg_desc_active);
-
        __netif_tx_unlock(nq);
 
        return sent_frames;
@@ -4478,9 +4482,11 @@ fec_drv_remove(struct platform_device *pdev)
        struct device_node *np = pdev->dev.of_node;
        int ret;
 
-       ret = pm_runtime_resume_and_get(&pdev->dev);
+       ret = pm_runtime_get_sync(&pdev->dev);
        if (ret < 0)
-               return ret;
+               dev_err(&pdev->dev,
+                       "Failed to resume device in remove callback (%pe)\n",
+                       ERR_PTR(ret));
 
        cancel_work_sync(&fep->tx_timeout_work);
        fec_ptp_stop(pdev);
@@ -4493,8 +4499,13 @@ fec_drv_remove(struct platform_device *pdev)
                of_phy_deregister_fixed_link(np);
        of_node_put(fep->phy_node);
 
-       clk_disable_unprepare(fep->clk_ahb);
-       clk_disable_unprepare(fep->clk_ipg);
+       /* After pm_runtime_get_sync() failed, the clks are still off, so skip
+        * disabling them again.
+        */
+       if (ret >= 0) {
+               clk_disable_unprepare(fep->clk_ahb);
+               clk_disable_unprepare(fep->clk_ipg);
+       }
        pm_runtime_put_noidle(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
 
index 57ce74315eba4cbf0e18806f72d001b9f2e10f5b..caa00c72aeebaac083b22e11fb8b4094e8e62eab 100644 (file)
@@ -294,19 +294,6 @@ static int gve_napi_poll_dqo(struct napi_struct *napi, int budget)
        bool reschedule = false;
        int work_done = 0;
 
-       /* Clear PCI MSI-X Pending Bit Array (PBA)
-        *
-        * This bit is set if an interrupt event occurs while the vector is
-        * masked. If this bit is set and we reenable the interrupt, it will
-        * fire again. Since we're just about to poll the queue state, we don't
-        * need it to fire again.
-        *
-        * Under high softirq load, it's possible that the interrupt condition
-        * is triggered twice before we got the chance to process it.
-        */
-       gve_write_irq_doorbell_dqo(priv, block,
-                                  GVE_ITR_NO_UPDATE_DQO | GVE_ITR_CLEAR_PBA_BIT_DQO);
-
        if (block->tx)
                reschedule |= gve_tx_poll_dqo(block, /*do_clean=*/true);
 
index cbbab5b2b402b70d4b1a2f680fa8b773c1cb7744..b85c412683ddc227ad06bc71b5357f80e9d50c93 100644 (file)
@@ -331,9 +331,25 @@ static int hclge_comm_cmd_csq_done(struct hclge_comm_hw *hw)
        return head == hw->cmq.csq.next_to_use;
 }
 
-static void hclge_comm_wait_for_resp(struct hclge_comm_hw *hw,
+static u32 hclge_get_cmdq_tx_timeout(u16 opcode, u32 tx_timeout)
+{
+       static const struct hclge_cmdq_tx_timeout_map cmdq_tx_timeout_map[] = {
+               {HCLGE_OPC_CFG_RST_TRIGGER, HCLGE_COMM_CMDQ_TX_TIMEOUT_500MS},
+       };
+       u32 i;
+
+       for (i = 0; i < ARRAY_SIZE(cmdq_tx_timeout_map); i++)
+               if (cmdq_tx_timeout_map[i].opcode == opcode)
+                       return cmdq_tx_timeout_map[i].tx_timeout;
+
+       return tx_timeout;
+}
+
+static void hclge_comm_wait_for_resp(struct hclge_comm_hw *hw, u16 opcode,
                                     bool *is_completed)
 {
+       u32 cmdq_tx_timeout = hclge_get_cmdq_tx_timeout(opcode,
+                                                       hw->cmq.tx_timeout);
        u32 timeout = 0;
 
        do {
@@ -343,7 +359,7 @@ static void hclge_comm_wait_for_resp(struct hclge_comm_hw *hw,
                }
                udelay(1);
                timeout++;
-       } while (timeout < hw->cmq.tx_timeout);
+       } while (timeout < cmdq_tx_timeout);
 }
 
 static int hclge_comm_cmd_convert_err_code(u16 desc_ret)
@@ -407,7 +423,8 @@ static int hclge_comm_cmd_check_result(struct hclge_comm_hw *hw,
         * if multi descriptors to be sent, use the first one to check
         */
        if (HCLGE_COMM_SEND_SYNC(le16_to_cpu(desc->flag)))
-               hclge_comm_wait_for_resp(hw, &is_completed);
+               hclge_comm_wait_for_resp(hw, le16_to_cpu(desc->opcode),
+                                        &is_completed);
 
        if (!is_completed)
                ret = -EBADE;
@@ -529,7 +546,7 @@ int hclge_comm_cmd_queue_init(struct pci_dev *pdev, struct hclge_comm_hw *hw)
        cmdq->crq.desc_num = HCLGE_COMM_NIC_CMQ_DESC_NUM;
 
        /* Setup Tx write back timeout */
-       cmdq->tx_timeout = HCLGE_COMM_CMDQ_TX_TIMEOUT;
+       cmdq->tx_timeout = HCLGE_COMM_CMDQ_TX_TIMEOUT_DEFAULT;
 
        /* Setup queue rings */
        ret = hclge_comm_alloc_cmd_queue(hw, HCLGE_COMM_TYPE_CSQ);
index de72ecbfd5ad8549653dc730e986a1b3a0f37af9..18f1b4bf362da9b83f4fe9fd8d4885842ff4d7dc 100644 (file)
@@ -54,7 +54,8 @@
 #define HCLGE_COMM_NIC_SW_RST_RDY              BIT(HCLGE_COMM_NIC_SW_RST_RDY_B)
 #define HCLGE_COMM_NIC_CMQ_DESC_NUM_S          3
 #define HCLGE_COMM_NIC_CMQ_DESC_NUM            1024
-#define HCLGE_COMM_CMDQ_TX_TIMEOUT             30000
+#define HCLGE_COMM_CMDQ_TX_TIMEOUT_DEFAULT     30000
+#define HCLGE_COMM_CMDQ_TX_TIMEOUT_500MS       500000
 
 enum hclge_opcode_type {
        /* Generic commands */
@@ -360,6 +361,11 @@ struct hclge_comm_caps_bit_map {
        u16 local_bit;
 };
 
+struct hclge_cmdq_tx_timeout_map {
+       u32 opcode;
+       u32 tx_timeout;
+};
+
 struct hclge_comm_firmware_compat_cmd {
        __le32 compat;
        u8 rsv[20];
index 4c3e90a1c4d07368ad4757926aeced0ea8832808..d385ffc21876601d94022104c545fa95be60ddcb 100644 (file)
@@ -130,7 +130,7 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = {
                .name = "tx_bd_queue",
                .cmd = HNAE3_DBG_CMD_TX_BD,
                .dentry = HNS3_DBG_DENTRY_TX_BD,
-               .buf_len = HNS3_DBG_READ_LEN_4MB,
+               .buf_len = HNS3_DBG_READ_LEN_5MB,
                .init = hns3_dbg_bd_file_init,
        },
        {
index 97578eabb7d8b7a2defc1ac1422bb77f29b1f6bf..4a5ef8a90a1046883416f00648e5f47ff2a42721 100644 (file)
@@ -10,6 +10,7 @@
 #define HNS3_DBG_READ_LEN_128KB        0x20000
 #define HNS3_DBG_READ_LEN_1MB  0x100000
 #define HNS3_DBG_READ_LEN_4MB  0x400000
+#define HNS3_DBG_READ_LEN_5MB  0x500000
 #define HNS3_DBG_WRITE_LEN     1024
 
 #define HNS3_DBG_DATA_STR_LEN  32
index 4fb5406c1951dce7095010a4e7c7528d8e59091b..2689b108f7df7b4e94efdeec45135b8b297a15d7 100644 (file)
@@ -8053,12 +8053,15 @@ static void hclge_ae_stop(struct hnae3_handle *handle)
        /* If it is not PF reset or FLR, the firmware will disable the MAC,
         * so it only need to stop phy here.
         */
-       if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state) &&
-           hdev->reset_type != HNAE3_FUNC_RESET &&
-           hdev->reset_type != HNAE3_FLR_RESET) {
-               hclge_mac_stop_phy(hdev);
-               hclge_update_link_status(hdev);
-               return;
+       if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) {
+               hclge_pfc_pause_en_cfg(hdev, HCLGE_PFC_TX_RX_DISABLE,
+                                      HCLGE_PFC_DISABLE);
+               if (hdev->reset_type != HNAE3_FUNC_RESET &&
+                   hdev->reset_type != HNAE3_FLR_RESET) {
+                       hclge_mac_stop_phy(hdev);
+                       hclge_update_link_status(hdev);
+                       return;
+               }
        }
 
        hclge_reset_tqp(handle);
index 4a33f65190e2b431ea201c42ce81b86ed5c99d54..922c0da3660c7b9ff466828c1896676da7206ca2 100644 (file)
@@ -171,8 +171,8 @@ int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx)
        return hclge_cmd_send(&hdev->hw, &desc, 1);
 }
 
-static int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap,
-                                 u8 pfc_bitmap)
+int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap,
+                          u8 pfc_bitmap)
 {
        struct hclge_desc desc;
        struct hclge_pfc_en_cmd *pfc = (struct hclge_pfc_en_cmd *)desc.data;
index 68f28a98e380bc529b1808e39d74a679decbbc43..dd6f1fd486cf24d326c808e4d902732ca9329cf7 100644 (file)
@@ -164,6 +164,9 @@ struct hclge_bp_to_qs_map_cmd {
        u32 rsvd1;
 };
 
+#define HCLGE_PFC_DISABLE      0
+#define HCLGE_PFC_TX_RX_DISABLE        0
+
 struct hclge_pfc_en_cmd {
        u8 tx_rx_en_bitmap;
        u8 pri_en_bitmap;
@@ -235,6 +238,8 @@ void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc);
 void hclge_tm_pfc_info_update(struct hclge_dev *hdev);
 int hclge_tm_dwrr_cfg(struct hclge_dev *hdev);
 int hclge_tm_init_hw(struct hclge_dev *hdev, bool init);
+int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap,
+                          u8 pfc_bitmap);
 int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx);
 int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr);
 void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats);
index f240462503419035c7b2e733434b66969372adee..dd08989a4c7c1d122955c8b2839f07b32ff2283d 100644 (file)
@@ -1436,7 +1436,10 @@ static int hclgevf_reset_wait(struct hclgevf_dev *hdev)
         * might happen in case reset assertion was made by PF. Yes, this also
         * means we might end up waiting bit more even for VF reset.
         */
-       msleep(5000);
+       if (hdev->reset_type == HNAE3_VF_FULL_RESET)
+               msleep(5000);
+       else
+               msleep(500);
 
        return 0;
 }
index 9afbbdac35903f1ae018c00fe28213ece3227d3f..7c0578b5457b96bd9d4b4f53a19f64cb4ca8560b 100644 (file)
@@ -2238,11 +2238,6 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                iavf_process_config(adapter);
                adapter->flags |= IAVF_FLAG_SETUP_NETDEV_FEATURES;
 
-               /* Request VLAN offload settings */
-               if (VLAN_V2_ALLOWED(adapter))
-                       iavf_set_vlan_offload_features(adapter, 0,
-                                                      netdev->features);
-
                iavf_set_queue_vlan_tag_loc(adapter);
 
                was_mac_changed = !ether_addr_equal(netdev->dev_addr,
index c6d4926f0fcf50df80bec065e8b150ffe45b0831..850db8e0e6b0021ab0f70718634c4dfb496f0928 100644 (file)
@@ -932,10 +932,9 @@ ice_tx_prepare_vlan_flags_dcb(struct ice_tx_ring *tx_ring,
        if ((first->tx_flags & ICE_TX_FLAGS_HW_VLAN ||
             first->tx_flags & ICE_TX_FLAGS_HW_OUTER_SINGLE_VLAN) ||
            skb->priority != TC_PRIO_CONTROL) {
-               first->tx_flags &= ~ICE_TX_FLAGS_VLAN_PR_M;
+               first->vid &= ~VLAN_PRIO_MASK;
                /* Mask the lower 3 bits to set the 802.1p priority */
-               first->tx_flags |= (skb->priority & 0x7) <<
-                                  ICE_TX_FLAGS_VLAN_PR_S;
+               first->vid |= (skb->priority << VLAN_PRIO_SHIFT) & VLAN_PRIO_MASK;
                /* if this is not already set it means a VLAN 0 + priority needs
                 * to be offloaded
                 */
index 450317dfcca7360cb1acdfca470bd4295d11e3db..11ae0e41f518a13b1c77c56a15404338495b746a 100644 (file)
@@ -2745,6 +2745,8 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)
                        goto unroll_vector_base;
 
                ice_vsi_map_rings_to_vectors(vsi);
+               vsi->stat_offsets_loaded = false;
+
                if (ice_is_xdp_ena_vsi(vsi)) {
                        ret = ice_vsi_determine_xdp_res(vsi);
                        if (ret)
@@ -2793,6 +2795,9 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)
                ret = ice_vsi_alloc_ring_stats(vsi);
                if (ret)
                        goto unroll_vector_base;
+
+               vsi->stat_offsets_loaded = false;
+
                /* Do not exit if configuring RSS had an issue, at least
                 * receive traffic on first queue. Hence no need to capture
                 * return value
index f1dca59bd8449ea91706451c3226fe4ff912cc40..588ad8696756defb6154022fe4fc9b7c75eed366 100644 (file)
@@ -1171,7 +1171,7 @@ int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena)
        if (!vf)
                return -EINVAL;
 
-       ret = ice_check_vf_ready_for_cfg(vf);
+       ret = ice_check_vf_ready_for_reset(vf);
        if (ret)
                goto out_put_vf;
 
@@ -1286,7 +1286,7 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
                goto out_put_vf;
        }
 
-       ret = ice_check_vf_ready_for_cfg(vf);
+       ret = ice_check_vf_ready_for_reset(vf);
        if (ret)
                goto out_put_vf;
 
@@ -1340,7 +1340,7 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
                return -EOPNOTSUPP;
        }
 
-       ret = ice_check_vf_ready_for_cfg(vf);
+       ret = ice_check_vf_ready_for_reset(vf);
        if (ret)
                goto out_put_vf;
 
@@ -1653,7 +1653,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
        if (!vf)
                return -EINVAL;
 
-       ret = ice_check_vf_ready_for_cfg(vf);
+       ret = ice_check_vf_ready_for_reset(vf);
        if (ret)
                goto out_put_vf;
 
index 4fcf2d07eb853b10be4b5b483b33e0f95db9446a..52d0a126eb6161852bb96457b9025a35e5641578 100644 (file)
@@ -1152,11 +1152,11 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
        unsigned int total_rx_bytes = 0, total_rx_pkts = 0;
        unsigned int offset = rx_ring->rx_offset;
        struct xdp_buff *xdp = &rx_ring->xdp;
+       u32 cached_ntc = rx_ring->first_desc;
        struct ice_tx_ring *xdp_ring = NULL;
        struct bpf_prog *xdp_prog = NULL;
        u32 ntc = rx_ring->next_to_clean;
        u32 cnt = rx_ring->count;
-       u32 cached_ntc = ntc;
        u32 xdp_xmit = 0;
        u32 cached_ntu;
        bool failure;
@@ -1664,8 +1664,7 @@ ice_tx_map(struct ice_tx_ring *tx_ring, struct ice_tx_buf *first,
 
        if (first->tx_flags & ICE_TX_FLAGS_HW_VLAN) {
                td_cmd |= (u64)ICE_TX_DESC_CMD_IL2TAG1;
-               td_tag = (first->tx_flags & ICE_TX_FLAGS_VLAN_M) >>
-                         ICE_TX_FLAGS_VLAN_S;
+               td_tag = first->vid;
        }
 
        dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE);
@@ -1998,7 +1997,7 @@ ice_tx_prepare_vlan_flags(struct ice_tx_ring *tx_ring, struct ice_tx_buf *first)
         * VLAN offloads exclusively so we only care about the VLAN ID here
         */
        if (skb_vlan_tag_present(skb)) {
-               first->tx_flags |= skb_vlan_tag_get(skb) << ICE_TX_FLAGS_VLAN_S;
+               first->vid = skb_vlan_tag_get(skb);
                if (tx_ring->flags & ICE_TX_FLAGS_RING_VLAN_L2TAG2)
                        first->tx_flags |= ICE_TX_FLAGS_HW_OUTER_SINGLE_VLAN;
                else
@@ -2388,8 +2387,7 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
                offload.cd_qw1 |= (u64)(ICE_TX_DESC_DTYPE_CTX |
                                        (ICE_TX_CTX_DESC_IL2TAG2 <<
                                        ICE_TXD_CTX_QW1_CMD_S));
-               offload.cd_l2tag2 = (first->tx_flags & ICE_TX_FLAGS_VLAN_M) >>
-                       ICE_TX_FLAGS_VLAN_S;
+               offload.cd_l2tag2 = first->vid;
        }
 
        /* set up TSO offload */
index fff0efe28373affc555994c335f3c412d8844cdb..166413fc33f48f71a459009819a75d000601b03f 100644 (file)
@@ -127,10 +127,6 @@ static inline int ice_skb_pad(void)
 #define ICE_TX_FLAGS_IPV6      BIT(6)
 #define ICE_TX_FLAGS_TUNNEL    BIT(7)
 #define ICE_TX_FLAGS_HW_OUTER_SINGLE_VLAN      BIT(8)
-#define ICE_TX_FLAGS_VLAN_M    0xffff0000
-#define ICE_TX_FLAGS_VLAN_PR_M 0xe0000000
-#define ICE_TX_FLAGS_VLAN_PR_S 29
-#define ICE_TX_FLAGS_VLAN_S    16
 
 #define ICE_XDP_PASS           0
 #define ICE_XDP_CONSUMED       BIT(0)
@@ -182,8 +178,9 @@ struct ice_tx_buf {
                unsigned int gso_segs;
                unsigned int nr_frags;  /* used for mbuf XDP */
        };
-       u32 type:16;                    /* &ice_tx_buf_type */
-       u32 tx_flags:16;
+       u32 tx_flags:12;
+       u32 type:4;                     /* &ice_tx_buf_type */
+       u32 vid:16;
        DEFINE_DMA_UNMAP_LEN(len);
        DEFINE_DMA_UNMAP_ADDR(dma);
 };
index 89fd6982df0934b53b27a538856bdc7b3c30c75b..bf74a2f3a4f8c3d8ebf5a1492782ec06c79b3ddd 100644 (file)
@@ -185,6 +185,25 @@ int ice_check_vf_ready_for_cfg(struct ice_vf *vf)
        return 0;
 }
 
+/**
+ * ice_check_vf_ready_for_reset - check if VF is ready to be reset
+ * @vf: VF to check if it's ready to be reset
+ *
+ * The purpose of this function is to ensure that the VF is not in reset,
+ * disabled, and is both initialized and active, thus enabling us to safely
+ * initialize another reset.
+ */
+int ice_check_vf_ready_for_reset(struct ice_vf *vf)
+{
+       int ret;
+
+       ret = ice_check_vf_ready_for_cfg(vf);
+       if (!ret && !test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
+               ret = -EAGAIN;
+
+       return ret;
+}
+
 /**
  * ice_trigger_vf_reset - Reset a VF on HW
  * @vf: pointer to the VF structure
index e3cda6fb71ab1e61221557abb0692ad9c1b19d14..a38ef00a367942b52f45c8b9d87abe4d95f52fef 100644 (file)
@@ -215,6 +215,7 @@ u16 ice_get_num_vfs(struct ice_pf *pf);
 struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf);
 bool ice_is_vf_disabled(struct ice_vf *vf);
 int ice_check_vf_ready_for_cfg(struct ice_vf *vf);
+int ice_check_vf_ready_for_reset(struct ice_vf *vf);
 void ice_set_vf_state_dis(struct ice_vf *vf);
 bool ice_is_any_vf_in_unicast_promisc(struct ice_pf *pf);
 void
index 97243c616d5d6d939196fcca9b4ea04724dbbf0a..f4a524f80b110f1dc3d60d706eedb31a20740000 100644 (file)
@@ -3955,6 +3955,7 @@ error_handler:
                ice_vc_notify_vf_link_state(vf);
                break;
        case VIRTCHNL_OP_RESET_VF:
+               clear_bit(ICE_VF_STATE_ACTIVE, vf->vf_states);
                ops->reset_vf(vf);
                break;
        case VIRTCHNL_OP_ADD_ETH_ADDR:
index 205d577bdbbaad57af46694858f6d4f28617e3a7..caf91c6f52b4d03cabef2cc7fe6a4d545a0cc899 100644 (file)
@@ -426,7 +426,7 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value)
 static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
 {
        u32 hash_value, hash_mask;
-       u8 bit_shift = 0;
+       u8 bit_shift = 1;
 
        /* Register count multiplied by bits per register */
        hash_mask = (hw->mac.mta_reg_count * 32) - 1;
@@ -434,7 +434,7 @@ static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
        /* For a mc_filter_type of 0, bit_shift is the number of left-shifts
         * where 0xFF would still fall within the hash mask.
         */
-       while (hash_mask >> bit_shift != 0xFF)
+       while (hash_mask >> bit_shift != 0xFF && bit_shift < 4)
                bit_shift++;
 
        /* The portion of the address that is used for the hash table
index 7045fedfd73a04ba63cdb2d657754722f5291de8..7af223b0a37f51e129c5d28d9d500262a4c0b620 100644 (file)
@@ -652,9 +652,7 @@ static void otx2_sqe_add_ext(struct otx2_nic *pfvf, struct otx2_snd_queue *sq,
                                htons(ext->lso_sb - skb_network_offset(skb));
                } else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
                        ext->lso_format = pfvf->hw.lso_tsov6_idx;
-
-                       ipv6_hdr(skb)->payload_len =
-                               htons(ext->lso_sb - skb_network_offset(skb));
+                       ipv6_hdr(skb)->payload_len = htons(tcp_hdrlen(skb));
                } else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
                        __be16 l3_proto = vlan_get_protocol(skb);
                        struct udphdr *udph = udp_hdr(skb);
index a75fd072082c6e415043398a8293323c246ac4a1..834c644b67db51b69724d4b8671f3bb65821e7b0 100644 (file)
@@ -3269,18 +3269,14 @@ static int mtk_open(struct net_device *dev)
                        eth->dsa_meta[i] = md_dst;
                }
        } else {
-               /* Hardware special tag parsing needs to be disabled if at least
-                * one MAC does not use DSA.
+               /* Hardware DSA untagging and VLAN RX offloading need to be
+                * disabled if at least one MAC does not use DSA.
                 */
                u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
 
                val &= ~MTK_CDMP_STAG_EN;
                mtk_w32(eth, val, MTK_CDMP_IG_CTRL);
 
-               val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
-               val &= ~MTK_CDMQ_STAG_EN;
-               mtk_w32(eth, val, MTK_CDMQ_IG_CTRL);
-
                mtk_w32(eth, 0, MTK_CDMP_EG_CTRL);
        }
 
index 4c205afbd2309628eda5fe356fe4b7abb27eb660..985cff910f30c55a411340898da7ceca803f0fb6 100644 (file)
@@ -654,7 +654,7 @@ __mtk_wed_detach(struct mtk_wed_device *dev)
                                           BIT(hw->index), BIT(hw->index));
        }
 
-       if (!hw_list[!hw->index]->wed_dev &&
+       if ((!hw_list[!hw->index] || !hw_list[!hw->index]->wed_dev) &&
            hw->eth->dma_dev != hw->eth->dev)
                mtk_eth_set_dma_device(hw->eth, hw->eth->dev);
 
index d53de39539a8fd90d455fbe83f87dba0225dde14..d532883b42d7c30bf2f1230097a1cd55d46e4cf4 100644 (file)
@@ -1920,9 +1920,10 @@ static void mlx5_cmd_err_trace(struct mlx5_core_dev *dev, u16 opcode, u16 op_mod
 static void cmd_status_log(struct mlx5_core_dev *dev, u16 opcode, u8 status,
                           u32 syndrome, int err)
 {
+       const char *namep = mlx5_command_str(opcode);
        struct mlx5_cmd_stats *stats;
 
-       if (!err)
+       if (!err || !(strcmp(namep, "unknown command opcode")))
                return;
 
        stats = &dev->cmd.stats[opcode];
index f40497823e65fada81f0d289e0b4c68842ffc940..7c0f2adbea000d2453add53348a48c49ccc75110 100644 (file)
@@ -490,7 +490,7 @@ static void poll_trace(struct mlx5_fw_tracer *tracer,
                                (u64)timestamp_low;
                break;
        default:
-               if (tracer_event->event_id >= tracer->str_db.first_string_trace ||
+               if (tracer_event->event_id >= tracer->str_db.first_string_trace &&
                    tracer_event->event_id <= tracer->str_db.first_string_trace +
                                              tracer->str_db.num_string_trace) {
                        tracer_event->type = TRACER_EVENT_TYPE_STRING;
index b8987a404d7526d2f6fe3cd48c0a5f94e22d9aee..8e999f238194812bb44e5b57e1f3b22cf08c67dd 100644 (file)
@@ -327,6 +327,7 @@ struct mlx5e_params {
        unsigned int sw_mtu;
        int hard_mtu;
        bool ptp_rx;
+       __be32 terminate_lkey_be;
 };
 
 static inline u8 mlx5e_get_dcb_num_tc(struct mlx5e_params *params)
index 7ac1ad9c46de0352a0a323f815f8a0b28f2281d2..7e8e96cc5cd083e220e36334dd499220f2ed542a 100644 (file)
@@ -51,7 +51,7 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
        if (err)
                goto out;
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
                buffer = MLX5_ADDR_OF(pbmc_reg, out, buffer[i]);
                port_buffer->buffer[i].lossy =
                        MLX5_GET(bufferx_reg, buffer, lossy);
@@ -73,14 +73,24 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
                          port_buffer->buffer[i].lossy);
        }
 
-       port_buffer->headroom_size = total_used;
+       port_buffer->internal_buffers_size = 0;
+       for (i = MLX5E_MAX_NETWORK_BUFFER; i < MLX5E_TOTAL_BUFFERS; i++) {
+               buffer = MLX5_ADDR_OF(pbmc_reg, out, buffer[i]);
+               port_buffer->internal_buffers_size +=
+                       MLX5_GET(bufferx_reg, buffer, size) * port_buff_cell_sz;
+       }
+
        port_buffer->port_buffer_size =
                MLX5_GET(pbmc_reg, out, port_buffer_size) * port_buff_cell_sz;
-       port_buffer->spare_buffer_size =
-               port_buffer->port_buffer_size - total_used;
-
-       mlx5e_dbg(HW, priv, "total buffer size=%d, spare buffer size=%d\n",
-                 port_buffer->port_buffer_size,
+       port_buffer->headroom_size = total_used;
+       port_buffer->spare_buffer_size = port_buffer->port_buffer_size -
+                                        port_buffer->internal_buffers_size -
+                                        port_buffer->headroom_size;
+
+       mlx5e_dbg(HW, priv,
+                 "total buffer size=%u, headroom buffer size=%u, internal buffers size=%u, spare buffer size=%u\n",
+                 port_buffer->port_buffer_size, port_buffer->headroom_size,
+                 port_buffer->internal_buffers_size,
                  port_buffer->spare_buffer_size);
 out:
        kfree(out);
@@ -206,11 +216,11 @@ static int port_update_pool_cfg(struct mlx5_core_dev *mdev,
        if (!MLX5_CAP_GEN(mdev, sbcam_reg))
                return 0;
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++)
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++)
                lossless_buff_count += ((port_buffer->buffer[i].size) &&
                                       (!(port_buffer->buffer[i].lossy)));
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
                p = select_sbcm_params(&port_buffer->buffer[i], lossless_buff_count);
                err = mlx5e_port_set_sbcm(mdev, 0, i,
                                          MLX5_INGRESS_DIR,
@@ -293,7 +303,7 @@ static int port_set_buffer(struct mlx5e_priv *priv,
        if (err)
                goto out;
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
                void *buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]);
                u64 size = port_buffer->buffer[i].size;
                u64 xoff = port_buffer->buffer[i].xoff;
@@ -351,7 +361,7 @@ static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer,
 {
        int i;
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
                if (port_buffer->buffer[i].lossy) {
                        port_buffer->buffer[i].xoff = 0;
                        port_buffer->buffer[i].xon  = 0;
@@ -408,7 +418,7 @@ static int update_buffer_lossy(struct mlx5_core_dev *mdev,
        int err;
        int i;
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
                prio_count = 0;
                lossy_count = 0;
 
@@ -432,11 +442,11 @@ static int update_buffer_lossy(struct mlx5_core_dev *mdev,
        }
 
        if (changed) {
-               err = port_update_pool_cfg(mdev, port_buffer);
+               err = update_xoff_threshold(port_buffer, xoff, max_mtu, port_buff_cell_sz);
                if (err)
                        return err;
 
-               err = update_xoff_threshold(port_buffer, xoff, max_mtu, port_buff_cell_sz);
+               err = port_update_pool_cfg(mdev, port_buffer);
                if (err)
                        return err;
 
@@ -515,7 +525,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
 
        if (change & MLX5E_PORT_BUFFER_PRIO2BUFFER) {
                update_prio2buffer = true;
-               for (i = 0; i < MLX5E_MAX_BUFFER; i++)
+               for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++)
                        mlx5e_dbg(HW, priv, "%s: requested to map prio[%d] to buffer %d\n",
                                  __func__, i, prio2buffer[i]);
 
@@ -530,7 +540,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
        }
 
        if (change & MLX5E_PORT_BUFFER_SIZE) {
-               for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+               for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
                        mlx5e_dbg(HW, priv, "%s: buffer[%d]=%d\n", __func__, i, buffer_size[i]);
                        if (!port_buffer.buffer[i].lossy && !buffer_size[i]) {
                                mlx5e_dbg(HW, priv, "%s: lossless buffer[%d] size cannot be zero\n",
@@ -544,7 +554,9 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
 
                mlx5e_dbg(HW, priv, "%s: total buffer requested=%d\n", __func__, total_used);
 
-               if (total_used > port_buffer.port_buffer_size)
+               if (total_used > port_buffer.headroom_size &&
+                   (total_used - port_buffer.headroom_size) >
+                           port_buffer.spare_buffer_size)
                        return -EINVAL;
 
                update_buffer = true;
index a6ef118de758f88591181d521d83cd2493a08bda..f4a19ffbb641c07b82291091e4f67f8524378e82 100644 (file)
@@ -35,7 +35,8 @@
 #include "en.h"
 #include "port.h"
 
-#define MLX5E_MAX_BUFFER 8
+#define MLX5E_MAX_NETWORK_BUFFER 8
+#define MLX5E_TOTAL_BUFFERS 10
 #define MLX5E_DEFAULT_CABLE_LEN 7 /* 7 meters */
 
 #define MLX5_BUFFER_SUPPORTED(mdev) (MLX5_CAP_GEN(mdev, pcam_reg) && \
@@ -60,8 +61,9 @@ struct mlx5e_bufferx_reg {
 struct mlx5e_port_buffer {
        u32                       port_buffer_size;
        u32                       spare_buffer_size;
-       u32                       headroom_size;
-       struct mlx5e_bufferx_reg  buffer[MLX5E_MAX_BUFFER];
+       u32                       headroom_size;          /* Buffers 0-7 */
+       u32                       internal_buffers_size;  /* Buffers 8-9 */
+       struct mlx5e_bufferx_reg  buffer[MLX5E_MAX_NETWORK_BUFFER];
 };
 
 int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
index eb5abd0e55d9060ae62ea7542eeb2b111128c4ab..3cbebfba582bdbce79741c4c7d798dd13846af64 100644 (file)
@@ -175,6 +175,8 @@ static bool mlx5e_ptp_poll_ts_cq(struct mlx5e_cq *cq, int budget)
        /* ensure cq space is freed before enabling more cqes */
        wmb();
 
+       mlx5e_txqsq_wake(&ptpsq->txqsq);
+
        return work_done == budget;
 }
 
index fc923a99b6a483d5eaddba1f01c76d66549b74a3..0380a04c3691cbc72d13c873886a4ffd3ec96d01 100644 (file)
@@ -84,7 +84,7 @@ mlx5e_tc_act_init_parse_state(struct mlx5e_tc_act_parse_state *parse_state,
 
 int
 mlx5e_tc_act_post_parse(struct mlx5e_tc_act_parse_state *parse_state,
-                       struct flow_action *flow_action,
+                       struct flow_action *flow_action, int from, int to,
                        struct mlx5_flow_attr *attr,
                        enum mlx5_flow_namespace_type ns_type)
 {
@@ -96,6 +96,11 @@ mlx5e_tc_act_post_parse(struct mlx5e_tc_act_parse_state *parse_state,
        priv = parse_state->flow->priv;
 
        flow_action_for_each(i, act, flow_action) {
+               if (i < from)
+                       continue;
+               else if (i > to)
+                       break;
+
                tc_act = mlx5e_tc_act_get(act->id, ns_type);
                if (!tc_act || !tc_act->post_parse)
                        continue;
index 0e6e1872ac62e291aef03dcafd4d413fcb9d6bb7..d6c12d0ea55ba5458bda9d0ec1199ab2b4891c2d 100644 (file)
@@ -112,7 +112,7 @@ mlx5e_tc_act_init_parse_state(struct mlx5e_tc_act_parse_state *parse_state,
 
 int
 mlx5e_tc_act_post_parse(struct mlx5e_tc_act_parse_state *parse_state,
-                       struct flow_action *flow_action,
+                       struct flow_action *flow_action, int from, int to,
                        struct mlx5_flow_attr *attr,
                        enum mlx5_flow_namespace_type ns_type);
 
index 20c2d2ecaf9356da8d253e8e33a9b45add25bf73..f0c3464f037f4a0d0bc37047e7ace1b50ba8ff6c 100644 (file)
@@ -492,6 +492,19 @@ void mlx5e_encap_put(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e)
        mlx5e_encap_dealloc(priv, e);
 }
 
+static void mlx5e_encap_put_locked(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e)
+{
+       struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+
+       lockdep_assert_held(&esw->offloads.encap_tbl_lock);
+
+       if (!refcount_dec_and_test(&e->refcnt))
+               return;
+       list_del(&e->route_list);
+       hash_del_rcu(&e->encap_hlist);
+       mlx5e_encap_dealloc(priv, e);
+}
+
 static void mlx5e_decap_put(struct mlx5e_priv *priv, struct mlx5e_decap_entry *d)
 {
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
@@ -816,6 +829,8 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv,
        uintptr_t hash_key;
        int err = 0;
 
+       lockdep_assert_held(&esw->offloads.encap_tbl_lock);
+
        parse_attr = attr->parse_attr;
        tun_info = parse_attr->tun_info[out_index];
        mpls_info = &parse_attr->mpls_info[out_index];
@@ -829,7 +844,6 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv,
 
        hash_key = hash_encap_info(&key);
 
-       mutex_lock(&esw->offloads.encap_tbl_lock);
        e = mlx5e_encap_get(priv, &key, hash_key);
 
        /* must verify if encap is valid or not */
@@ -840,15 +854,6 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv,
                        goto out_err;
                }
 
-               mutex_unlock(&esw->offloads.encap_tbl_lock);
-               wait_for_completion(&e->res_ready);
-
-               /* Protect against concurrent neigh update. */
-               mutex_lock(&esw->offloads.encap_tbl_lock);
-               if (e->compl_result < 0) {
-                       err = -EREMOTEIO;
-                       goto out_err;
-               }
                goto attach_flow;
        }
 
@@ -877,15 +882,12 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv,
        INIT_LIST_HEAD(&e->flows);
        hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key);
        tbl_time_before = mlx5e_route_tbl_get_last_update(priv);
-       mutex_unlock(&esw->offloads.encap_tbl_lock);
 
        if (family == AF_INET)
                err = mlx5e_tc_tun_create_header_ipv4(priv, mirred_dev, e);
        else if (family == AF_INET6)
                err = mlx5e_tc_tun_create_header_ipv6(priv, mirred_dev, e);
 
-       /* Protect against concurrent neigh update. */
-       mutex_lock(&esw->offloads.encap_tbl_lock);
        complete_all(&e->res_ready);
        if (err) {
                e->compl_result = err;
@@ -920,18 +922,15 @@ attach_flow:
        } else {
                flow_flag_set(flow, SLOW);
        }
-       mutex_unlock(&esw->offloads.encap_tbl_lock);
 
        return err;
 
 out_err:
-       mutex_unlock(&esw->offloads.encap_tbl_lock);
        if (e)
-               mlx5e_encap_put(priv, e);
+               mlx5e_encap_put_locked(priv, e);
        return err;
 
 out_err_init:
-       mutex_unlock(&esw->offloads.encap_tbl_lock);
        kfree(tun_info);
        kfree(e);
        return err;
@@ -1016,6 +1015,93 @@ out_err:
        return err;
 }
 
+int mlx5e_tc_tun_encap_dests_set(struct mlx5e_priv *priv,
+                                struct mlx5e_tc_flow *flow,
+                                struct mlx5_flow_attr *attr,
+                                struct netlink_ext_ack *extack,
+                                bool *vf_tun)
+{
+       struct mlx5e_tc_flow_parse_attr *parse_attr;
+       struct mlx5_esw_flow_attr *esw_attr;
+       struct net_device *encap_dev = NULL;
+       struct mlx5e_rep_priv *rpriv;
+       struct mlx5e_priv *out_priv;
+       struct mlx5_eswitch *esw;
+       int out_index;
+       int err = 0;
+
+       if (!mlx5e_is_eswitch_flow(flow))
+               return 0;
+
+       parse_attr = attr->parse_attr;
+       esw_attr = attr->esw_attr;
+       *vf_tun = false;
+
+       esw = priv->mdev->priv.eswitch;
+       mutex_lock(&esw->offloads.encap_tbl_lock);
+       for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) {
+               struct net_device *out_dev;
+               int mirred_ifindex;
+
+               if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP))
+                       continue;
+
+               mirred_ifindex = parse_attr->mirred_ifindex[out_index];
+               out_dev = dev_get_by_index(dev_net(priv->netdev), mirred_ifindex);
+               if (!out_dev) {
+                       NL_SET_ERR_MSG_MOD(extack, "Requested mirred device not found");
+                       err = -ENODEV;
+                       goto out;
+               }
+               err = mlx5e_attach_encap(priv, flow, attr, out_dev, out_index,
+                                        extack, &encap_dev);
+               dev_put(out_dev);
+               if (err)
+                       goto out;
+
+               if (esw_attr->dests[out_index].flags &
+                   MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE &&
+                   !esw_attr->dest_int_port)
+                       *vf_tun = true;
+
+               out_priv = netdev_priv(encap_dev);
+               rpriv = out_priv->ppriv;
+               esw_attr->dests[out_index].rep = rpriv->rep;
+               esw_attr->dests[out_index].mdev = out_priv->mdev;
+       }
+
+       if (*vf_tun && esw_attr->out_count > 1) {
+               NL_SET_ERR_MSG_MOD(extack, "VF tunnel encap with mirroring is not supported");
+               err = -EOPNOTSUPP;
+               goto out;
+       }
+
+out:
+       mutex_unlock(&esw->offloads.encap_tbl_lock);
+       return err;
+}
+
+void mlx5e_tc_tun_encap_dests_unset(struct mlx5e_priv *priv,
+                                   struct mlx5e_tc_flow *flow,
+                                   struct mlx5_flow_attr *attr)
+{
+       struct mlx5_esw_flow_attr *esw_attr;
+       int out_index;
+
+       if (!mlx5e_is_eswitch_flow(flow))
+               return;
+
+       esw_attr = attr->esw_attr;
+
+       for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) {
+               if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP))
+                       continue;
+
+               mlx5e_detach_encap(flow->priv, flow, attr, out_index);
+               kfree(attr->parse_attr->tun_info[out_index]);
+       }
+}
+
 static int cmp_route_info(struct mlx5e_route_key *a,
                          struct mlx5e_route_key *b)
 {
@@ -1369,11 +1455,13 @@ static void mlx5e_invalidate_encap(struct mlx5e_priv *priv,
        struct mlx5e_tc_flow *flow;
 
        list_for_each_entry(flow, encap_flows, tmp_list) {
-               struct mlx5_flow_attr *attr = flow->attr;
                struct mlx5_esw_flow_attr *esw_attr;
+               struct mlx5_flow_attr *attr;
 
                if (!mlx5e_is_offloaded_flow(flow))
                        continue;
+
+               attr = mlx5e_tc_get_encap_attr(flow);
                esw_attr = attr->esw_attr;
 
                if (flow_flag_test(flow, SLOW))
index 8ad273dde40ee5b41ad1cdc4963ce8ad9d10fccb..5d7d67687cbcd29204ae121e4af99b1292335b02 100644 (file)
@@ -30,6 +30,15 @@ int mlx5e_attach_decap_route(struct mlx5e_priv *priv,
 void mlx5e_detach_decap_route(struct mlx5e_priv *priv,
                              struct mlx5e_tc_flow *flow);
 
+int mlx5e_tc_tun_encap_dests_set(struct mlx5e_priv *priv,
+                                struct mlx5e_tc_flow *flow,
+                                struct mlx5_flow_attr *attr,
+                                struct netlink_ext_ack *extack,
+                                bool *vf_tun);
+void mlx5e_tc_tun_encap_dests_unset(struct mlx5e_priv *priv,
+                                   struct mlx5e_tc_flow *flow,
+                                   struct mlx5_flow_attr *attr);
+
 struct ip_tunnel_info *mlx5e_dup_tun_info(const struct ip_tunnel_info *tun_info);
 
 int mlx5e_tc_set_attr_rx_tun(struct mlx5e_tc_flow *flow,
index 47381e949f1f5fc7006fddeb2b5e19e1dee7a354..879d698b6119303836915d5dc19f6f910d506890 100644 (file)
@@ -193,6 +193,8 @@ static inline u16 mlx5e_txqsq_get_next_pi(struct mlx5e_txqsq *sq, u16 size)
        return pi;
 }
 
+void mlx5e_txqsq_wake(struct mlx5e_txqsq *sq);
+
 static inline u16 mlx5e_shampo_get_cqe_header_index(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
 {
        return be16_to_cpu(cqe->shampo.header_entry_index) & (rq->mpwqe.shampo->hd_per_wq - 1);
index 1f90594499c6098d06f37f1beed887d200b1a1a4..41c396e764579492b21b2f1cedb3f54a471894c4 100644 (file)
@@ -150,10 +150,8 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb,
 
        inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
        in = kvzalloc(inlen, GFP_KERNEL);
-       if (!in) {
-               err = -ENOMEM;
-               goto out;
-       }
+       if (!in)
+               return -ENOMEM;
 
        if (enable_uc_lb)
                lb_flags = MLX5_TIRC_SELF_LB_BLOCK_BLOCK_UNICAST;
@@ -171,14 +169,13 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb,
                tirn = tir->tirn;
                err = mlx5_core_modify_tir(mdev, tirn, in);
                if (err)
-                       goto out;
+                       break;
        }
+       mutex_unlock(&mdev->mlx5e_res.hw_objs.td.list_lock);
 
-out:
        kvfree(in);
        if (err)
                netdev_err(priv->netdev, "refresh tir(0x%x) failed, %d\n", tirn, err);
-       mutex_unlock(&mdev->mlx5e_res.hw_objs.td.list_lock);
 
        return err;
 }
index 89de92d0648363a899793f1aa5ea4fb324a9ddc8..ebee52a8361aa7f7102683c4d62dbc4571ed1a71 100644 (file)
@@ -926,9 +926,10 @@ static int mlx5e_dcbnl_getbuffer(struct net_device *dev,
        if (err)
                return err;
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++)
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++)
                dcb_buffer->buffer_size[i] = port_buffer.buffer[i].size;
-       dcb_buffer->total_size = port_buffer.port_buffer_size;
+       dcb_buffer->total_size = port_buffer.port_buffer_size -
+                                port_buffer.internal_buffers_size;
 
        return 0;
 }
@@ -970,7 +971,7 @@ static int mlx5e_dcbnl_setbuffer(struct net_device *dev,
        if (err)
                return err;
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
                if (port_buffer.buffer[i].size != dcb_buffer->buffer_size[i]) {
                        changed |= MLX5E_PORT_BUFFER_SIZE;
                        buffer_size = dcb_buffer->buffer_size;
index 2944691f06added0b8420c962f514a7bee413e49..a7c526ee5024748097a39abf2f718c0e9ea28f9d 100644 (file)
@@ -727,26 +727,6 @@ static void mlx5e_rq_free_shampo(struct mlx5e_rq *rq)
        mlx5e_rq_shampo_hd_free(rq);
 }
 
-static __be32 mlx5e_get_terminate_scatter_list_mkey(struct mlx5_core_dev *dev)
-{
-       u32 out[MLX5_ST_SZ_DW(query_special_contexts_out)] = {};
-       u32 in[MLX5_ST_SZ_DW(query_special_contexts_in)] = {};
-       int res;
-
-       if (!MLX5_CAP_GEN(dev, terminate_scatter_list_mkey))
-               return MLX5_TERMINATE_SCATTER_LIST_LKEY;
-
-       MLX5_SET(query_special_contexts_in, in, opcode,
-                MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS);
-       res = mlx5_cmd_exec_inout(dev, query_special_contexts, in, out);
-       if (res)
-               return MLX5_TERMINATE_SCATTER_LIST_LKEY;
-
-       res = MLX5_GET(query_special_contexts_out, out,
-                      terminate_scatter_list_mkey);
-       return cpu_to_be32(res);
-}
-
 static int mlx5e_alloc_rq(struct mlx5e_params *params,
                          struct mlx5e_xsk_param *xsk,
                          struct mlx5e_rq_param *rqp,
@@ -908,7 +888,7 @@ static int mlx5e_alloc_rq(struct mlx5e_params *params,
                        /* check if num_frags is not a pow of two */
                        if (rq->wqe.info.num_frags < (1 << rq->wqe.info.log_num_frags)) {
                                wqe->data[f].byte_count = 0;
-                               wqe->data[f].lkey = mlx5e_get_terminate_scatter_list_mkey(mdev);
+                               wqe->data[f].lkey = params->terminate_lkey_be;
                                wqe->data[f].addr = 0;
                        }
                }
@@ -5007,6 +4987,8 @@ void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16
        /* RQ */
        mlx5e_build_rq_params(mdev, params);
 
+       params->terminate_lkey_be = mlx5_core_get_terminate_scatter_list_mkey(mdev);
+
        params->packet_merge.timeout = mlx5e_choose_lro_timeout(mdev, MLX5E_DEFAULT_LRO_TIMEOUT);
 
        /* CQ moderation params */
@@ -5279,12 +5261,16 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
 
        mlx5e_timestamp_init(priv);
 
+       priv->dfs_root = debugfs_create_dir("nic",
+                                           mlx5_debugfs_get_dev_root(mdev));
+
        fs = mlx5e_fs_init(priv->profile, mdev,
                           !test_bit(MLX5E_STATE_DESTROYING, &priv->state),
                           priv->dfs_root);
        if (!fs) {
                err = -ENOMEM;
                mlx5_core_err(mdev, "FS initialization failed, %d\n", err);
+               debugfs_remove_recursive(priv->dfs_root);
                return err;
        }
        priv->fs = fs;
@@ -5305,6 +5291,7 @@ static void mlx5e_nic_cleanup(struct mlx5e_priv *priv)
        mlx5e_health_destroy_reporters(priv);
        mlx5e_ktls_cleanup(priv);
        mlx5e_fs_cleanup(priv->fs);
+       debugfs_remove_recursive(priv->dfs_root);
        priv->fs = NULL;
 }
 
@@ -5851,8 +5838,8 @@ void mlx5e_detach_netdev(struct mlx5e_priv *priv)
 }
 
 static int
-mlx5e_netdev_attach_profile(struct net_device *netdev, struct mlx5_core_dev *mdev,
-                           const struct mlx5e_profile *new_profile, void *new_ppriv)
+mlx5e_netdev_init_profile(struct net_device *netdev, struct mlx5_core_dev *mdev,
+                         const struct mlx5e_profile *new_profile, void *new_ppriv)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
        int err;
@@ -5868,6 +5855,25 @@ mlx5e_netdev_attach_profile(struct net_device *netdev, struct mlx5_core_dev *mde
        err = new_profile->init(priv->mdev, priv->netdev);
        if (err)
                goto priv_cleanup;
+
+       return 0;
+
+priv_cleanup:
+       mlx5e_priv_cleanup(priv);
+       return err;
+}
+
+static int
+mlx5e_netdev_attach_profile(struct net_device *netdev, struct mlx5_core_dev *mdev,
+                           const struct mlx5e_profile *new_profile, void *new_ppriv)
+{
+       struct mlx5e_priv *priv = netdev_priv(netdev);
+       int err;
+
+       err = mlx5e_netdev_init_profile(netdev, mdev, new_profile, new_ppriv);
+       if (err)
+               return err;
+
        err = mlx5e_attach_netdev(priv);
        if (err)
                goto profile_cleanup;
@@ -5875,7 +5881,6 @@ mlx5e_netdev_attach_profile(struct net_device *netdev, struct mlx5_core_dev *mde
 
 profile_cleanup:
        new_profile->cleanup(priv);
-priv_cleanup:
        mlx5e_priv_cleanup(priv);
        return err;
 }
@@ -5894,6 +5899,12 @@ int mlx5e_netdev_change_profile(struct mlx5e_priv *priv,
        priv->profile->cleanup(priv);
        mlx5e_priv_cleanup(priv);
 
+       if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+               mlx5e_netdev_init_profile(netdev, mdev, new_profile, new_ppriv);
+               set_bit(MLX5E_STATE_DESTROYING, &priv->state);
+               return -EIO;
+       }
+
        err = mlx5e_netdev_attach_profile(netdev, mdev, new_profile, new_ppriv);
        if (err) { /* roll back to original profile */
                netdev_warn(netdev, "%s: new profile init failed, %d\n", __func__, err);
@@ -5955,8 +5966,11 @@ static int mlx5e_suspend(struct auxiliary_device *adev, pm_message_t state)
        struct net_device *netdev = priv->netdev;
        struct mlx5_core_dev *mdev = priv->mdev;
 
-       if (!netif_device_present(netdev))
+       if (!netif_device_present(netdev)) {
+               if (test_bit(MLX5E_STATE_DESTROYING, &priv->state))
+                       mlx5e_destroy_mdev_resources(mdev);
                return -ENODEV;
+       }
 
        mlx5e_detach_netdev(priv);
        mlx5e_destroy_mdev_resources(mdev);
@@ -6002,9 +6016,6 @@ static int mlx5e_probe(struct auxiliary_device *adev,
        priv->profile = profile;
        priv->ppriv = NULL;
 
-       priv->dfs_root = debugfs_create_dir("nic",
-                                           mlx5_debugfs_get_dev_root(priv->mdev));
-
        err = profile->init(mdev, netdev);
        if (err) {
                mlx5_core_err(mdev, "mlx5e_nic_profile init failed, %d\n", err);
@@ -6033,7 +6044,6 @@ err_resume:
 err_profile_cleanup:
        profile->cleanup(priv);
 err_destroy_netdev:
-       debugfs_remove_recursive(priv->dfs_root);
        mlx5e_destroy_netdev(priv);
 err_devlink_port_unregister:
        mlx5e_devlink_port_unregister(mlx5e_dev);
@@ -6053,7 +6063,6 @@ static void mlx5e_remove(struct auxiliary_device *adev)
        unregister_netdev(priv->netdev);
        mlx5e_suspend(adev, state);
        priv->profile->cleanup(priv);
-       debugfs_remove_recursive(priv->dfs_root);
        mlx5e_destroy_netdev(priv);
        mlx5e_devlink_port_unregister(mlx5e_dev);
        mlx5e_destroy_devlink(mlx5e_dev);
index 1fc386eccaf8f9f1345d1a2c640b1039781ca0e1..3e7041bd5705e8761258d3513c5bc358a602cf68 100644 (file)
@@ -30,6 +30,7 @@
  * SOFTWARE.
  */
 
+#include <linux/debugfs.h>
 #include <linux/mlx5/fs.h>
 #include <net/switchdev.h>
 #include <net/pkt_cls.h>
@@ -812,11 +813,15 @@ static int mlx5e_init_ul_rep(struct mlx5_core_dev *mdev,
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
 
+       priv->dfs_root = debugfs_create_dir("nic",
+                                           mlx5_debugfs_get_dev_root(mdev));
+
        priv->fs = mlx5e_fs_init(priv->profile, mdev,
                                 !test_bit(MLX5E_STATE_DESTROYING, &priv->state),
                                 priv->dfs_root);
        if (!priv->fs) {
                netdev_err(priv->netdev, "FS allocation failed\n");
+               debugfs_remove_recursive(priv->dfs_root);
                return -ENOMEM;
        }
 
@@ -829,6 +834,7 @@ static int mlx5e_init_ul_rep(struct mlx5_core_dev *mdev,
 static void mlx5e_cleanup_rep(struct mlx5e_priv *priv)
 {
        mlx5e_fs_cleanup(priv->fs);
+       debugfs_remove_recursive(priv->dfs_root);
        priv->fs = NULL;
 }
 
index 728b82ce4031a2b6ce3e0434064980f39985ff2e..8a5a8703f0a31b0c4b2feadfb39a5cbcdb1d9196 100644 (file)
@@ -1665,11 +1665,9 @@ bool mlx5e_tc_is_vf_tunnel(struct net_device *out_dev, struct net_device *route_
 int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *route_dev, u16 *vport)
 {
        struct mlx5e_priv *out_priv, *route_priv;
-       struct mlx5_devcom *devcom = NULL;
        struct mlx5_core_dev *route_mdev;
        struct mlx5_eswitch *esw;
        u16 vhca_id;
-       int err;
 
        out_priv = netdev_priv(out_dev);
        esw = out_priv->mdev->priv.eswitch;
@@ -1678,6 +1676,9 @@ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *ro
 
        vhca_id = MLX5_CAP_GEN(route_mdev, vhca_id);
        if (mlx5_lag_is_active(out_priv->mdev)) {
+               struct mlx5_devcom *devcom;
+               int err;
+
                /* In lag case we may get devices from different eswitch instances.
                 * If we failed to get vport num, it means, mostly, that we on the wrong
                 * eswitch.
@@ -1686,101 +1687,16 @@ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *ro
                if (err != -ENOENT)
                        return err;
 
+               rcu_read_lock();
                devcom = out_priv->mdev->priv.devcom;
-               esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
-               if (!esw)
-                       return -ENODEV;
-       }
-
-       err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
-       if (devcom)
-               mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
-       return err;
-}
-
-static int
-set_encap_dests(struct mlx5e_priv *priv,
-               struct mlx5e_tc_flow *flow,
-               struct mlx5_flow_attr *attr,
-               struct netlink_ext_ack *extack,
-               bool *vf_tun)
-{
-       struct mlx5e_tc_flow_parse_attr *parse_attr;
-       struct mlx5_esw_flow_attr *esw_attr;
-       struct net_device *encap_dev = NULL;
-       struct mlx5e_rep_priv *rpriv;
-       struct mlx5e_priv *out_priv;
-       int out_index;
-       int err = 0;
-
-       if (!mlx5e_is_eswitch_flow(flow))
-               return 0;
-
-       parse_attr = attr->parse_attr;
-       esw_attr = attr->esw_attr;
-       *vf_tun = false;
-
-       for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) {
-               struct net_device *out_dev;
-               int mirred_ifindex;
-
-               if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP))
-                       continue;
-
-               mirred_ifindex = parse_attr->mirred_ifindex[out_index];
-               out_dev = dev_get_by_index(dev_net(priv->netdev), mirred_ifindex);
-               if (!out_dev) {
-                       NL_SET_ERR_MSG_MOD(extack, "Requested mirred device not found");
-                       err = -ENODEV;
-                       goto out;
-               }
-               err = mlx5e_attach_encap(priv, flow, attr, out_dev, out_index,
-                                        extack, &encap_dev);
-               dev_put(out_dev);
-               if (err)
-                       goto out;
+               esw = mlx5_devcom_get_peer_data_rcu(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+               err = esw ? mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport) : -ENODEV;
+               rcu_read_unlock();
 
-               if (esw_attr->dests[out_index].flags &
-                   MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE &&
-                   !esw_attr->dest_int_port)
-                       *vf_tun = true;
-
-               out_priv = netdev_priv(encap_dev);
-               rpriv = out_priv->ppriv;
-               esw_attr->dests[out_index].rep = rpriv->rep;
-               esw_attr->dests[out_index].mdev = out_priv->mdev;
-       }
-
-       if (*vf_tun && esw_attr->out_count > 1) {
-               NL_SET_ERR_MSG_MOD(extack, "VF tunnel encap with mirroring is not supported");
-               err = -EOPNOTSUPP;
-               goto out;
+               return err;
        }
 
-out:
-       return err;
-}
-
-static void
-clean_encap_dests(struct mlx5e_priv *priv,
-                 struct mlx5e_tc_flow *flow,
-                 struct mlx5_flow_attr *attr)
-{
-       struct mlx5_esw_flow_attr *esw_attr;
-       int out_index;
-
-       if (!mlx5e_is_eswitch_flow(flow))
-               return;
-
-       esw_attr = attr->esw_attr;
-
-       for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) {
-               if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP))
-                       continue;
-
-               mlx5e_detach_encap(priv, flow, attr, out_index);
-               kfree(attr->parse_attr->tun_info[out_index]);
-       }
+       return mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
 }
 
 static int
@@ -1819,7 +1735,7 @@ post_process_attr(struct mlx5e_tc_flow *flow,
        if (err)
                goto err_out;
 
-       err = set_encap_dests(flow->priv, flow, attr, extack, &vf_tun);
+       err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun);
        if (err)
                goto err_out;
 
@@ -3943,8 +3859,8 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state,
        struct mlx5_flow_attr *prev_attr;
        struct flow_action_entry *act;
        struct mlx5e_tc_act *tc_act;
+       int err, i, i_split = 0;
        bool is_missable;
-       int err, i;
 
        ns_type = mlx5e_get_flow_namespace(flow);
        list_add(&attr->list, &flow->attrs);
@@ -3985,7 +3901,8 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state,
                    i < flow_action->num_entries - 1)) {
                        is_missable = tc_act->is_missable ? tc_act->is_missable(act) : false;
 
-                       err = mlx5e_tc_act_post_parse(parse_state, flow_action, attr, ns_type);
+                       err = mlx5e_tc_act_post_parse(parse_state, flow_action, i_split, i, attr,
+                                                     ns_type);
                        if (err)
                                goto out_free_post_acts;
 
@@ -3995,6 +3912,7 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state,
                                goto out_free_post_acts;
                        }
 
+                       i_split = i + 1;
                        list_add(&attr->list, &flow->attrs);
                }
 
@@ -4009,7 +3927,7 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state,
                }
        }
 
-       err = mlx5e_tc_act_post_parse(parse_state, flow_action, attr, ns_type);
+       err = mlx5e_tc_act_post_parse(parse_state, flow_action, i_split, i, attr, ns_type);
        if (err)
                goto out_free_post_acts;
 
@@ -4323,7 +4241,7 @@ mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *a
        if (attr->post_act_handle)
                mlx5e_tc_post_act_del(get_post_action(flow->priv), attr->post_act_handle);
 
-       clean_encap_dests(flow->priv, flow, attr);
+       mlx5e_tc_tun_encap_dests_unset(flow->priv, flow, attr);
 
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT)
                mlx5_fc_destroy(counter_dev, attr->counter);
@@ -5301,6 +5219,8 @@ int mlx5e_tc_esw_init(struct mlx5_rep_uplink_priv *uplink_priv)
                goto err_action_counter;
        }
 
+       mlx5_esw_offloads_devcom_init(esw);
+
        return 0;
 
 err_action_counter:
@@ -5329,7 +5249,7 @@ void mlx5e_tc_esw_cleanup(struct mlx5_rep_uplink_priv *uplink_priv)
        priv = netdev_priv(rpriv->netdev);
        esw = priv->mdev->priv.eswitch;
 
-       mlx5e_tc_clean_fdb_peer_flows(esw);
+       mlx5_esw_offloads_devcom_cleanup(esw);
 
        mlx5e_tc_tun_cleanup(uplink_priv->encap);
 
@@ -5643,22 +5563,43 @@ bool mlx5e_tc_update_skb_nic(struct mlx5_cqe64 *cqe, struct sk_buff *skb)
                                   0, NULL);
 }
 
+static struct mapping_ctx *
+mlx5e_get_priv_obj_mapping(struct mlx5e_priv *priv)
+{
+       struct mlx5e_tc_table *tc;
+       struct mlx5_eswitch *esw;
+       struct mapping_ctx *ctx;
+
+       if (is_mdev_switchdev_mode(priv->mdev)) {
+               esw = priv->mdev->priv.eswitch;
+               ctx = esw->offloads.reg_c0_obj_pool;
+       } else {
+               tc = mlx5e_fs_get_tc(priv->fs);
+               ctx = tc->mapping;
+       }
+
+       return ctx;
+}
+
 int mlx5e_tc_action_miss_mapping_get(struct mlx5e_priv *priv, struct mlx5_flow_attr *attr,
                                     u64 act_miss_cookie, u32 *act_miss_mapping)
 {
-       struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct mlx5_mapped_obj mapped_obj = {};
+       struct mlx5_eswitch *esw;
        struct mapping_ctx *ctx;
        int err;
 
-       ctx = esw->offloads.reg_c0_obj_pool;
-
+       ctx = mlx5e_get_priv_obj_mapping(priv);
        mapped_obj.type = MLX5_MAPPED_OBJ_ACT_MISS;
        mapped_obj.act_miss_cookie = act_miss_cookie;
        err = mapping_add(ctx, &mapped_obj, act_miss_mapping);
        if (err)
                return err;
 
+       if (!is_mdev_switchdev_mode(priv->mdev))
+               return 0;
+
+       esw = priv->mdev->priv.eswitch;
        attr->act_id_restore_rule = esw_add_restore_rule(esw, *act_miss_mapping);
        if (IS_ERR(attr->act_id_restore_rule))
                goto err_rule;
@@ -5673,10 +5614,9 @@ err_rule:
 void mlx5e_tc_action_miss_mapping_put(struct mlx5e_priv *priv, struct mlx5_flow_attr *attr,
                                      u32 act_miss_mapping)
 {
-       struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
-       struct mapping_ctx *ctx;
+       struct mapping_ctx *ctx = mlx5e_get_priv_obj_mapping(priv);
 
-       ctx = esw->offloads.reg_c0_obj_pool;
-       mlx5_del_flow_rules(attr->act_id_restore_rule);
+       if (is_mdev_switchdev_mode(priv->mdev))
+               mlx5_del_flow_rules(attr->act_id_restore_rule);
        mapping_remove(ctx, act_miss_mapping);
 }
index df5e780e8e6a6537b23c8fc8b0fb18234480e108..c7eb6b238c2ba15510533a904920afd9790dca5e 100644 (file)
@@ -762,6 +762,17 @@ static void mlx5e_tx_wi_consume_fifo_skbs(struct mlx5e_txqsq *sq, struct mlx5e_t
        }
 }
 
+void mlx5e_txqsq_wake(struct mlx5e_txqsq *sq)
+{
+       if (netif_tx_queue_stopped(sq->txq) &&
+           mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, sq->stop_room) &&
+           mlx5e_ptpsq_fifo_has_room(sq) &&
+           !test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) {
+               netif_tx_wake_queue(sq->txq);
+               sq->stats->wake++;
+       }
+}
+
 bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget)
 {
        struct mlx5e_sq_stats *stats;
@@ -861,13 +872,7 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget)
 
        netdev_tx_completed_queue(sq->txq, npkts, nbytes);
 
-       if (netif_tx_queue_stopped(sq->txq) &&
-           mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, sq->stop_room) &&
-           mlx5e_ptpsq_fifo_has_room(sq) &&
-           !test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) {
-               netif_tx_wake_queue(sq->txq);
-               stats->wake++;
-       }
+       mlx5e_txqsq_wake(sq);
 
        return (i == MLX5E_TX_CQ_POLL_BUDGET);
 }
index a50bfda18e96d95796ecb10a80c839d17455d569..fbb2d963fb7e1bc3afce053980f360f2467d1bf1 100644 (file)
@@ -161,20 +161,22 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
                }
        }
 
+       /* budget=0 means we may be in IRQ context, do as little as possible */
+       if (unlikely(!budget))
+               goto out;
+
        busy |= mlx5e_poll_xdpsq_cq(&c->xdpsq.cq);
 
        if (c->xdp)
                busy |= mlx5e_poll_xdpsq_cq(&c->rq_xdpsq.cq);
 
-       if (likely(budget)) { /* budget=0 means: don't poll rx rings */
-               if (xsk_open)
-                       work_done = mlx5e_poll_rx_cq(&xskrq->cq, budget);
+       if (xsk_open)
+               work_done = mlx5e_poll_rx_cq(&xskrq->cq, budget);
 
-               if (likely(budget - work_done))
-                       work_done += mlx5e_poll_rx_cq(&rq->cq, budget - work_done);
+       if (likely(budget - work_done))
+               work_done += mlx5e_poll_rx_cq(&rq->cq, budget - work_done);
 
-               busy |= work_done == budget;
-       }
+       busy |= work_done == budget;
 
        mlx5e_poll_ico_cq(&c->icosq.cq);
        if (mlx5e_poll_ico_cq(&c->async_icosq.cq))
index 1c35d721a31d7d250705aa7630ea666cffedc639..3db4866d7880fc4c41b05971e8fc4224e8f391ac 100644 (file)
@@ -824,7 +824,7 @@ static int comp_irqs_request_pci(struct mlx5_core_dev *dev)
        ncomp_eqs = table->num_comp_eqs;
        cpus = kcalloc(ncomp_eqs, sizeof(*cpus), GFP_KERNEL);
        if (!cpus)
-               ret = -ENOMEM;
+               return -ENOMEM;
 
        i = 0;
        rcu_read_lock();
@@ -1104,7 +1104,7 @@ void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev)
        struct mlx5_eq_table *table = dev->priv.eq_table;
 
        mutex_lock(&table->lock); /* sync with create/destroy_async_eq */
-       mlx5_irq_table_destroy(dev);
+       mlx5_irq_table_free_irqs(dev);
        mutex_unlock(&table->lock);
 }
 
index 1a042c9817131e7860a046c77ed7cc18b0b6e7e6..add6cfa432a5b7dd2c5cd4830a576d3ec9a00e7e 100644 (file)
@@ -342,6 +342,7 @@ struct mlx5_eswitch {
                u32             large_group_num;
        }  params;
        struct blocking_notifier_head n_head;
+       bool paired[MLX5_MAX_PORTS];
 };
 
 void esw_offloads_disable(struct mlx5_eswitch *esw);
@@ -369,6 +370,8 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs);
 void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf);
 void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw);
 void mlx5_eswitch_disable(struct mlx5_eswitch *esw);
+void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw);
+void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw);
 int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
                               u16 vport, const u8 *mac);
 int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
@@ -767,6 +770,8 @@ static inline void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) {}
 static inline int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) { return 0; }
 static inline void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf) {}
 static inline void mlx5_eswitch_disable(struct mlx5_eswitch *esw) {}
+static inline void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw) {}
+static inline void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) {}
 static inline bool mlx5_eswitch_is_funcs_handler(struct mlx5_core_dev *dev) { return false; }
 static inline
 int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, u16 vport, int link_state) { return 0; }
index 69215ffb9999532d839f5c21f7881f716ee35c96..8d19c20d3447e67cb63b4e7b4ead294ba3147b66 100644 (file)
@@ -2742,6 +2742,9 @@ static int mlx5_esw_offloads_devcom_event(int event,
                    mlx5_eswitch_vport_match_metadata_enabled(peer_esw))
                        break;
 
+               if (esw->paired[mlx5_get_dev_index(peer_esw->dev)])
+                       break;
+
                err = mlx5_esw_offloads_set_ns_peer(esw, peer_esw, true);
                if (err)
                        goto err_out;
@@ -2753,14 +2756,18 @@ static int mlx5_esw_offloads_devcom_event(int event,
                if (err)
                        goto err_pair;
 
+               esw->paired[mlx5_get_dev_index(peer_esw->dev)] = true;
+               peer_esw->paired[mlx5_get_dev_index(esw->dev)] = true;
                mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true);
                break;
 
        case ESW_OFFLOADS_DEVCOM_UNPAIR:
-               if (!mlx5_devcom_is_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS))
+               if (!esw->paired[mlx5_get_dev_index(peer_esw->dev)])
                        break;
 
                mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false);
+               esw->paired[mlx5_get_dev_index(peer_esw->dev)] = false;
+               peer_esw->paired[mlx5_get_dev_index(esw->dev)] = false;
                mlx5_esw_offloads_unpair(peer_esw);
                mlx5_esw_offloads_unpair(esw);
                mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false);
@@ -2779,7 +2786,7 @@ err_out:
        return err;
 }
 
-static void esw_offloads_devcom_init(struct mlx5_eswitch *esw)
+void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw)
 {
        struct mlx5_devcom *devcom = esw->dev->priv.devcom;
 
@@ -2802,7 +2809,7 @@ static void esw_offloads_devcom_init(struct mlx5_eswitch *esw)
                               ESW_OFFLOADS_DEVCOM_PAIR, esw);
 }
 
-static void esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
+void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
 {
        struct mlx5_devcom *devcom = esw->dev->priv.devcom;
 
@@ -3250,8 +3257,6 @@ int esw_offloads_enable(struct mlx5_eswitch *esw)
        if (err)
                goto err_vports;
 
-       esw_offloads_devcom_init(esw);
-
        return 0;
 
 err_vports:
@@ -3292,7 +3297,6 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw,
 
 void esw_offloads_disable(struct mlx5_eswitch *esw)
 {
-       esw_offloads_devcom_cleanup(esw);
        mlx5_eswitch_disable_pf_vf_vports(esw);
        esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK);
        esw_set_passing_vport_metadata(esw, false);
index adefde3ea941010f7133184a1dd40c405c06841f..b7d779d08d8371082415d439b547e54cf6f6b8e5 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/mlx5/vport.h>
 #include "lib/devcom.h"
+#include "mlx5_core.h"
 
 static LIST_HEAD(devcom_list);
 
@@ -13,7 +14,7 @@ static LIST_HEAD(devcom_list);
 
 struct mlx5_devcom_component {
        struct {
-               void *data;
+               void __rcu *data;
        } device[MLX5_DEVCOM_PORTS_SUPPORTED];
 
        mlx5_devcom_event_handler_t handler;
@@ -77,6 +78,7 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev)
        if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED)
                return NULL;
 
+       mlx5_dev_list_lock();
        sguid0 = mlx5_query_nic_system_image_guid(dev);
        list_for_each_entry(iter, &devcom_list, list) {
                struct mlx5_core_dev *tmp_dev = NULL;
@@ -102,8 +104,10 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev)
 
        if (!priv) {
                priv = mlx5_devcom_list_alloc();
-               if (!priv)
-                       return ERR_PTR(-ENOMEM);
+               if (!priv) {
+                       devcom = ERR_PTR(-ENOMEM);
+                       goto out;
+               }
 
                idx = 0;
                new_priv = true;
@@ -112,13 +116,16 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev)
        priv->devs[idx] = dev;
        devcom = mlx5_devcom_alloc(priv, idx);
        if (!devcom) {
-               kfree(priv);
-               return ERR_PTR(-ENOMEM);
+               if (new_priv)
+                       kfree(priv);
+               devcom = ERR_PTR(-ENOMEM);
+               goto out;
        }
 
        if (new_priv)
                list_add(&priv->list, &devcom_list);
-
+out:
+       mlx5_dev_list_unlock();
        return devcom;
 }
 
@@ -131,6 +138,7 @@ void mlx5_devcom_unregister_device(struct mlx5_devcom *devcom)
        if (IS_ERR_OR_NULL(devcom))
                return;
 
+       mlx5_dev_list_lock();
        priv = devcom->priv;
        priv->devs[devcom->idx] = NULL;
 
@@ -141,10 +149,12 @@ void mlx5_devcom_unregister_device(struct mlx5_devcom *devcom)
                        break;
 
        if (i != MLX5_DEVCOM_PORTS_SUPPORTED)
-               return;
+               goto out;
 
        list_del(&priv->list);
        kfree(priv);
+out:
+       mlx5_dev_list_unlock();
 }
 
 void mlx5_devcom_register_component(struct mlx5_devcom *devcom,
@@ -162,7 +172,7 @@ void mlx5_devcom_register_component(struct mlx5_devcom *devcom,
        comp = &devcom->priv->components[id];
        down_write(&comp->sem);
        comp->handler = handler;
-       comp->device[devcom->idx].data = data;
+       rcu_assign_pointer(comp->device[devcom->idx].data, data);
        up_write(&comp->sem);
 }
 
@@ -176,8 +186,9 @@ void mlx5_devcom_unregister_component(struct mlx5_devcom *devcom,
 
        comp = &devcom->priv->components[id];
        down_write(&comp->sem);
-       comp->device[devcom->idx].data = NULL;
+       RCU_INIT_POINTER(comp->device[devcom->idx].data, NULL);
        up_write(&comp->sem);
+       synchronize_rcu();
 }
 
 int mlx5_devcom_send_event(struct mlx5_devcom *devcom,
@@ -193,12 +204,15 @@ int mlx5_devcom_send_event(struct mlx5_devcom *devcom,
 
        comp = &devcom->priv->components[id];
        down_write(&comp->sem);
-       for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
-               if (i != devcom->idx && comp->device[i].data) {
-                       err = comp->handler(event, comp->device[i].data,
-                                           event_data);
+       for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) {
+               void *data = rcu_dereference_protected(comp->device[i].data,
+                                                      lockdep_is_held(&comp->sem));
+
+               if (i != devcom->idx && data) {
+                       err = comp->handler(event, data, event_data);
                        break;
                }
+       }
 
        up_write(&comp->sem);
        return err;
@@ -213,7 +227,7 @@ void mlx5_devcom_set_paired(struct mlx5_devcom *devcom,
        comp = &devcom->priv->components[id];
        WARN_ON(!rwsem_is_locked(&comp->sem));
 
-       comp->paired = paired;
+       WRITE_ONCE(comp->paired, paired);
 }
 
 bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom,
@@ -222,7 +236,7 @@ bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom,
        if (IS_ERR_OR_NULL(devcom))
                return false;
 
-       return devcom->priv->components[id].paired;
+       return READ_ONCE(devcom->priv->components[id].paired);
 }
 
 void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
@@ -236,7 +250,7 @@ void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
 
        comp = &devcom->priv->components[id];
        down_read(&comp->sem);
-       if (!comp->paired) {
+       if (!READ_ONCE(comp->paired)) {
                up_read(&comp->sem);
                return NULL;
        }
@@ -245,7 +259,29 @@ void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
                if (i != devcom->idx)
                        break;
 
-       return comp->device[i].data;
+       return rcu_dereference_protected(comp->device[i].data, lockdep_is_held(&comp->sem));
+}
+
+void *mlx5_devcom_get_peer_data_rcu(struct mlx5_devcom *devcom, enum mlx5_devcom_components id)
+{
+       struct mlx5_devcom_component *comp;
+       int i;
+
+       if (IS_ERR_OR_NULL(devcom))
+               return NULL;
+
+       for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
+               if (i != devcom->idx)
+                       break;
+
+       comp = &devcom->priv->components[id];
+       /* This can change concurrently, however 'data' pointer will remain
+        * valid for the duration of RCU read section.
+        */
+       if (!READ_ONCE(comp->paired))
+               return NULL;
+
+       return rcu_dereference(comp->device[i].data);
 }
 
 void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom,
index 94313c18bb6470d593e8e15e161188a279b58401..9a496f4722dadd690388a98c5cba59f0cfa9371b 100644 (file)
@@ -41,6 +41,7 @@ bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom,
 
 void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
                                enum mlx5_devcom_components id);
+void *mlx5_devcom_get_peer_data_rcu(struct mlx5_devcom *devcom, enum mlx5_devcom_components id);
 void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom,
                                   enum mlx5_devcom_components id);
 
index 995eb2d5ace0b2681718920d7ebdb09c94625156..d6ee016deae176aa2ac54401304a5e8e1dda4c8f 100644 (file)
@@ -923,7 +923,6 @@ static int mlx5_pci_init(struct mlx5_core_dev *dev, struct pci_dev *pdev,
        }
 
        mlx5_pci_vsc_init(dev);
-       dev->caps.embedded_cpu = mlx5_read_embedded_cpu(dev);
        return 0;
 
 err_clr_master:
@@ -1049,7 +1048,7 @@ static int mlx5_init_once(struct mlx5_core_dev *dev)
 
        dev->dm = mlx5_dm_create(dev);
        if (IS_ERR(dev->dm))
-               mlx5_core_warn(dev, "Failed to init device memory%d\n", err);
+               mlx5_core_warn(dev, "Failed to init device memory %ld\n", PTR_ERR(dev->dm));
 
        dev->tracer = mlx5_fw_tracer_create(dev);
        dev->hv_vhca = mlx5_hv_vhca_create(dev);
@@ -1155,6 +1154,7 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout
                goto err_cmd_cleanup;
        }
 
+       dev->caps.embedded_cpu = mlx5_read_embedded_cpu(dev);
        mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_UP);
 
        mlx5_start_health_poll(dev);
@@ -1802,15 +1802,16 @@ static void remove_one(struct pci_dev *pdev)
        struct devlink *devlink = priv_to_devlink(dev);
 
        set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state);
-       /* mlx5_drain_fw_reset() is using devlink APIs. Hence, we must drain
-        * fw_reset before unregistering the devlink.
+       /* mlx5_drain_fw_reset() and mlx5_drain_health_wq() are using
+        * devlink notify APIs.
+        * Hence, we must drain them before unregistering the devlink.
         */
        mlx5_drain_fw_reset(dev);
+       mlx5_drain_health_wq(dev);
        devlink_unregister(devlink);
        mlx5_sriov_disable(pdev);
        mlx5_thermal_uninit(dev);
        mlx5_crdump_disable(dev);
-       mlx5_drain_health_wq(dev);
        mlx5_uninit_one(dev);
        mlx5_pci_close(dev);
        mlx5_mdev_uninit(dev);
index efd0c299c5c73f54a3e8356aff4ea30a57459dec..aa403a5ea34ed22d30f987c84260423c444b37ec 100644 (file)
@@ -15,6 +15,7 @@ int mlx5_irq_table_init(struct mlx5_core_dev *dev);
 void mlx5_irq_table_cleanup(struct mlx5_core_dev *dev);
 int mlx5_irq_table_create(struct mlx5_core_dev *dev);
 void mlx5_irq_table_destroy(struct mlx5_core_dev *dev);
+void mlx5_irq_table_free_irqs(struct mlx5_core_dev *dev);
 int mlx5_irq_table_get_num_comp(struct mlx5_irq_table *table);
 int mlx5_irq_table_get_sfs_vec(struct mlx5_irq_table *table);
 struct mlx5_irq_table *mlx5_irq_table_get(struct mlx5_core_dev *dev);
index 9d735c343a3b8c0df0a1a90ceacab0e9439d86b7..678f0be8137520bc91e3d6fcc322529e20b1062a 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <linux/kernel.h>
 #include <linux/mlx5/driver.h>
+#include <linux/mlx5/qp.h>
 #include "mlx5_core.h"
 
 int mlx5_core_create_mkey(struct mlx5_core_dev *dev, u32 *mkey, u32 *in,
@@ -122,3 +123,23 @@ int mlx5_core_destroy_psv(struct mlx5_core_dev *dev, int psv_num)
        return mlx5_cmd_exec_in(dev, destroy_psv, in);
 }
 EXPORT_SYMBOL(mlx5_core_destroy_psv);
+
+__be32 mlx5_core_get_terminate_scatter_list_mkey(struct mlx5_core_dev *dev)
+{
+       u32 out[MLX5_ST_SZ_DW(query_special_contexts_out)] = {};
+       u32 in[MLX5_ST_SZ_DW(query_special_contexts_in)] = {};
+       u32 mkey;
+
+       if (!MLX5_CAP_GEN(dev, terminate_scatter_list_mkey))
+               return MLX5_TERMINATE_SCATTER_LIST_LKEY;
+
+       MLX5_SET(query_special_contexts_in, in, opcode,
+                MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS);
+       if (mlx5_cmd_exec_inout(dev, query_special_contexts, in, out))
+               return MLX5_TERMINATE_SCATTER_LIST_LKEY;
+
+       mkey = MLX5_GET(query_special_contexts_out, out,
+                       terminate_scatter_list_mkey);
+       return cpu_to_be32(mkey);
+}
+EXPORT_SYMBOL(mlx5_core_get_terminate_scatter_list_mkey);
index 2245d3b2f393bcd60affd0963d3340016502570a..843da89a903501dd8964bf5ba7de7967113fd5aa 100644 (file)
@@ -32,6 +32,7 @@ struct mlx5_irq {
        struct mlx5_irq_pool *pool;
        int refcount;
        struct msi_map map;
+       u32 pool_index;
 };
 
 struct mlx5_irq_table {
@@ -132,7 +133,7 @@ static void irq_release(struct mlx5_irq *irq)
        struct cpu_rmap *rmap;
 #endif
 
-       xa_erase(&pool->irqs, irq->map.index);
+       xa_erase(&pool->irqs, irq->pool_index);
        /* free_irq requires that affinity_hint and rmap will be cleared before
         * calling it. To satisfy this requirement, we call
         * irq_cpu_rmap_remove() to remove the notifier
@@ -140,7 +141,7 @@ static void irq_release(struct mlx5_irq *irq)
        irq_update_affinity_hint(irq->map.virq, NULL);
 #ifdef CONFIG_RFS_ACCEL
        rmap = mlx5_eq_table_get_rmap(pool->dev);
-       if (rmap && irq->map.index)
+       if (rmap)
                irq_cpu_rmap_remove(rmap, irq->map.virq);
 #endif
 
@@ -231,12 +232,13 @@ struct mlx5_irq *mlx5_irq_alloc(struct mlx5_irq_pool *pool, int i,
        if (!irq)
                return ERR_PTR(-ENOMEM);
        if (!i || !pci_msix_can_alloc_dyn(dev->pdev)) {
-               /* The vector at index 0 was already allocated.
-                * Just get the irq number. If dynamic irq is not supported
-                * vectors have also been allocated.
+               /* The vector at index 0 is always statically allocated. If
+                * dynamic irq is not supported all vectors are statically
+                * allocated. In both cases just get the irq number and set
+                * the index.
                 */
                irq->map.virq = pci_irq_vector(dev->pdev, i);
-               irq->map.index = 0;
+               irq->map.index = i;
        } else {
                irq->map = pci_msix_alloc_irq_at(dev->pdev, MSI_ANY_INDEX, af_desc);
                if (!irq->map.virq) {
@@ -276,11 +278,11 @@ struct mlx5_irq *mlx5_irq_alloc(struct mlx5_irq_pool *pool, int i,
        }
        irq->pool = pool;
        irq->refcount = 1;
-       irq->map.index = i;
-       err = xa_err(xa_store(&pool->irqs, irq->map.index, irq, GFP_KERNEL));
+       irq->pool_index = i;
+       err = xa_err(xa_store(&pool->irqs, irq->pool_index, irq, GFP_KERNEL));
        if (err) {
                mlx5_core_err(dev, "Failed to alloc xa entry for irq(%u). err = %d\n",
-                             irq->map.index, err);
+                             irq->pool_index, err);
                goto err_xa;
        }
        return irq;
@@ -567,13 +569,13 @@ int mlx5_irqs_request_vectors(struct mlx5_core_dev *dev, u16 *cpus, int nirqs,
        struct mlx5_irq *irq;
        int i;
 
-       af_desc.is_managed = 1;
+       af_desc.is_managed = false;
        for (i = 0; i < nirqs; i++) {
+               cpumask_clear(&af_desc.mask);
                cpumask_set_cpu(cpus[i], &af_desc.mask);
                irq = mlx5_irq_request(dev, i + 1, &af_desc, rmap);
                if (IS_ERR(irq))
                        break;
-               cpumask_clear(&af_desc.mask);
                irqs[i] = irq;
        }
 
@@ -691,6 +693,24 @@ static void irq_pools_destroy(struct mlx5_irq_table *table)
        irq_pool_free(table->pcif_pool);
 }
 
+static void mlx5_irq_pool_free_irqs(struct mlx5_irq_pool *pool)
+{
+       struct mlx5_irq *irq;
+       unsigned long index;
+
+       xa_for_each(&pool->irqs, index, irq)
+               free_irq(irq->map.virq, &irq->nh);
+}
+
+static void mlx5_irq_pools_free_irqs(struct mlx5_irq_table *table)
+{
+       if (table->sf_ctrl_pool) {
+               mlx5_irq_pool_free_irqs(table->sf_comp_pool);
+               mlx5_irq_pool_free_irqs(table->sf_ctrl_pool);
+       }
+       mlx5_irq_pool_free_irqs(table->pcif_pool);
+}
+
 /* irq_table API */
 
 int mlx5_irq_table_init(struct mlx5_core_dev *dev)
@@ -774,6 +794,17 @@ void mlx5_irq_table_destroy(struct mlx5_core_dev *dev)
        pci_free_irq_vectors(dev->pdev);
 }
 
+void mlx5_irq_table_free_irqs(struct mlx5_core_dev *dev)
+{
+       struct mlx5_irq_table *table = dev->priv.irq_table;
+
+       if (mlx5_core_is_sf(dev))
+               return;
+
+       mlx5_irq_pools_free_irqs(table);
+       pci_free_irq_vectors(dev->pdev);
+}
+
 int mlx5_irq_table_get_sfs_vec(struct mlx5_irq_table *table)
 {
        if (table->sf_comp_pool)
index e2f26d0bc61541f98d637d0c45f9c710c4325230..0692363cf80e4d8f2d31e4133faab797a03abf10 100644 (file)
@@ -63,6 +63,7 @@ static void mlx5_sf_dev_remove(struct auxiliary_device *adev)
        struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev);
        struct devlink *devlink = priv_to_devlink(sf_dev->mdev);
 
+       mlx5_drain_health_wq(sf_dev->mdev);
        devlink_unregister(devlink);
        mlx5_uninit_one(sf_dev->mdev);
        iounmap(sf_dev->mdev->iseg);
index 3835ba3f4ddac6a3b82aab154121d15b8ec4fb6a..1aa525e509f109277b03d53c11f51e18886fde95 100644 (file)
@@ -117,6 +117,8 @@ int mlx5dr_cmd_query_device(struct mlx5_core_dev *mdev,
        caps->gvmi              = MLX5_CAP_GEN(mdev, vhca_id);
        caps->flex_protocols    = MLX5_CAP_GEN(mdev, flex_parser_protocols);
        caps->sw_format_ver     = MLX5_CAP_GEN(mdev, steering_format_version);
+       caps->roce_caps.fl_rc_qp_when_roce_disabled =
+               MLX5_CAP_GEN(mdev, fl_rc_qp_when_roce_disabled);
 
        if (MLX5_CAP_GEN(mdev, roce)) {
                err = dr_cmd_query_nic_vport_roce_en(mdev, 0, &roce_en);
@@ -124,7 +126,7 @@ int mlx5dr_cmd_query_device(struct mlx5_core_dev *mdev,
                        return err;
 
                caps->roce_caps.roce_en = roce_en;
-               caps->roce_caps.fl_rc_qp_when_roce_disabled =
+               caps->roce_caps.fl_rc_qp_when_roce_disabled |=
                        MLX5_CAP_ROCE(mdev, fl_rc_qp_when_roce_disabled);
                caps->roce_caps.fl_rc_qp_when_roce_enabled =
                        MLX5_CAP_ROCE(mdev, fl_rc_qp_when_roce_enabled);
index 13e06a6a6b22af75704204eae5243f0288b71049..d6947fe13d560d141e8e2efa9c7be49a485abcc0 100644 (file)
@@ -213,6 +213,8 @@ struct mlx5dr_ptrn_mgr *mlx5dr_ptrn_mgr_create(struct mlx5dr_domain *dmn)
        }
 
        INIT_LIST_HEAD(&mgr->ptrn_list);
+       mutex_init(&mgr->modify_hdr_mutex);
+
        return mgr;
 
 free_mgr:
@@ -237,5 +239,6 @@ void mlx5dr_ptrn_mgr_destroy(struct mlx5dr_ptrn_mgr *mgr)
        }
 
        mlx5dr_icm_pool_destroy(mgr->ptrn_icm_pool);
+       mutex_destroy(&mgr->modify_hdr_mutex);
        kfree(mgr);
 }
index 9413aaf51251b798cc5fc70c861599041efbd687..e94fbb015efad7e1988e738980d2e1378e4d4d50 100644 (file)
@@ -15,7 +15,8 @@ static u32 dr_ste_crc32_calc(const void *input_data, size_t length)
 {
        u32 crc = crc32(0, input_data, length);
 
-       return (__force u32)htonl(crc);
+       return (__force u32)((crc >> 24) & 0xff) | ((crc << 8) & 0xff0000) |
+                           ((crc >> 8) & 0xff00) | ((crc << 24) & 0xff000000);
 }
 
 bool mlx5dr_ste_supp_ttl_cs_recalc(struct mlx5dr_cmd_caps *caps)
index afa3b92a6905f691dbd63649ccf4190f20e9bd48..0d5a41a2ae010914b50fac74b5c719c6aa3fa2cd 100644 (file)
@@ -245,12 +245,6 @@ static bool mlxbf_gige_rx_packet(struct mlxbf_gige *priv, int *rx_pkts)
 
                skb = priv->rx_skb[rx_pi_rem];
 
-               skb_put(skb, datalen);
-
-               skb->ip_summed = CHECKSUM_NONE; /* device did not checksum packet */
-
-               skb->protocol = eth_type_trans(skb, netdev);
-
                /* Alloc another RX SKB for this same index */
                rx_skb = mlxbf_gige_alloc_skb(priv, MLXBF_GIGE_DEFAULT_BUF_SZ,
                                              &rx_buf_dma, DMA_FROM_DEVICE);
@@ -259,6 +253,13 @@ static bool mlxbf_gige_rx_packet(struct mlxbf_gige *priv, int *rx_pkts)
                priv->rx_skb[rx_pi_rem] = rx_skb;
                dma_unmap_single(priv->dev, *rx_wqe_addr,
                                 MLXBF_GIGE_DEFAULT_BUF_SZ, DMA_FROM_DEVICE);
+
+               skb_put(skb, datalen);
+
+               skb->ip_summed = CHECKSUM_NONE; /* device did not checksum packet */
+
+               skb->protocol = eth_type_trans(skb, netdev);
+
                *rx_wqe_addr = rx_buf_dma;
        } else if (rx_cqe & MLXBF_GIGE_RX_CQE_PKT_STATUS_MAC_ERR) {
                priv->stats.rx_mac_errors++;
index 2b6e046e1d10bbc7fcec9f334e344eec90bb7d11..ee2698698d71a43bb71256a085f91daf603ac095 100644 (file)
@@ -1039,6 +1039,16 @@ static int lan966x_reset_switch(struct lan966x *lan966x)
 
        reset_control_reset(switch_reset);
 
+       /* Don't reinitialize the switch core, if it is already initialized. In
+        * case it is initialized twice, some pointers inside the queue system
+        * in HW will get corrupted and then after a while the queue system gets
+        * full and no traffic is passing through the switch. The issue is seen
+        * when loading and unloading the driver and sending traffic through the
+        * switch.
+        */
+       if (lan_rd(lan966x, SYS_RESET_CFG) & SYS_RESET_CFG_CORE_ENA)
+               return 0;
+
        lan_wr(SYS_RESET_CFG_CORE_ENA_SET(0), lan966x, SYS_RESET_CFG);
        lan_wr(SYS_RAM_INIT_RAM_INIT_SET(1), lan966x, SYS_RAM_INIT);
        ret = readx_poll_timeout(lan966x_ram_init, lan966x,
index 06d6292e09b332d9261806784738651e29d4dd8a..d907727c7b7a5324b66e319683d4d611638cd09c 100644 (file)
@@ -1279,8 +1279,6 @@ static void mana_poll_tx_cq(struct mana_cq *cq)
        if (comp_read < 1)
                return;
 
-       apc->eth_stats.tx_cqes = comp_read;
-
        for (i = 0; i < comp_read; i++) {
                struct mana_tx_comp_oob *cqe_oob;
 
@@ -1363,8 +1361,6 @@ static void mana_poll_tx_cq(struct mana_cq *cq)
                WARN_ON_ONCE(1);
 
        cq->work_done = pkt_transmitted;
-
-       apc->eth_stats.tx_cqes -= pkt_transmitted;
 }
 
 static void mana_post_pkt_rxq(struct mana_rxq *rxq)
@@ -1626,15 +1622,11 @@ static void mana_poll_rx_cq(struct mana_cq *cq)
 {
        struct gdma_comp *comp = cq->gdma_comp_buf;
        struct mana_rxq *rxq = cq->rxq;
-       struct mana_port_context *apc;
        int comp_read, i;
 
-       apc = netdev_priv(rxq->ndev);
-
        comp_read = mana_gd_poll_cq(cq->gdma_cq, comp, CQE_POLLING_BUFFER);
        WARN_ON_ONCE(comp_read > CQE_POLLING_BUFFER);
 
-       apc->eth_stats.rx_cqes = comp_read;
        rxq->xdp_flush = false;
 
        for (i = 0; i < comp_read; i++) {
@@ -1646,8 +1638,6 @@ static void mana_poll_rx_cq(struct mana_cq *cq)
                        return;
 
                mana_process_rx_cqe(rxq, cq, &comp[i]);
-
-               apc->eth_stats.rx_cqes--;
        }
 
        if (rxq->xdp_flush)
index a64c81410dc14cfcd44d263f0e79cc3337805ca4..0dc78679f62096ebf79da9d9af12b0519acb1e95 100644 (file)
@@ -13,11 +13,9 @@ static const struct {
 } mana_eth_stats[] = {
        {"stop_queue", offsetof(struct mana_ethtool_stats, stop_queue)},
        {"wake_queue", offsetof(struct mana_ethtool_stats, wake_queue)},
-       {"tx_cqes", offsetof(struct mana_ethtool_stats, tx_cqes)},
        {"tx_cq_err", offsetof(struct mana_ethtool_stats, tx_cqe_err)},
        {"tx_cqe_unknown_type", offsetof(struct mana_ethtool_stats,
                                        tx_cqe_unknown_type)},
-       {"rx_cqes", offsetof(struct mana_ethtool_stats, rx_cqes)},
        {"rx_coalesced_err", offsetof(struct mana_ethtool_stats,
                                        rx_coalesced_err)},
        {"rx_cqe_unknown_type", offsetof(struct mana_ethtool_stats,
index ef6fd3f6be3098f5ef84e5867d48663702f6bcc7..5595bfe84bbbbe975de9b39a5d8f2d8c5df1af05 100644 (file)
@@ -307,15 +307,15 @@ static const u32 vsc7514_sys_regmap[] = {
        REG(SYS_COUNT_DROP_YELLOW_PRIO_4,               0x000218),
        REG(SYS_COUNT_DROP_YELLOW_PRIO_5,               0x00021c),
        REG(SYS_COUNT_DROP_YELLOW_PRIO_6,               0x000220),
-       REG(SYS_COUNT_DROP_YELLOW_PRIO_7,               0x000214),
-       REG(SYS_COUNT_DROP_GREEN_PRIO_0,                0x000218),
-       REG(SYS_COUNT_DROP_GREEN_PRIO_1,                0x00021c),
-       REG(SYS_COUNT_DROP_GREEN_PRIO_2,                0x000220),
-       REG(SYS_COUNT_DROP_GREEN_PRIO_3,                0x000224),
-       REG(SYS_COUNT_DROP_GREEN_PRIO_4,                0x000228),
-       REG(SYS_COUNT_DROP_GREEN_PRIO_5,                0x00022c),
-       REG(SYS_COUNT_DROP_GREEN_PRIO_6,                0x000230),
-       REG(SYS_COUNT_DROP_GREEN_PRIO_7,                0x000234),
+       REG(SYS_COUNT_DROP_YELLOW_PRIO_7,               0x000224),
+       REG(SYS_COUNT_DROP_GREEN_PRIO_0,                0x000228),
+       REG(SYS_COUNT_DROP_GREEN_PRIO_1,                0x00022c),
+       REG(SYS_COUNT_DROP_GREEN_PRIO_2,                0x000230),
+       REG(SYS_COUNT_DROP_GREEN_PRIO_3,                0x000234),
+       REG(SYS_COUNT_DROP_GREEN_PRIO_4,                0x000238),
+       REG(SYS_COUNT_DROP_GREEN_PRIO_5,                0x00023c),
+       REG(SYS_COUNT_DROP_GREEN_PRIO_6,                0x000240),
+       REG(SYS_COUNT_DROP_GREEN_PRIO_7,                0x000244),
        REG(SYS_RESET_CFG,                              0x000508),
        REG(SYS_CMID,                                   0x00050c),
        REG(SYS_VLAN_ETYPE_CFG,                         0x000510),
index 094374df42b8c41513f968e44455f3e286fdcd84..38b8b10b03cd3b5c94a52925751e3171a5601a7e 100644 (file)
@@ -8,7 +8,7 @@
 
 #ifdef CONFIG_DCB
 /* DCB feature definitions */
-#define NFP_NET_MAX_DSCP       4
+#define NFP_NET_MAX_DSCP       64
 #define NFP_NET_MAX_TC         IEEE_8021QAZ_MAX_TCS
 #define NFP_NET_MAX_PRIO       8
 #define NFP_DCB_CFG_STRIDE     256
index 0605d1ee490dd0599dc6d69b31a52955d71ef9c8..7a549b834e970a5ac40330513e3220466d78acef 100644 (file)
@@ -6138,6 +6138,7 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
        return 0;
 
 out_error:
+       nv_mgmt_release_sema(dev);
        if (phystate_orig)
                writel(phystate|NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl);
 out_freering:
index a7e376e7e689c016e1d7cad675b27b0821002883..4b19803a7dd011c3fa13f2c65b6f886e8a291b7d 100644 (file)
@@ -616,10 +616,10 @@ struct rtl8169_private {
                struct work_struct work;
        } wk;
 
-       spinlock_t config25_lock;
-       spinlock_t mac_ocp_lock;
+       raw_spinlock_t config25_lock;
+       raw_spinlock_t mac_ocp_lock;
 
-       spinlock_t cfg9346_usage_lock;
+       raw_spinlock_t cfg9346_usage_lock;
        int cfg9346_usage_count;
 
        unsigned supports_gmii:1;
@@ -671,20 +671,20 @@ static void rtl_lock_config_regs(struct rtl8169_private *tp)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&tp->cfg9346_usage_lock, flags);
+       raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags);
        if (!--tp->cfg9346_usage_count)
                RTL_W8(tp, Cfg9346, Cfg9346_Lock);
-       spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);
 }
 
 static void rtl_unlock_config_regs(struct rtl8169_private *tp)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&tp->cfg9346_usage_lock, flags);
+       raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags);
        if (!tp->cfg9346_usage_count++)
                RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
-       spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);
 }
 
 static void rtl_pci_commit(struct rtl8169_private *tp)
@@ -698,10 +698,10 @@ static void rtl_mod_config2(struct rtl8169_private *tp, u8 clear, u8 set)
        unsigned long flags;
        u8 val;
 
-       spin_lock_irqsave(&tp->config25_lock, flags);
+       raw_spin_lock_irqsave(&tp->config25_lock, flags);
        val = RTL_R8(tp, Config2);
        RTL_W8(tp, Config2, (val & ~clear) | set);
-       spin_unlock_irqrestore(&tp->config25_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->config25_lock, flags);
 }
 
 static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set)
@@ -709,10 +709,10 @@ static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set)
        unsigned long flags;
        u8 val;
 
-       spin_lock_irqsave(&tp->config25_lock, flags);
+       raw_spin_lock_irqsave(&tp->config25_lock, flags);
        val = RTL_R8(tp, Config5);
        RTL_W8(tp, Config5, (val & ~clear) | set);
-       spin_unlock_irqrestore(&tp->config25_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->config25_lock, flags);
 }
 
 static bool rtl_is_8125(struct rtl8169_private *tp)
@@ -899,9 +899,9 @@ static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&tp->mac_ocp_lock, flags);
+       raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
        __r8168_mac_ocp_write(tp, reg, data);
-       spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
 }
 
 static u16 __r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
@@ -919,9 +919,9 @@ static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
        unsigned long flags;
        u16 val;
 
-       spin_lock_irqsave(&tp->mac_ocp_lock, flags);
+       raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
        val = __r8168_mac_ocp_read(tp, reg);
-       spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
 
        return val;
 }
@@ -932,10 +932,10 @@ static void r8168_mac_ocp_modify(struct rtl8169_private *tp, u32 reg, u16 mask,
        unsigned long flags;
        u16 data;
 
-       spin_lock_irqsave(&tp->mac_ocp_lock, flags);
+       raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
        data = __r8168_mac_ocp_read(tp, reg);
        __r8168_mac_ocp_write(tp, reg, (data & ~mask) | set);
-       spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
 }
 
 /* Work around a hw issue with RTL8168g PHY, the quirk disables
@@ -1420,14 +1420,14 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
                        r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0);
        }
 
-       spin_lock_irqsave(&tp->config25_lock, flags);
+       raw_spin_lock_irqsave(&tp->config25_lock, flags);
        for (i = 0; i < tmp; i++) {
                options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask;
                if (wolopts & cfg[i].opt)
                        options |= cfg[i].mask;
                RTL_W8(tp, cfg[i].reg, options);
        }
-       spin_unlock_irqrestore(&tp->config25_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->config25_lock, flags);
 
        switch (tp->mac_version) {
        case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
@@ -5179,9 +5179,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        tp->eee_adv = -1;
        tp->ocp_base = OCP_STD_PHY_BASE;
 
-       spin_lock_init(&tp->cfg9346_usage_lock);
-       spin_lock_init(&tp->config25_lock);
-       spin_lock_init(&tp->mac_ocp_lock);
+       raw_spin_lock_init(&tp->cfg9346_usage_lock);
+       raw_spin_lock_init(&tp->config25_lock);
+       raw_spin_lock_init(&tp->mac_ocp_lock);
 
        dev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,
                                                   struct pcpu_sw_netstats);
index 29afaddb598db4b32acebdfa34667365ab503c85..aace87139cea1088a15ef3a7720dff0edbaca86a 100644 (file)
@@ -1485,7 +1485,7 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd
 
        if (rswitch_get_num_cur_queues(gq) >= gq->ring_size - 1) {
                netif_stop_subqueue(ndev, 0);
-               return ret;
+               return NETDEV_TX_BUSY;
        }
 
        if (skb_put_padto(skb, ETH_ZLEN))
index d916877b5a9ad92414c36f317ea8aae41706cecd..be395cd8770bc71db641b710b90c3d00dc2f43fe 100644 (file)
@@ -378,7 +378,9 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
        efx->net_dev = net_dev;
        SET_NETDEV_DEV(net_dev, &efx->pci_dev->dev);
 
-       net_dev->features |= efx->type->offload_features;
+       /* enable all supported features except rx-fcs and rx-all */
+       net_dev->features |= efx->type->offload_features &
+                            ~(NETIF_F_RXFCS | NETIF_F_RXALL);
        net_dev->hw_features |= efx->type->offload_features;
        net_dev->hw_enc_features |= efx->type->offload_features;
        net_dev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_SG |
index 381b805659d39a11d5ceef2cf9d67cb2fba3bc8d..ef9971cbb695d2e82fb58268522295ce853ebffe 100644 (file)
@@ -171,9 +171,14 @@ static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
 
        rc = efx_mcdi_nvram_metadata(efx, partition_type, NULL, version, NULL,
                                     0);
+
+       /* If the partition does not exist, that is not an error. */
+       if (rc == -ENOENT)
+               return 0;
+
        if (rc) {
-               netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed\n",
-                         version_name);
+               netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed (rc=%d)\n",
+                         version_name, rc);
                return rc;
        }
 
@@ -187,36 +192,33 @@ static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
 static int efx_devlink_info_stored_versions(struct efx_nic *efx,
                                            struct devlink_info_req *req)
 {
-       int rc;
-
-       rc = efx_devlink_info_nvram_partition(efx, req,
-                                             NVRAM_PARTITION_TYPE_BUNDLE,
-                                             DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID);
-       if (rc)
-               return rc;
-
-       rc = efx_devlink_info_nvram_partition(efx, req,
-                                             NVRAM_PARTITION_TYPE_MC_FIRMWARE,
-                                             DEVLINK_INFO_VERSION_GENERIC_FW_MGMT);
-       if (rc)
-               return rc;
-
-       rc = efx_devlink_info_nvram_partition(efx, req,
-                                             NVRAM_PARTITION_TYPE_SUC_FIRMWARE,
-                                             EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC);
-       if (rc)
-               return rc;
-
-       rc = efx_devlink_info_nvram_partition(efx, req,
-                                             NVRAM_PARTITION_TYPE_EXPANSION_ROM,
-                                             EFX_DEVLINK_INFO_VERSION_FW_EXPROM);
-       if (rc)
-               return rc;
+       int err;
 
-       rc = efx_devlink_info_nvram_partition(efx, req,
-                                             NVRAM_PARTITION_TYPE_EXPANSION_UEFI,
-                                             EFX_DEVLINK_INFO_VERSION_FW_UEFI);
-       return rc;
+       /* We do not care here about the specific error but just if an error
+        * happened. The specific error will be reported inside the call
+        * through system messages, and if any error happened in any call
+        * below, we report it through extack.
+        */
+       err = efx_devlink_info_nvram_partition(efx, req,
+                                              NVRAM_PARTITION_TYPE_BUNDLE,
+                                              DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID);
+
+       err |= efx_devlink_info_nvram_partition(efx, req,
+                                               NVRAM_PARTITION_TYPE_MC_FIRMWARE,
+                                               DEVLINK_INFO_VERSION_GENERIC_FW_MGMT);
+
+       err |= efx_devlink_info_nvram_partition(efx, req,
+                                               NVRAM_PARTITION_TYPE_SUC_FIRMWARE,
+                                               EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC);
+
+       err |= efx_devlink_info_nvram_partition(efx, req,
+                                               NVRAM_PARTITION_TYPE_EXPANSION_ROM,
+                                               EFX_DEVLINK_INFO_VERSION_FW_EXPROM);
+
+       err |= efx_devlink_info_nvram_partition(efx, req,
+                                               NVRAM_PARTITION_TYPE_EXPANSION_UEFI,
+                                               EFX_DEVLINK_INFO_VERSION_FW_UEFI);
+       return err;
 }
 
 #define EFX_VER_FLAG(_f)       \
@@ -587,27 +589,20 @@ static int efx_devlink_info_get(struct devlink *devlink,
 {
        struct efx_devlink *devlink_private = devlink_priv(devlink);
        struct efx_nic *efx = devlink_private->efx;
-       int rc;
+       int err;
 
-       /* Several different MCDI commands are used. We report first error
-        * through extack returning at that point. Specific error
-        * information via system messages.
+       /* Several different MCDI commands are used. We report if errors
+        * happened through extack. Specific error information via system
+        * messages inside the calls.
         */
-       rc = efx_devlink_info_board_cfg(efx, req);
-       if (rc) {
-               NL_SET_ERR_MSG_MOD(extack, "Getting board info failed");
-               return rc;
-       }
-       rc = efx_devlink_info_stored_versions(efx, req);
-       if (rc) {
-               NL_SET_ERR_MSG_MOD(extack, "Getting stored versions failed");
-               return rc;
-       }
-       rc = efx_devlink_info_running_versions(efx, req);
-       if (rc) {
-               NL_SET_ERR_MSG_MOD(extack, "Getting running versions failed");
-               return rc;
-       }
+       err = efx_devlink_info_board_cfg(efx, req);
+
+       err |= efx_devlink_info_stored_versions(efx, req);
+
+       err |= efx_devlink_info_running_versions(efx, req);
+
+       if (err)
+               NL_SET_ERR_MSG_MOD(extack, "Errors when getting device info. Check system messages");
 
        return 0;
 }
index 0327639a628a91adccd4229bca56c30fb75b5c78..c004443c1d58c3eebe042489fb18b1430688cd27 100644 (file)
@@ -624,13 +624,12 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx,
        if (!found) { /* We don't care. */
                netif_dbg(efx, drv, efx->net_dev,
                          "Ignoring foreign filter that doesn't egdev us\n");
-               rc = -EOPNOTSUPP;
-               goto release;
+               return -EOPNOTSUPP;
        }
 
        rc = efx_mae_match_check_caps(efx, &match.mask, NULL);
        if (rc)
-               goto release;
+               return rc;
 
        if (efx_tc_match_is_encap(&match.mask)) {
                enum efx_encap_type type;
@@ -639,8 +638,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx,
                if (type == EFX_ENCAP_TYPE_NONE) {
                        NL_SET_ERR_MSG_MOD(extack,
                                           "Egress encap match on unsupported tunnel device");
-                       rc = -EOPNOTSUPP;
-                       goto release;
+                       return -EOPNOTSUPP;
                }
 
                rc = efx_mae_check_encap_type_supported(efx, type);
@@ -648,25 +646,24 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx,
                        NL_SET_ERR_MSG_FMT_MOD(extack,
                                               "Firmware reports no support for %s encap match",
                                               efx_tc_encap_type_name(type));
-                       goto release;
+                       return rc;
                }
 
                rc = efx_tc_flower_record_encap_match(efx, &match, type,
                                                      extack);
                if (rc)
-                       goto release;
+                       return rc;
        } else {
                /* This is not a tunnel decap rule, ignore it */
                netif_dbg(efx, drv, efx->net_dev,
                          "Ignoring foreign filter without encap match\n");
-               rc = -EOPNOTSUPP;
-               goto release;
+               return -EOPNOTSUPP;
        }
 
        rule = kzalloc(sizeof(*rule), GFP_USER);
        if (!rule) {
                rc = -ENOMEM;
-               goto release;
+               goto out_free;
        }
        INIT_LIST_HEAD(&rule->acts.list);
        rule->cookie = tc->cookie;
@@ -678,7 +675,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx,
                          "Ignoring already-offloaded rule (cookie %lx)\n",
                          tc->cookie);
                rc = -EEXIST;
-               goto release;
+               goto out_free;
        }
 
        act = kzalloc(sizeof(*act), GFP_USER);
@@ -843,6 +840,7 @@ release:
                                       efx_tc_match_action_ht_params);
                efx_tc_free_action_set_list(efx, &rule->acts, false);
        }
+out_free:
        kfree(rule);
        if (match.encap)
                efx_tc_flower_release_encap_match(efx, match.encap);
@@ -899,8 +897,7 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
                return rc;
        if (efx_tc_match_is_encap(&match.mask)) {
                NL_SET_ERR_MSG_MOD(extack, "Ingress enc_key matches not supported");
-               rc = -EOPNOTSUPP;
-               goto release;
+               return -EOPNOTSUPP;
        }
 
        if (tc->common.chain_index) {
@@ -924,9 +921,9 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
        if (old) {
                netif_dbg(efx, drv, efx->net_dev,
                          "Already offloaded rule (cookie %lx)\n", tc->cookie);
-               rc = -EEXIST;
                NL_SET_ERR_MSG_MOD(extack, "Rule already offloaded");
-               goto release;
+               kfree(rule);
+               return -EEXIST;
        }
 
        /* Parse actions */
index 4538f334df576677686bf01bac3197bfb8825a2f..d3c5306f1c41f7aca6f6a9170f7946a3abfe6cd0 100644 (file)
@@ -181,6 +181,7 @@ enum power_event {
 #define GMAC4_LPI_CTRL_STATUS  0xd0
 #define GMAC4_LPI_TIMER_CTRL   0xd4
 #define GMAC4_LPI_ENTRY_TIMER  0xd8
+#define GMAC4_MAC_ONEUS_TIC_COUNTER    0xdc
 
 /* LPI control and status defines */
 #define GMAC4_LPI_CTRL_STATUS_LPITCSE  BIT(21) /* LPI Tx Clock Stop Enable */
index afaec3fb9ab663bb009a02e12e8067df9ea98069..03b1c5a97826ec35a593aa6880fae858267099bd 100644 (file)
@@ -25,6 +25,7 @@ static void dwmac4_core_init(struct mac_device_info *hw,
        struct stmmac_priv *priv = netdev_priv(dev);
        void __iomem *ioaddr = hw->pcsr;
        u32 value = readl(ioaddr + GMAC_CONFIG);
+       u32 clk_rate;
 
        value |= GMAC_CORE_INIT;
 
@@ -47,6 +48,10 @@ static void dwmac4_core_init(struct mac_device_info *hw,
 
        writel(value, ioaddr + GMAC_CONFIG);
 
+       /* Configure LPI 1us counter to number of CSR clock ticks in 1us - 1 */
+       clk_rate = clk_get_rate(priv->plat->stmmac_clk);
+       writel((clk_rate / 1000000) - 1, ioaddr + GMAC4_MAC_ONEUS_TIC_COUNTER);
+
        /* Enable GMAC interrupts */
        value = GMAC_INT_DEFAULT_ENABLE;
 
index 0fca81507a779acafc11faa52aafeb41326b1f8e..52cab9de05f278cb2d344a28e8bf1751e780aa67 100644 (file)
@@ -7233,8 +7233,7 @@ int stmmac_dvr_probe(struct device *device,
        ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                            NETIF_F_RXCSUM;
        ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
-                            NETDEV_XDP_ACT_XSK_ZEROCOPY |
-                            NETDEV_XDP_ACT_NDO_XMIT;
+                            NETDEV_XDP_ACT_XSK_ZEROCOPY;
 
        ret = stmmac_tc_init(priv, priv);
        if (!ret) {
index 9d4d8c3dad0a3f769650d571ace87a4e77d292a7..aa6f16d3df649e8742584e0aacf83204acc1030c 100644 (file)
@@ -117,6 +117,9 @@ int stmmac_xdp_set_prog(struct stmmac_priv *priv, struct bpf_prog *prog,
                return -EOPNOTSUPP;
        }
 
+       if (!prog)
+               xdp_features_clear_redirect_target(dev);
+
        need_update = !!priv->xdp_prog != !!prog;
        if (if_running && need_update)
                stmmac_xdp_release(dev);
@@ -131,5 +134,8 @@ int stmmac_xdp_set_prog(struct stmmac_priv *priv, struct bpf_prog *prog,
        if (if_running && need_update)
                stmmac_xdp_open(dev);
 
+       if (prog)
+               xdp_features_set_redirect_target(dev, false);
+
        return 0;
 }
index 4ef05bad4613c9309a81b00ba896b365a698eec7..d61dfa250feb722b67352104b272dbeebd056f0d 100644 (file)
@@ -5077,6 +5077,8 @@ err_out_iounmap:
                cas_shutdown(cp);
        mutex_unlock(&cp->pm_mutex);
 
+       vfree(cp->fw_data);
+
        pci_iounmap(pdev, cp->regs);
 
 
index 2ee80ed140b72b1cf1702b19bf9bad69c36c7d47..afa1d56d9095c13fe65a09f76fbc99679d9d8624 100644 (file)
@@ -119,7 +119,7 @@ enum ipa_status_field_id {
 };
 
 /* Size in bytes of an IPA packet status structure */
-#define IPA_STATUS_SIZE                        sizeof(__le32[4])
+#define IPA_STATUS_SIZE                        sizeof(__le32[8])
 
 /* IPA status structure decoder; looks up field values for a structure */
 static u32 ipa_status_extract(struct ipa *ipa, const void *data,
index 460b3d4f2245f2adf8c757bfa52b732ba6c1e7eb..ab5133eb1d51783efdab2542265b4e0293e59af9 100644 (file)
@@ -436,6 +436,9 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb)
                goto err;
        }
        skb_dst_set(skb, &rt->dst);
+
+       memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+
        err = ip_local_out(net, skb->sk, skb);
        if (unlikely(net_xmit_eval(err)))
                dev->stats.tx_errors++;
@@ -474,6 +477,9 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
                goto err;
        }
        skb_dst_set(skb, dst);
+
+       memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
+
        err = ip6_local_out(net, skb->sk, skb);
        if (unlikely(net_xmit_eval(err)))
                dev->stats.tx_errors++;
index 1e0c206d0f2e68175e671b7d6ec65a869af6fc4f..da2001ea1f9937dd5c4e633dd3d781ef7d5f1dbb 100644 (file)
@@ -291,7 +291,8 @@ static int i2c_rollball_mii_cmd(struct mii_bus *bus, int bus_addr, u8 cmd,
        return i2c_transfer_rollball(i2c, msgs, ARRAY_SIZE(msgs));
 }
 
-static int i2c_mii_read_rollball(struct mii_bus *bus, int phy_id, int reg)
+static int i2c_mii_read_rollball(struct mii_bus *bus, int phy_id, int devad,
+                                int reg)
 {
        u8 buf[4], res[6];
        int bus_addr, ret;
@@ -302,7 +303,7 @@ static int i2c_mii_read_rollball(struct mii_bus *bus, int phy_id, int reg)
                return 0xffff;
 
        buf[0] = ROLLBALL_DATA_ADDR;
-       buf[1] = (reg >> 16) & 0x1f;
+       buf[1] = devad;
        buf[2] = (reg >> 8) & 0xff;
        buf[3] = reg & 0xff;
 
@@ -322,8 +323,8 @@ static int i2c_mii_read_rollball(struct mii_bus *bus, int phy_id, int reg)
        return val;
 }
 
-static int i2c_mii_write_rollball(struct mii_bus *bus, int phy_id, int reg,
-                                 u16 val)
+static int i2c_mii_write_rollball(struct mii_bus *bus, int phy_id, int devad,
+                                 int reg, u16 val)
 {
        int bus_addr, ret;
        u8 buf[6];
@@ -333,7 +334,7 @@ static int i2c_mii_write_rollball(struct mii_bus *bus, int phy_id, int reg,
                return 0;
 
        buf[0] = ROLLBALL_DATA_ADDR;
-       buf[1] = (reg >> 16) & 0x1f;
+       buf[1] = devad;
        buf[2] = (reg >> 8) & 0xff;
        buf[3] = reg & 0xff;
        buf[4] = val >> 8;
@@ -405,8 +406,8 @@ struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
                        return ERR_PTR(ret);
                }
 
-               mii->read = i2c_mii_read_rollball;
-               mii->write = i2c_mii_write_rollball;
+               mii->read_c45 = i2c_mii_read_rollball;
+               mii->write_c45 = i2c_mii_write_rollball;
                break;
        default:
                mii->read = i2c_mii_read_default_c22;
index 68fc55906e788581347ed6b0729c8287860cde1b..554837c21e73c060705e33fcad908cda77b908c0 100644 (file)
@@ -67,6 +67,7 @@ static int mvusb_mdio_probe(struct usb_interface *interface,
        struct device *dev = &interface->dev;
        struct mvusb_mdio *mvusb;
        struct mii_bus *mdio;
+       int ret;
 
        mdio = devm_mdiobus_alloc_size(dev, sizeof(*mvusb));
        if (!mdio)
@@ -87,7 +88,15 @@ static int mvusb_mdio_probe(struct usb_interface *interface,
        mdio->write = mvusb_mdio_write;
 
        usb_set_intfdata(interface, mvusb);
-       return of_mdiobus_register(mdio, dev->of_node);
+       ret = of_mdiobus_register(mdio, dev->of_node);
+       if (ret)
+               goto put_dev;
+
+       return 0;
+
+put_dev:
+       usb_put_dev(mvusb->udev);
+       return ret;
 }
 
 static void mvusb_mdio_disconnect(struct usb_interface *interface)
index 539cd43eae8d3e532ab551e317f855f429690fa5..72f25e778840f9330ca862e611732aabd11c340c 100644 (file)
@@ -873,7 +873,7 @@ int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
 
        switch (compat->an_mode) {
        case DW_AN_C73:
-               if (phylink_autoneg_inband(mode)) {
+               if (test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)) {
                        ret = xpcs_config_aneg_c73(xpcs, compat);
                        if (ret)
                                return ret;
@@ -1203,7 +1203,7 @@ static const struct xpcs_compat synopsys_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
        [DW_XPCS_2500BASEX] = {
                .supported = xpcs_2500basex_features,
                .interface = xpcs_2500basex_interfaces,
-               .num_interfaces = ARRAY_SIZE(xpcs_2500basex_features),
+               .num_interfaces = ARRAY_SIZE(xpcs_2500basex_interfaces),
                .an_mode = DW_2500BASEX,
        },
 };
index 9902fb1820997ea1fd46c1e50c82442707e5cebe..729db441797a0e8c8059c33e08fe998e0e18c188 100644 (file)
@@ -40,6 +40,11 @@ static inline int bcm_phy_write_exp_sel(struct phy_device *phydev,
        return bcm_phy_write_exp(phydev, reg | MII_BCM54XX_EXP_SEL_ER, val);
 }
 
+static inline int bcm_phy_read_exp_sel(struct phy_device *phydev, u16 reg)
+{
+       return bcm_phy_read_exp(phydev, reg | MII_BCM54XX_EXP_SEL_ER);
+}
+
 int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val);
 int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum);
 
index 06be71ecd2f8e7b1043b50a5767fecf0af05bc9a..f8c17a253f8b37b8b1590d1c7f22cf6616fc57fc 100644 (file)
@@ -486,7 +486,7 @@ static int bcm7xxx_16nm_ephy_afe_config(struct phy_device *phydev)
        bcm_phy_write_misc(phydev, 0x0038, 0x0002, 0xede0);
 
        /* Read CORE_EXPA9 */
-       tmp = bcm_phy_read_exp(phydev, 0x00a9);
+       tmp = bcm_phy_read_exp_sel(phydev, 0x00a9);
        /* CORE_EXPA9[6:1] is rcalcode[5:0] */
        rcalcode = (tmp & 0x7e) / 2;
        /* Correct RCAL code + 1 is -1% rprogr, LP: +16 */
index d75f526a20a49b6a65889c41adeb1395dcea002c..76f5a2402fb060dcc6c85aa4f6f6727f9c105317 100644 (file)
@@ -44,6 +44,7 @@
 #define DP83867_STRAP_STS1     0x006E
 #define DP83867_STRAP_STS2     0x006f
 #define DP83867_RGMIIDCTL      0x0086
+#define DP83867_DSP_FFE_CFG    0x012c
 #define DP83867_RXFCFG         0x0134
 #define DP83867_RXFPMD1        0x0136
 #define DP83867_RXFPMD2        0x0137
@@ -941,8 +942,27 @@ static int dp83867_phy_reset(struct phy_device *phydev)
 
        usleep_range(10, 20);
 
-       return phy_modify(phydev, MII_DP83867_PHYCTRL,
+       err = phy_modify(phydev, MII_DP83867_PHYCTRL,
                         DP83867_PHYCR_FORCE_LINK_GOOD, 0);
+       if (err < 0)
+               return err;
+
+       /* Configure the DSP Feedforward Equalizer Configuration register to
+        * improve short cable (< 1 meter) performance. This will not affect
+        * long cable performance.
+        */
+       err = phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_DSP_FFE_CFG,
+                           0x0e81);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESTART);
+       if (err < 0)
+               return err;
+
+       usleep_range(10, 20);
+
+       return 0;
 }
 
 static void dp83867_link_change_notify(struct phy_device *phydev)
index a50235fdf7d99d2f5db21dc8e002a0830223ae08..defe5cc6d4fcef4754edfb0aa5a1d6e562e0b282 100644 (file)
@@ -179,6 +179,7 @@ enum rgmii_clock_delay {
 #define VSC8502_RGMII_CNTL               20
 #define VSC8502_RGMII_RX_DELAY_MASK      0x0070
 #define VSC8502_RGMII_TX_DELAY_MASK      0x0007
+#define VSC8502_RGMII_RX_CLK_DISABLE     0x0800
 
 #define MSCC_PHY_WOL_LOWER_MAC_ADDR      21
 #define MSCC_PHY_WOL_MID_MAC_ADDR        22
@@ -276,6 +277,7 @@ enum rgmii_clock_delay {
 /* Microsemi PHY ID's
  *   Code assumes lowest nibble is 0
  */
+#define PHY_ID_VSC8501                   0x00070530
 #define PHY_ID_VSC8502                   0x00070630
 #define PHY_ID_VSC8504                   0x000704c0
 #define PHY_ID_VSC8514                   0x00070670
index 62bf99e45af16d86ff80428af812e34183888715..28df8a2e4230f3ffd6f559e8ac9521cedc7d0100 100644 (file)
@@ -519,16 +519,27 @@ out_unlock:
  *  * 2.0 ns (which causes the data to be sampled at exactly half way between
  *    clock transitions at 1000 Mbps) if delays should be enabled
  */
-static int vsc85xx_rgmii_set_skews(struct phy_device *phydev, u32 rgmii_cntl,
-                                  u16 rgmii_rx_delay_mask,
-                                  u16 rgmii_tx_delay_mask)
+static int vsc85xx_update_rgmii_cntl(struct phy_device *phydev, u32 rgmii_cntl,
+                                    u16 rgmii_rx_delay_mask,
+                                    u16 rgmii_tx_delay_mask)
 {
        u16 rgmii_rx_delay_pos = ffs(rgmii_rx_delay_mask) - 1;
        u16 rgmii_tx_delay_pos = ffs(rgmii_tx_delay_mask) - 1;
        u16 reg_val = 0;
-       int rc;
+       u16 mask = 0;
+       int rc = 0;
 
-       mutex_lock(&phydev->lock);
+       /* For traffic to pass, the VSC8502 family needs the RX_CLK disable bit
+        * to be unset for all PHY modes, so do that as part of the paged
+        * register modification.
+        * For some family members (like VSC8530/31/40/41) this bit is reserved
+        * and read-only, and the RX clock is enabled by default.
+        */
+       if (rgmii_cntl == VSC8502_RGMII_CNTL)
+               mask |= VSC8502_RGMII_RX_CLK_DISABLE;
+
+       if (phy_interface_is_rgmii(phydev))
+               mask |= rgmii_rx_delay_mask | rgmii_tx_delay_mask;
 
        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
            phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
@@ -537,31 +548,20 @@ static int vsc85xx_rgmii_set_skews(struct phy_device *phydev, u32 rgmii_cntl,
            phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
                reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_tx_delay_pos;
 
-       rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
-                             rgmii_cntl,
-                             rgmii_rx_delay_mask | rgmii_tx_delay_mask,
-                             reg_val);
-
-       mutex_unlock(&phydev->lock);
+       if (mask)
+               rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
+                                     rgmii_cntl, mask, reg_val);
 
        return rc;
 }
 
 static int vsc85xx_default_config(struct phy_device *phydev)
 {
-       int rc;
-
        phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
 
-       if (phy_interface_mode_is_rgmii(phydev->interface)) {
-               rc = vsc85xx_rgmii_set_skews(phydev, VSC8502_RGMII_CNTL,
-                                            VSC8502_RGMII_RX_DELAY_MASK,
-                                            VSC8502_RGMII_TX_DELAY_MASK);
-               if (rc)
-                       return rc;
-       }
-
-       return 0;
+       return vsc85xx_update_rgmii_cntl(phydev, VSC8502_RGMII_CNTL,
+                                        VSC8502_RGMII_RX_DELAY_MASK,
+                                        VSC8502_RGMII_TX_DELAY_MASK);
 }
 
 static int vsc85xx_get_tunable(struct phy_device *phydev,
@@ -1758,13 +1758,11 @@ static int vsc8584_config_init(struct phy_device *phydev)
        if (ret)
                return ret;
 
-       if (phy_interface_is_rgmii(phydev)) {
-               ret = vsc85xx_rgmii_set_skews(phydev, VSC8572_RGMII_CNTL,
-                                             VSC8572_RGMII_RX_DELAY_MASK,
-                                             VSC8572_RGMII_TX_DELAY_MASK);
-               if (ret)
-                       return ret;
-       }
+       ret = vsc85xx_update_rgmii_cntl(phydev, VSC8572_RGMII_CNTL,
+                                       VSC8572_RGMII_RX_DELAY_MASK,
+                                       VSC8572_RGMII_TX_DELAY_MASK);
+       if (ret)
+               return ret;
 
        ret = genphy_soft_reset(phydev);
        if (ret)
@@ -2316,6 +2314,30 @@ static int vsc85xx_probe(struct phy_device *phydev)
 
 /* Microsemi VSC85xx PHYs */
 static struct phy_driver vsc85xx_driver[] = {
+{
+       .phy_id         = PHY_ID_VSC8501,
+       .name           = "Microsemi GE VSC8501 SyncE",
+       .phy_id_mask    = 0xfffffff0,
+       /* PHY_BASIC_FEATURES */
+       .soft_reset     = &genphy_soft_reset,
+       .config_init    = &vsc85xx_config_init,
+       .config_aneg    = &vsc85xx_config_aneg,
+       .read_status    = &vsc85xx_read_status,
+       .handle_interrupt = vsc85xx_handle_interrupt,
+       .config_intr    = &vsc85xx_config_intr,
+       .suspend        = &genphy_suspend,
+       .resume         = &genphy_resume,
+       .probe          = &vsc85xx_probe,
+       .set_wol        = &vsc85xx_wol_set,
+       .get_wol        = &vsc85xx_wol_get,
+       .get_tunable    = &vsc85xx_get_tunable,
+       .set_tunable    = &vsc85xx_set_tunable,
+       .read_page      = &vsc85xx_phy_read_page,
+       .write_page     = &vsc85xx_phy_write_page,
+       .get_sset_count = &vsc85xx_get_sset_count,
+       .get_strings    = &vsc85xx_get_strings,
+       .get_stats      = &vsc85xx_get_stats,
+},
 {
        .phy_id         = PHY_ID_VSC8502,
        .name           = "Microsemi GE VSC8502 SyncE",
@@ -2656,6 +2678,8 @@ static struct phy_driver vsc85xx_driver[] = {
 module_phy_driver(vsc85xx_driver);
 
 static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
+       { PHY_ID_VSC8501, 0xfffffff0, },
+       { PHY_ID_VSC8502, 0xfffffff0, },
        { PHY_ID_VSC8504, 0xfffffff0, },
        { PHY_ID_VSC8514, 0xfffffff0, },
        { PHY_ID_VSC8530, 0xfffffff0, },
index 6301a9abfb95596647e81e9071ca7828e54d6bcf..ea1073adc5a16a6b531e9f1f2c51869dad8ead80 100644 (file)
@@ -274,13 +274,6 @@ static int gpy_config_init(struct phy_device *phydev)
        return ret < 0 ? ret : 0;
 }
 
-static bool gpy_has_broken_mdint(struct phy_device *phydev)
-{
-       /* At least these PHYs are known to have broken interrupt handling */
-       return phydev->drv->phy_id == PHY_ID_GPY215B ||
-              phydev->drv->phy_id == PHY_ID_GPY215C;
-}
-
 static int gpy_probe(struct phy_device *phydev)
 {
        struct device *dev = &phydev->mdio.dev;
@@ -300,8 +293,7 @@ static int gpy_probe(struct phy_device *phydev)
        phydev->priv = priv;
        mutex_init(&priv->mbox_lock);
 
-       if (gpy_has_broken_mdint(phydev) &&
-           !device_property_present(dev, "maxlinear,use-broken-interrupts"))
+       if (!device_property_present(dev, "maxlinear,use-broken-interrupts"))
                phydev->dev_flags |= PHY_F_NO_IRQ;
 
        fw_version = phy_read(phydev, PHY_FWV);
@@ -659,11 +651,9 @@ static irqreturn_t gpy_handle_interrupt(struct phy_device *phydev)
         * frame. Therefore, polling is the best we can do and won't do any more
         * harm.
         * It was observed that this bug happens on link state and link speed
-        * changes on a GPY215B and GYP215C independent of the firmware version
-        * (which doesn't mean that this list is exhaustive).
+        * changes independent of the firmware version.
         */
-       if (gpy_has_broken_mdint(phydev) &&
-           (reg & (PHY_IMASK_LSTC | PHY_IMASK_LSPC))) {
+       if (reg & (PHY_IMASK_LSTC | PHY_IMASK_LSPC)) {
                reg = gpy_mbox_read(phydev, REG_GPIO0_OUT);
                if (reg < 0) {
                        phy_error(phydev);
index a4111f1be375738033042f3c86fcba8197c528bb..e237949deee64f486695557ba2396f4173993270 100644 (file)
@@ -2225,6 +2225,10 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
 
        ASSERT_RTNL();
 
+       /* Mask out unsupported advertisements */
+       linkmode_and(config.advertising, kset->link_modes.advertising,
+                    pl->supported);
+
        if (pl->phydev) {
                /* We can rely on phylib for this update; we also do not need
                 * to update the pl->link_config settings:
@@ -2249,10 +2253,6 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
 
        config = pl->link_config;
 
-       /* Mask out unsupported advertisements */
-       linkmode_and(config.advertising, kset->link_modes.advertising,
-                    pl->supported);
-
        /* FIXME: should we reject autoneg if phy/mac does not support it? */
        switch (kset->base.autoneg) {
        case AUTONEG_DISABLE:
index ce993cc75bf3106cd7fe71ab9d4188c6ac09af27..d30d730ed5a71b8cc31880acc0f82d4b0f65f739 100644 (file)
@@ -742,7 +742,7 @@ static ssize_t tap_get_user(struct tap_queue *q, void *msg_control,
 
        /* Move network header to the right position for VLAN tagged packets */
        if (eth_type_vlan(skb->protocol) &&
-           __vlan_get_protocol(skb, skb->protocol, &depth) != 0)
+           vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
                skb_set_network_header(skb, depth);
 
        /* copy skb_ubuf_info for callback when skb has no error */
@@ -1197,7 +1197,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
 
        /* Move network header to the right position for VLAN tagged packets */
        if (eth_type_vlan(skb->protocol) &&
-           __vlan_get_protocol(skb, skb->protocol, &depth) != 0)
+           vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
                skb_set_network_header(skb, depth);
 
        rcu_read_lock();
index d10606f257c43345e1d293dd462cdf77fc37497b..555b0b1e9a7893ac828fa2e9488d1d3d7df3c064 100644 (file)
@@ -1629,6 +1629,7 @@ static int team_init(struct net_device *dev)
 
        team->dev = dev;
        team_set_no_mode(team);
+       team->notifier_ctx = false;
 
        team->pcpu_stats = netdev_alloc_pcpu_stats(struct team_pcpu_stats);
        if (!team->pcpu_stats)
@@ -3022,7 +3023,11 @@ static int team_device_event(struct notifier_block *unused,
                team_del_slave(port->team->dev, dev);
                break;
        case NETDEV_FEAT_CHANGE:
-               team_compute_features(port->team);
+               if (!port->team->notifier_ctx) {
+                       port->team->notifier_ctx = true;
+                       team_compute_features(port->team);
+                       port->team->notifier_ctx = false;
+               }
                break;
        case NETDEV_PRECHANGEMTU:
                /* Forbid to change mtu of underlaying device */
index d4d0a41a905a7e7fb332af8279136041b9229f23..d75456adc62ac82a4f9da10c50c48266c5a9a0c0 100644 (file)
@@ -1977,6 +1977,14 @@ napi_busy:
                int queue_len;
 
                spin_lock_bh(&queue->lock);
+
+               if (unlikely(tfile->detached)) {
+                       spin_unlock_bh(&queue->lock);
+                       rcu_read_unlock();
+                       err = -EBUSY;
+                       goto free_skb;
+               }
+
                __skb_queue_tail(queue, skb);
                queue_len = skb_queue_len(queue);
                spin_unlock(&queue->lock);
@@ -2512,6 +2520,13 @@ build:
        if (tfile->napi_enabled) {
                queue = &tfile->sk.sk_write_queue;
                spin_lock(&queue->lock);
+
+               if (unlikely(tfile->detached)) {
+                       spin_unlock(&queue->lock);
+                       kfree_skb(skb);
+                       return -EBUSY;
+               }
+
                __skb_queue_tail(queue, skb);
                spin_unlock(&queue->lock);
                ret = 1;
index 6ce8f4f0c70e898c5ebb7198c46ac6a38f5b588f..db05622f1f703ec6fc147935c296640c55499a4b 100644 (file)
@@ -181,9 +181,12 @@ static u32 cdc_ncm_check_tx_max(struct usbnet *dev, u32 new_tx)
        else
                min = ctx->max_datagram_size + ctx->max_ndp_size + sizeof(struct usb_cdc_ncm_nth32);
 
-       max = min_t(u32, CDC_NCM_NTB_MAX_SIZE_TX, le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize));
-       if (max == 0)
+       if (le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize) == 0)
                max = CDC_NCM_NTB_MAX_SIZE_TX; /* dwNtbOutMaxSize not set */
+       else
+               max = clamp_t(u32, le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize),
+                             USB_CDC_NCM_NTB_MIN_OUT_SIZE,
+                             CDC_NCM_NTB_MAX_SIZE_TX);
 
        /* some devices set dwNtbOutMaxSize too low for the above default */
        min = min(min, max);
@@ -1244,6 +1247,9 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
                         * further.
                         */
                        if (skb_out == NULL) {
+                               /* If even the smallest allocation fails, abort. */
+                               if (ctx->tx_curr_size == USB_CDC_NCM_NTB_MIN_OUT_SIZE)
+                                       goto alloc_failed;
                                ctx->tx_low_mem_max_cnt = min(ctx->tx_low_mem_max_cnt + 1,
                                                              (unsigned)CDC_NCM_LOW_MEM_MAX_CNT);
                                ctx->tx_low_mem_val = ctx->tx_low_mem_max_cnt;
@@ -1262,13 +1268,8 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
                        skb_out = alloc_skb(ctx->tx_curr_size, GFP_ATOMIC);
 
                        /* No allocation possible so we will abort */
-                       if (skb_out == NULL) {
-                               if (skb != NULL) {
-                                       dev_kfree_skb_any(skb);
-                                       dev->net->stats.tx_dropped++;
-                               }
-                               goto exit_no_skb;
-                       }
+                       if (!skb_out)
+                               goto alloc_failed;
                        ctx->tx_low_mem_val--;
                }
                if (ctx->is_ndp16) {
@@ -1461,6 +1462,11 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
 
        return skb_out;
 
+alloc_failed:
+       if (skb) {
+               dev_kfree_skb_any(skb);
+               dev->net->stats.tx_dropped++;
+       }
 exit_no_skb:
        /* Start timer, if there is a remaining non-empty skb */
        if (ctx->tx_curr_skb != NULL && n > 0)
index 571e37e67f9ce1706de16d3f4a4f9c883a6e8992..f1865d047971b5dc4946fbefec5c428ec2e1c8f5 100644 (file)
@@ -1325,7 +1325,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x2001, 0x7e3d, 4)},    /* D-Link DWM-222 A2 */
        {QMI_FIXED_INTF(0x2020, 0x2031, 4)},    /* Olicard 600 */
        {QMI_FIXED_INTF(0x2020, 0x2033, 4)},    /* BroadMobi BM806U */
-       {QMI_FIXED_INTF(0x2020, 0x2060, 4)},    /* BroadMobi BM818 */
+       {QMI_QUIRK_SET_DTR(0x2020, 0x2060, 4)}, /* BroadMobi BM818 */
        {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)},    /* Sierra Wireless MC7700 */
        {QMI_FIXED_INTF(0x114f, 0x68a2, 8)},    /* Sierra Wireless MC7750 */
        {QMI_FIXED_INTF(0x1199, 0x68a2, 8)},    /* Sierra Wireless MC7710 in QMI mode */
index a12ae26db0e223e57b691b0dc0728b97734d0659..56ca1d27030428bde3f0cd1c8c1738650ae46ca2 100644 (file)
@@ -1868,6 +1868,38 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
        return received;
 }
 
+static void virtnet_disable_queue_pair(struct virtnet_info *vi, int qp_index)
+{
+       virtnet_napi_tx_disable(&vi->sq[qp_index].napi);
+       napi_disable(&vi->rq[qp_index].napi);
+       xdp_rxq_info_unreg(&vi->rq[qp_index].xdp_rxq);
+}
+
+static int virtnet_enable_queue_pair(struct virtnet_info *vi, int qp_index)
+{
+       struct net_device *dev = vi->dev;
+       int err;
+
+       err = xdp_rxq_info_reg(&vi->rq[qp_index].xdp_rxq, dev, qp_index,
+                              vi->rq[qp_index].napi.napi_id);
+       if (err < 0)
+               return err;
+
+       err = xdp_rxq_info_reg_mem_model(&vi->rq[qp_index].xdp_rxq,
+                                        MEM_TYPE_PAGE_SHARED, NULL);
+       if (err < 0)
+               goto err_xdp_reg_mem_model;
+
+       virtnet_napi_enable(vi->rq[qp_index].vq, &vi->rq[qp_index].napi);
+       virtnet_napi_tx_enable(vi, vi->sq[qp_index].vq, &vi->sq[qp_index].napi);
+
+       return 0;
+
+err_xdp_reg_mem_model:
+       xdp_rxq_info_unreg(&vi->rq[qp_index].xdp_rxq);
+       return err;
+}
+
 static int virtnet_open(struct net_device *dev)
 {
        struct virtnet_info *vi = netdev_priv(dev);
@@ -1881,22 +1913,20 @@ static int virtnet_open(struct net_device *dev)
                        if (!try_fill_recv(vi, &vi->rq[i], GFP_KERNEL))
                                schedule_delayed_work(&vi->refill, 0);
 
-               err = xdp_rxq_info_reg(&vi->rq[i].xdp_rxq, dev, i, vi->rq[i].napi.napi_id);
+               err = virtnet_enable_queue_pair(vi, i);
                if (err < 0)
-                       return err;
-
-               err = xdp_rxq_info_reg_mem_model(&vi->rq[i].xdp_rxq,
-                                                MEM_TYPE_PAGE_SHARED, NULL);
-               if (err < 0) {
-                       xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
-                       return err;
-               }
-
-               virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
-               virtnet_napi_tx_enable(vi, vi->sq[i].vq, &vi->sq[i].napi);
+                       goto err_enable_qp;
        }
 
        return 0;
+
+err_enable_qp:
+       disable_delayed_refill(vi);
+       cancel_delayed_work_sync(&vi->refill);
+
+       for (i--; i >= 0; i--)
+               virtnet_disable_queue_pair(vi, i);
+       return err;
 }
 
 static int virtnet_poll_tx(struct napi_struct *napi, int budget)
@@ -2305,11 +2335,8 @@ static int virtnet_close(struct net_device *dev)
        /* Make sure refill_work doesn't re-enable napi! */
        cancel_delayed_work_sync(&vi->refill);
 
-       for (i = 0; i < vi->max_queue_pairs; i++) {
-               virtnet_napi_tx_disable(&vi->sq[i].napi);
-               napi_disable(&vi->rq[i].napi);
-               xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
-       }
+       for (i = 0; i < vi->max_queue_pairs; i++)
+               virtnet_disable_queue_pair(vi, i);
 
        return 0;
 }
index 9fc7c088a539e3728631ef41bf49004e60fa17f5..67b4bac048e585bd336196b8004fa6555d6abd0c 100644 (file)
@@ -651,7 +651,7 @@ struct b43_iv {
        union {
                __be16 d16;
                __be32 d32;
-       } data __packed;
+       } __packed data;
 } __packed;
 
 
index 6b0cec467938fc555f23f0d464086afec69181d9..f49365d14619f39d05535e0b82b4e7f2228fbfa5 100644 (file)
@@ -379,7 +379,7 @@ struct b43legacy_iv {
        union {
                __be16 d16;
                __be32 d32;
-       } data __packed;
+       } __packed data;
 } __packed;
 
 #define B43legacy_PHYMODE(phytype)     (1 << (phytype))
index ff710b0b5071a19b60e8f5d3a7fe1e22cd7b75a9..00679a990e3dac9bc9b71c0941a737ec0338ccc4 100644 (file)
@@ -1039,6 +1039,11 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
        struct brcmf_sdio_dev *sdiodev;
        struct brcmf_bus *bus_if;
 
+       if (!id) {
+               dev_err(&func->dev, "Error no sdio_device_id passed for %x:%x\n", func->vendor, func->device);
+               return -ENODEV;
+       }
+
        brcmf_dbg(SDIO, "Enter\n");
        brcmf_dbg(SDIO, "Class=%x\n", func->class);
        brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor);
index 59f3e9c5e13907bec4902210ddc7024829b2024d..80220685f5e4514782a1179d3195cbd34cd890b3 100644 (file)
@@ -2394,6 +2394,9 @@ static void brcmf_pcie_debugfs_create(struct device *dev)
 }
 #endif
 
+/* Forward declaration for pci_match_id() call */
+static const struct pci_device_id brcmf_pcie_devid_table[];
+
 static int
 brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -2404,6 +2407,14 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        struct brcmf_core *core;
        struct brcmf_bus *bus;
 
+       if (!id) {
+               id = pci_match_id(brcmf_pcie_devid_table, pdev);
+               if (!id) {
+                       pci_err(pdev, "Error could not find pci_device_id for %x:%x\n", pdev->vendor, pdev->device);
+                       return -ENODEV;
+               }
+       }
+
        brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device);
 
        ret = -ENOMEM;
index 246843aeb6964af25f5fc9b6a64d0b9e169dc4de..2178675ae1a44d0e04afdd4d26ad6aa0625da8cf 100644 (file)
@@ -1331,6 +1331,9 @@ brcmf_usb_disconnect_cb(struct brcmf_usbdev_info *devinfo)
        brcmf_usb_detach(devinfo);
 }
 
+/* Forward declaration for usb_match_id() call */
+static const struct usb_device_id brcmf_usb_devid_table[];
+
 static int
 brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
@@ -1342,6 +1345,14 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
        u32 num_of_eps;
        u8 endpoint_num, ep;
 
+       if (!id) {
+               id = usb_match_id(intf, brcmf_usb_devid_table);
+               if (!id) {
+                       dev_err(&intf->dev, "Error could not find matching usb_device_id\n");
+                       return -ENODEV;
+               }
+       }
+
        brcmf_dbg(USB, "Enter 0x%04x:0x%04x\n", id->idVendor, id->idProduct);
 
        devinfo = kzalloc(sizeof(*devinfo), GFP_ATOMIC);
index 5f4a51310add082ecd5c931883ff4926fae0ed5d..cb9181f05501130b3cd6fb9cf348996397f6082c 100644 (file)
@@ -38,7 +38,7 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = {
        },
        { .ident = "ASUS",
          .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek COMPUTER INC."),
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
                },
        },
        {}
index d9faaae01abd22b149566dfbd6eda80672c59ea6..55219974b92bf73c6ab70aa3e53ca4408257753a 100644 (file)
@@ -1664,14 +1664,10 @@ static __le32 iwl_get_mon_reg(struct iwl_fw_runtime *fwrt, u32 alloc_id,
 }
 
 static void *
-iwl_dump_ini_mon_fill_header(struct iwl_fw_runtime *fwrt,
-                            struct iwl_dump_ini_region_data *reg_data,
+iwl_dump_ini_mon_fill_header(struct iwl_fw_runtime *fwrt, u32 alloc_id,
                             struct iwl_fw_ini_monitor_dump *data,
                             const struct iwl_fw_mon_regs *addrs)
 {
-       struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
-       u32 alloc_id = le32_to_cpu(reg->dram_alloc_id);
-
        if (!iwl_trans_grab_nic_access(fwrt->trans)) {
                IWL_ERR(fwrt, "Failed to get monitor header\n");
                return NULL;
@@ -1702,8 +1698,10 @@ iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt,
                                  void *data, u32 data_len)
 {
        struct iwl_fw_ini_monitor_dump *mon_dump = (void *)data;
+       struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
+       u32 alloc_id = le32_to_cpu(reg->dram_alloc_id);
 
-       return iwl_dump_ini_mon_fill_header(fwrt, reg_data, mon_dump,
+       return iwl_dump_ini_mon_fill_header(fwrt, alloc_id, mon_dump,
                                            &fwrt->trans->cfg->mon_dram_regs);
 }
 
@@ -1713,8 +1711,10 @@ iwl_dump_ini_mon_smem_fill_header(struct iwl_fw_runtime *fwrt,
                                  void *data, u32 data_len)
 {
        struct iwl_fw_ini_monitor_dump *mon_dump = (void *)data;
+       struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
+       u32 alloc_id = le32_to_cpu(reg->internal_buffer.alloc_id);
 
-       return iwl_dump_ini_mon_fill_header(fwrt, reg_data, mon_dump,
+       return iwl_dump_ini_mon_fill_header(fwrt, alloc_id, mon_dump,
                                            &fwrt->trans->cfg->mon_smem_regs);
 }
 
@@ -1725,7 +1725,10 @@ iwl_dump_ini_mon_dbgi_fill_header(struct iwl_fw_runtime *fwrt,
 {
        struct iwl_fw_ini_monitor_dump *mon_dump = (void *)data;
 
-       return iwl_dump_ini_mon_fill_header(fwrt, reg_data, mon_dump,
+       return iwl_dump_ini_mon_fill_header(fwrt,
+                                           /* no offset calculation later */
+                                           IWL_FW_INI_ALLOCATION_ID_DBGC1,
+                                           mon_dump,
                                            &fwrt->trans->cfg->mon_dbgi_regs);
 }
 
index 3963a0d4ed0427ba004e0bb5f846df5ab4eb8332..652a603c4500efed3be6162d4f26a520eeda3f93 100644 (file)
@@ -526,6 +526,11 @@ iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                rcu_read_lock();
 
                sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id]);
+               if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) {
+                       rcu_read_unlock();
+                       return PTR_ERR_OR_ZERO(sta);
+               }
+
                if (sta->mfp && (peer->ftm.trigger_based || peer->ftm.non_trigger_based))
                        FTM_PUT_FLAG(PMF);
 
index b35c96cf7ad24d5f6f2a3da03568a7db3db4fe6c..205c09bc986342ff8d98866310a4056dd0366602 100644 (file)
@@ -1091,7 +1091,7 @@ static const struct dmi_system_id dmi_tas_approved_list[] = {
        },
                { .ident = "LENOVO",
          .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Lenovo"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
                },
        },
        { .ident = "DELL",
@@ -1727,8 +1727,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
        iwl_mvm_tas_init(mvm);
        iwl_mvm_leds_sync(mvm);
 
-       if (fw_has_capa(&mvm->fw->ucode_capa,
-                       IWL_UCODE_TLV_CAPA_RFIM_SUPPORT)) {
+       if (iwl_rfi_supported(mvm)) {
                if (iwl_mvm_eval_dsm_rfi(mvm) == DSM_VALUE_RFI_ENABLE)
                        iwl_rfi_send_config_cmd(mvm, NULL);
        }
index eb828de40a3c6d9491dca4839fea28ce66911b4e..3814915cb1a67df435b3b84a973af9fa9e29505f 100644 (file)
@@ -123,11 +123,13 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                                if (mvmvif->link[i]->phy_ctxt)
                                        count++;
 
-                       /* FIXME: IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM should be
-                        * defined per HW
-                        */
-                       if (count >= IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM)
-                               return -EINVAL;
+                       if (vif->type == NL80211_IFTYPE_AP) {
+                               if (count > mvm->fw->ucode_capa.num_beacons)
+                                       return -EOPNOTSUPP;
+                       /* this should be per HW or such */
+                       } else if (count >= IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM) {
+                               return -EOPNOTSUPP;
+                       }
                }
 
                /* Catch early if driver tries to activate or deactivate a link
index 0f01b62357c6fded37ad07cfcacbd7eec8cf8118..17f788a5ff6ba686e0d9743c3e8677dfecf9dc6d 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
  */
@@ -3607,7 +3607,8 @@ static bool iwl_mvm_vif_conf_from_sta(struct iwl_mvm *mvm,
                                      struct ieee80211_vif *vif,
                                      struct ieee80211_sta *sta)
 {
-       unsigned int i;
+       struct ieee80211_link_sta *link_sta;
+       unsigned int link_id;
 
        /* Beacon interval check - firmware will crash if the beacon
         * interval is less than 16. We can't avoid connecting at all,
@@ -3616,14 +3617,11 @@ static bool iwl_mvm_vif_conf_from_sta(struct iwl_mvm *mvm,
         * wpa_s will blocklist the AP...
         */
 
-       for_each_set_bit(i, (unsigned long *)&sta->valid_links,
-                        IEEE80211_MLD_MAX_NUM_LINKS) {
-               struct ieee80211_link_sta *link_sta =
-                       link_sta_dereference_protected(sta, i);
+       for_each_sta_active_link(vif, sta, link_sta, link_id) {
                struct ieee80211_bss_conf *link_conf =
-                       link_conf_dereference_protected(vif, i);
+                       link_conf_dereference_protected(vif, link_id);
 
-               if (!link_conf || !link_sta)
+               if (!link_conf)
                        continue;
 
                if (link_conf->beacon_int < IWL_MVM_MIN_BEACON_INTERVAL_TU) {
@@ -3645,24 +3643,23 @@ static void iwl_mvm_vif_set_he_support(struct ieee80211_hw *hw,
                                       bool is_sta)
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       unsigned int i;
+       struct ieee80211_link_sta *link_sta;
+       unsigned int link_id;
 
-       for_each_set_bit(i, (unsigned long *)&sta->valid_links,
-                        IEEE80211_MLD_MAX_NUM_LINKS) {
-               struct ieee80211_link_sta *link_sta =
-                       link_sta_dereference_protected(sta, i);
+       for_each_sta_active_link(vif, sta, link_sta, link_id) {
                struct ieee80211_bss_conf *link_conf =
-                       link_conf_dereference_protected(vif, i);
+                       link_conf_dereference_protected(vif, link_id);
 
-               if (!link_conf || !link_sta || !mvmvif->link[i])
+               if (!link_conf || !mvmvif->link[link_id])
                        continue;
 
                link_conf->he_support = link_sta->he_cap.has_he;
 
                if (is_sta) {
-                       mvmvif->link[i]->he_ru_2mhz_block = false;
+                       mvmvif->link[link_id]->he_ru_2mhz_block = false;
                        if (link_sta->he_cap.has_he)
-                               iwl_mvm_check_he_obss_narrow_bw_ru(hw, vif, i,
+                               iwl_mvm_check_he_obss_narrow_bw_ru(hw, vif,
+                                                                  link_id,
                                                                   link_conf);
                }
        }
@@ -3675,6 +3672,7 @@ iwl_mvm_sta_state_notexist_to_none(struct iwl_mvm *mvm,
                                   struct iwl_mvm_sta_state_ops *callbacks)
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       struct ieee80211_link_sta *link_sta;
        unsigned int i;
        int ret;
 
@@ -3699,15 +3697,9 @@ iwl_mvm_sta_state_notexist_to_none(struct iwl_mvm *mvm,
                                           NL80211_TDLS_SETUP);
        }
 
-       for (i = 0; i < ARRAY_SIZE(sta->link); i++) {
-               struct ieee80211_link_sta *link_sta;
-
-               link_sta = link_sta_dereference_protected(sta, i);
-               if (!link_sta)
-                       continue;
-
+       for_each_sta_active_link(vif, sta, link_sta, i)
                link_sta->agg.max_rc_amsdu_len = 1;
-       }
+
        ieee80211_sta_recalc_aggregates(sta);
 
        if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
@@ -3725,7 +3717,8 @@ iwl_mvm_sta_state_auth_to_assoc(struct ieee80211_hw *hw,
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
-       unsigned int i;
+       struct ieee80211_link_sta *link_sta;
+       unsigned int link_id;
 
        lockdep_assert_held(&mvm->mutex);
 
@@ -3751,14 +3744,13 @@ iwl_mvm_sta_state_auth_to_assoc(struct ieee80211_hw *hw,
                if (!mvm->mld_api_is_used)
                        goto out;
 
-               for_each_set_bit(i, (unsigned long *)&sta->valid_links,
-                                IEEE80211_MLD_MAX_NUM_LINKS) {
+               for_each_sta_active_link(vif, sta, link_sta, link_id) {
                        struct ieee80211_bss_conf *link_conf =
-                               link_conf_dereference_protected(vif, i);
+                               link_conf_dereference_protected(vif, link_id);
 
                        if (WARN_ON(!link_conf))
                                return -EINVAL;
-                       if (!mvmvif->link[i])
+                       if (!mvmvif->link[link_id])
                                continue;
 
                        iwl_mvm_link_changed(mvm, vif, link_conf,
@@ -3889,6 +3881,9 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
                 * from the AP now.
                 */
                iwl_mvm_reset_cca_40mhz_workaround(mvm, vif);
+
+               /* Also free dup data just in case any assertions below fail */
+               kfree(mvm_sta->dup_data);
        }
 
        mutex_lock(&mvm->mutex);
index fbc2d5ed100690a583f750e0db0a91603aa7881c..7fb66c5709596af2ffa7c1168e1bcf96879643a4 100644 (file)
@@ -906,11 +906,12 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
                                n_active++;
                }
 
-               if (vif->type == NL80211_IFTYPE_AP &&
-                   n_active > mvm->fw->ucode_capa.num_beacons)
-                       return -EOPNOTSUPP;
-               else if (n_active > 1)
+               if (vif->type == NL80211_IFTYPE_AP) {
+                       if (n_active > mvm->fw->ucode_capa.num_beacons)
+                               return -EOPNOTSUPP;
+               } else if (n_active > 1) {
                        return -EOPNOTSUPP;
+               }
        }
 
        for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
index 0bfdf446275508a1c82b8a3335048af2a1591c3a..85a4ce8449ade824dc067961ac2938b4e4cfc661 100644 (file)
@@ -667,15 +667,15 @@ int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                ret = iwl_mvm_mld_alloc_sta_links(mvm, vif, sta);
                if (ret)
                        return ret;
-       }
 
-       spin_lock_init(&mvm_sta->lock);
+               spin_lock_init(&mvm_sta->lock);
 
-       if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
-               ret = iwl_mvm_alloc_sta_after_restart(mvm, vif, sta);
-       else
                ret = iwl_mvm_sta_init(mvm, vif, sta, IWL_MVM_INVALID_STA,
                                       STATION_TYPE_PEER);
+       } else {
+               ret = iwl_mvm_alloc_sta_after_restart(mvm, vif, sta);
+       }
+
        if (ret)
                goto err;
 
@@ -728,7 +728,7 @@ int iwl_mvm_mld_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
        struct ieee80211_link_sta *link_sta;
        unsigned int link_id;
-       int ret = 0;
+       int ret = -EINVAL;
 
        lockdep_assert_held(&mvm->mutex);
 
@@ -791,8 +791,6 @@ int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
        lockdep_assert_held(&mvm->mutex);
 
-       kfree(mvm_sta->dup_data);
-
        /* flush its queues here since we are freeing mvm_sta */
        for_each_sta_active_link(vif, sta, link_sta, link_id) {
                struct iwl_mvm_link_sta *mvm_link_sta =
index 6e7470d3a826d35ded09d840985893907205d671..9e5008e0e47f5c1824854c654a101cda4600caa3 100644 (file)
@@ -2347,6 +2347,7 @@ int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm,
                                u32 old_sta_mask,
                                u32 new_sta_mask);
 
+bool iwl_rfi_supported(struct iwl_mvm *mvm);
 int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm,
                            struct iwl_rfi_lut_entry *rfi_table);
 struct iwl_rfi_freq_table_resp_cmd *iwl_rfi_get_freq_table(struct iwl_mvm *mvm);
index 6d18a1fd649b90e52006f7869663541e7320360a..fdf60afb0f3f26ec9e96f9132aacf45d61564ae4 100644 (file)
@@ -445,6 +445,11 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
                struct iwl_mcc_update_resp *mcc_resp = (void *)pkt->data;
 
                n_channels =  __le32_to_cpu(mcc_resp->n_channels);
+               if (iwl_rx_packet_payload_len(pkt) !=
+                   struct_size(mcc_resp, channels, n_channels)) {
+                       resp_cp = ERR_PTR(-EINVAL);
+                       goto exit;
+               }
                resp_len = sizeof(struct iwl_mcc_update_resp) +
                           n_channels * sizeof(__le32);
                resp_cp = kmemdup(mcc_resp, resp_len, GFP_KERNEL);
@@ -456,6 +461,11 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
                struct iwl_mcc_update_resp_v3 *mcc_resp_v3 = (void *)pkt->data;
 
                n_channels =  __le32_to_cpu(mcc_resp_v3->n_channels);
+               if (iwl_rx_packet_payload_len(pkt) !=
+                   struct_size(mcc_resp_v3, channels, n_channels)) {
+                       resp_cp = ERR_PTR(-EINVAL);
+                       goto exit;
+               }
                resp_len = sizeof(struct iwl_mcc_update_resp) +
                           n_channels * sizeof(__le32);
                resp_cp = kzalloc(resp_len, GFP_KERNEL);
index bb77bc9aa8218af83b21fa8b353d118b12c3685b..2ecd32bed752ff55734d5e9f78f36efc213cb107 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2020 - 2021 Intel Corporation
+ * Copyright (C) 2020 - 2022 Intel Corporation
  */
 
 #include "mvm.h"
@@ -70,6 +70,16 @@ static const struct iwl_rfi_lut_entry iwl_rfi_table[IWL_RFI_LUT_SIZE] = {
                PHY_BAND_6, PHY_BAND_6,}},
 };
 
+bool iwl_rfi_supported(struct iwl_mvm *mvm)
+{
+       /* The feature depends on a platform bugfix, so for now
+        * it's always disabled.
+        * When the platform support detection is implemented we should
+        * check FW TLV and platform support instead.
+        */
+       return false;
+}
+
 int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm, struct iwl_rfi_lut_entry *rfi_table)
 {
        int ret;
@@ -81,7 +91,7 @@ int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm, struct iwl_rfi_lut_entry *rfi_t
                .len[0] = sizeof(cmd),
        };
 
-       if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_RFIM_SUPPORT))
+       if (!iwl_rfi_supported(mvm))
                return -EOPNOTSUPP;
 
        lockdep_assert_held(&mvm->mutex);
@@ -113,7 +123,7 @@ struct iwl_rfi_freq_table_resp_cmd *iwl_rfi_get_freq_table(struct iwl_mvm *mvm)
                .flags = CMD_WANT_SKB,
        };
 
-       if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_RFIM_SUPPORT))
+       if (!iwl_rfi_supported(mvm))
                return ERR_PTR(-EOPNOTSUPP);
 
        mutex_lock(&mvm->mutex);
index a4c1e3bf4ff1de8db144095f157984ea11943999..23266d0c9ce4812d10a3c221040e2b29e1e6c29e 100644 (file)
@@ -2691,6 +2691,8 @@ static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,
                return;
 
        lq_sta = mvm_sta;
+
+       spin_lock(&lq_sta->pers.lock);
        iwl_mvm_hwrate_to_tx_rate_v1(lq_sta->last_rate_n_flags,
                                     info->band, &info->control.rates[0]);
        info->control.rates[0].count = 1;
@@ -2705,6 +2707,7 @@ static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,
                iwl_mvm_hwrate_to_tx_rate_v1(last_ucode_rate, info->band,
                                             &txrc->reported_rate);
        }
+       spin_unlock(&lq_sta->pers.lock);
 }
 
 static void *rs_drv_alloc_sta(void *mvm_rate, struct ieee80211_sta *sta,
index e1d02c260e69d504a35f6ddf3cf8d04b23751a9a..6226e4e54a51d2775a19174f7683d2c1db5ec729 100644 (file)
@@ -691,6 +691,11 @@ void iwl_mvm_reorder_timer_expired(struct timer_list *t)
 
                rcu_read_lock();
                sta = rcu_dereference(buf->mvm->fw_id_to_mac_id[sta_id]);
+               if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) {
+                       rcu_read_unlock();
+                       goto out;
+               }
+
                mvmsta = iwl_mvm_sta_from_mac80211(sta);
 
                /* SN is set to the last expired frame + 1 */
@@ -712,6 +717,8 @@ void iwl_mvm_reorder_timer_expired(struct timer_list *t)
                          entries[index].e.reorder_time +
                          1 + RX_REORDER_BUF_TIMEOUT_MQ);
        }
+
+out:
        spin_unlock(&buf->lock);
 }
 
@@ -2512,7 +2519,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
                                RCU_INIT_POINTER(mvm->csa_tx_blocked_vif, NULL);
                                /* Unblock BCAST / MCAST station */
                                iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, false);
-                               cancel_delayed_work_sync(&mvm->cs_tx_unblock_dwork);
+                               cancel_delayed_work(&mvm->cs_tx_unblock_dwork);
                        }
                }
 
index 5469d634e28998a12b2c9bd2fefde11dbddbdd0a..05a54a69c1357c59f121803204c8d7d448d4c0ef 100644 (file)
@@ -281,7 +281,7 @@ static void iwl_mvm_rx_agg_session_expired(struct timer_list *t)
         * A-MDPU and hence the timer continues to run. Then, the
         * timer expires and sta is NULL.
         */
-       if (!sta)
+       if (IS_ERR_OR_NULL(sta))
                goto unlock;
 
        mvm_sta = iwl_mvm_sta_from_mac80211(sta);
@@ -2089,9 +2089,6 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 
        lockdep_assert_held(&mvm->mutex);
 
-       if (iwl_mvm_has_new_rx_api(mvm))
-               kfree(mvm_sta->dup_data);
-
        ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
        if (ret)
                return ret;
@@ -3785,6 +3782,9 @@ static inline u8 *iwl_mvm_get_mac_addr(struct iwl_mvm *mvm,
                u8 sta_id = mvmvif->deflink.ap_sta_id;
                sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
                                                lockdep_is_held(&mvm->mutex));
+               if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
+                       return NULL;
+
                return sta->addr;
        }
 
@@ -3822,6 +3822,11 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
 
        if (keyconf->cipher == WLAN_CIPHER_SUITE_TKIP) {
                addr = iwl_mvm_get_mac_addr(mvm, vif, sta);
+               if (!addr) {
+                       IWL_ERR(mvm, "Failed to find mac address\n");
+                       return -EINVAL;
+               }
+
                /* get phase 1 key from mac80211 */
                ieee80211_get_key_rx_seq(keyconf, 0, &seq);
                ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
index 10d7178f10718ebe350494c40235368eacfeeb6c..00719e1304386454f350677322764e46483fab57 100644 (file)
@@ -1875,7 +1875,7 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm,
        mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, sta_id);
 
        sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
-       if (WARN_ON_ONCE(!sta || !sta->wme)) {
+       if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta) || !sta->wme)) {
                rcu_read_unlock();
                return;
        }
index a5ec0f6313850a54c7cb5170b7d9c051b8d554ca..fabf637bdf7f99f5d6b6d59d1c1dd6d7b7a1ec90 100644 (file)
@@ -173,7 +173,7 @@ enum {
 #define MT_TXS5_MPDU_TX_CNT            GENMASK(31, 23)
 
 #define MT_TXS6_MPDU_FAIL_CNT          GENMASK(31, 23)
-
+#define MT_TXS7_MPDU_RETRY_BYTE                GENMASK(22, 0)
 #define MT_TXS7_MPDU_RETRY_CNT         GENMASK(31, 23)
 
 /* RXD DW0 */
index ee0fbfcd07d6469d94ce9a3f62c6868ef1fb753b..d39a3cc5e381f8b01e9ca2c8d0559215969ebeba 100644 (file)
@@ -608,7 +608,8 @@ bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid,
        /* PPDU based reporting */
        if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) {
                stats->tx_bytes +=
-                       le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_BYTE);
+                       le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_BYTE) -
+                       le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_BYTE);
                stats->tx_packets +=
                        le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_CNT);
                stats->tx_failed +=
index 130eb7b4fd914c02f9b938b49e945365c36a1122..39a4a73ef8e6a10bcdaafce6bbc96ba25705b7a9 100644 (file)
@@ -1088,7 +1088,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
                else if (beacon && mvif->beacon_rates_idx)
                        idx = mvif->beacon_rates_idx;
 
-               txwi[6] |= FIELD_PREP(MT_TXD6_TX_RATE, idx);
+               txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE, idx));
                txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
        }
 }
index 8eafbf1cee718dc31045bdfb71efe94dfb0a6a55..808c1c895113dacf4190674fa6aae9e7ffe121e9 100644 (file)
@@ -1803,6 +1803,7 @@ struct rtl8xxxu_priv {
        u32 rege9c;
        u32 regeb4;
        u32 regebc;
+       u32 regrcr;
        int next_mbox;
        int nr_out_eps;
 
index fd8c8c6d53d60b771da8ff0332c669167b203be4..831639d73657be9c338ec21d6cf4108331c40ac3 100644 (file)
@@ -4171,6 +4171,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
                RCR_ACCEPT_MGMT_FRAME | RCR_HTC_LOC_CTRL |
                RCR_APPEND_PHYSTAT | RCR_APPEND_ICV | RCR_APPEND_MIC;
        rtl8xxxu_write32(priv, REG_RCR, val32);
+       priv->regrcr = val32;
 
        if (fops->init_reg_rxfltmap) {
                /* Accept all data frames */
@@ -6501,7 +6502,7 @@ static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw,
                                      unsigned int *total_flags, u64 multicast)
 {
        struct rtl8xxxu_priv *priv = hw->priv;
-       u32 rcr = rtl8xxxu_read32(priv, REG_RCR);
+       u32 rcr = priv->regrcr;
 
        dev_dbg(&priv->udev->dev, "%s: changed_flags %08x, total_flags %08x\n",
                __func__, changed_flags, *total_flags);
@@ -6547,6 +6548,7 @@ static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw,
         */
 
        rtl8xxxu_write32(priv, REG_RCR, rcr);
+       priv->regrcr = rcr;
 
        *total_flags &= (FIF_ALLMULTI | FIF_FCSFAIL | FIF_BCN_PRBRESP_PROMISC |
                         FIF_CONTROL | FIF_OTHER_BSS | FIF_PSPOLL |
index 7aa6edad0d012738887d45febf34a54c8065d6e5..a6c024cab7ee44bc089eb20a1eb514b51e98ffaa 100644 (file)
@@ -918,7 +918,7 @@ static void rtw_ops_sta_rc_update(struct ieee80211_hw *hw,
        struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
 
        if (changed & IEEE80211_RC_BW_CHANGED)
-               rtw_update_sta_info(rtwdev, si, true);
+               ieee80211_queue_work(rtwdev->hw, &si->rc_work);
 }
 
 const struct ieee80211_ops rtw_ops = {
index 5bf6b45815578feb766453db223e7a71c93119e7..d30a191c9291dc888c8a469361fd7f00c4ec158a 100644 (file)
@@ -319,6 +319,17 @@ static u8 rtw_acquire_macid(struct rtw_dev *rtwdev)
        return mac_id;
 }
 
+static void rtw_sta_rc_work(struct work_struct *work)
+{
+       struct rtw_sta_info *si = container_of(work, struct rtw_sta_info,
+                                              rc_work);
+       struct rtw_dev *rtwdev = si->rtwdev;
+
+       mutex_lock(&rtwdev->mutex);
+       rtw_update_sta_info(rtwdev, si, true);
+       mutex_unlock(&rtwdev->mutex);
+}
+
 int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta,
                struct ieee80211_vif *vif)
 {
@@ -329,12 +340,14 @@ int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta,
        if (si->mac_id >= RTW_MAX_MAC_ID_NUM)
                return -ENOSPC;
 
+       si->rtwdev = rtwdev;
        si->sta = sta;
        si->vif = vif;
        si->init_ra_lv = 1;
        ewma_rssi_init(&si->avg_rssi);
        for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
                rtw_txq_init(rtwdev, sta->txq[i]);
+       INIT_WORK(&si->rc_work, rtw_sta_rc_work);
 
        rtw_update_sta_info(rtwdev, si, true);
        rtw_fw_media_status_report(rtwdev, si->mac_id, true);
@@ -353,6 +366,8 @@ void rtw_sta_remove(struct rtw_dev *rtwdev, struct ieee80211_sta *sta,
        struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
        int i;
 
+       cancel_work_sync(&si->rc_work);
+
        rtw_release_macid(rtwdev, si->mac_id);
        if (fw_exist)
                rtw_fw_media_status_report(rtwdev, si->mac_id, false);
index a563285e90ede577f287d7329f1246cdb3569a14..9e841f6991a9a4d0d984fe5892282bd8d473ade4 100644 (file)
@@ -743,6 +743,7 @@ struct rtw_txq {
 DECLARE_EWMA(rssi, 10, 16);
 
 struct rtw_sta_info {
+       struct rtw_dev *rtwdev;
        struct ieee80211_sta *sta;
        struct ieee80211_vif *vif;
 
@@ -767,6 +768,8 @@ struct rtw_sta_info {
 
        bool use_cfg_mask;
        struct cfg80211_bitrate_mask *mask;
+
+       struct work_struct rc_work;
 };
 
 enum rtw_bfee_role {
index af0459a79899f65bd675d7078d00b44c8f617b4b..06fce7c3addaa395bc5c622621bf8bc7c0537dae 100644 (file)
@@ -87,11 +87,6 @@ static void rtw_sdio_writew(struct rtw_dev *rtwdev, u16 val, u32 addr,
        u8 buf[2];
        int i;
 
-       if (rtw_sdio_use_memcpy_io(rtwdev, addr, 2)) {
-               sdio_writew(rtwsdio->sdio_func, val, addr, err_ret);
-               return;
-       }
-
        *(__le16 *)buf = cpu_to_le16(val);
 
        for (i = 0; i < 2; i++) {
@@ -125,9 +120,6 @@ static u16 rtw_sdio_readw(struct rtw_dev *rtwdev, u32 addr, int *err_ret)
        u8 buf[2];
        int i;
 
-       if (rtw_sdio_use_memcpy_io(rtwdev, addr, 2))
-               return sdio_readw(rtwsdio->sdio_func, addr, err_ret);
-
        for (i = 0; i < 2; i++) {
                buf[i] = sdio_readb(rtwsdio->sdio_func, addr + i, err_ret);
                if (*err_ret)
index 30647f0dd61c66fb6433c7976752b916d8be3e53..ad1d7955c6a51e545b92c5e5bbd316f9120bf438 100644 (file)
@@ -78,7 +78,7 @@ struct rtw_usb {
        u8 pipe_interrupt;
        u8 pipe_in;
        u8 out_ep[RTW_USB_EP_MAX];
-       u8 qsel_to_ep[TX_DESC_QSEL_MAX];
+       int qsel_to_ep[TX_DESC_QSEL_MAX];
        u8 usb_txagg_num;
 
        struct workqueue_struct *txwq, *rxwq;
index b8019cfc11b20dd5889b6106ba905d5999f4aab3..512de491a064b1b741ad34802b423e7a2b59a968 100644 (file)
@@ -1425,6 +1425,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
        .wde_size4 = {RTW89_WDE_PG_64, 0, 4096,},
        /* PCIE 64 */
        .wde_size6 = {RTW89_WDE_PG_64, 512, 0,},
+       /* 8852B PCIE SCC */
+       .wde_size7 = {RTW89_WDE_PG_64, 510, 2,},
        /* DLFW */
        .wde_size9 = {RTW89_WDE_PG_64, 0, 1024,},
        /* 8852C DLFW */
@@ -1449,6 +1451,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
        .wde_qt4 = {0, 0, 0, 0,},
        /* PCIE 64 */
        .wde_qt6 = {448, 48, 0, 16,},
+       /* 8852B PCIE SCC */
+       .wde_qt7 = {446, 48, 0, 16,},
        /* 8852C DLFW */
        .wde_qt17 = {0, 0, 0,  0,},
        /* 8852C PCIE SCC */
index a8d9847ef0b49e1df2f7ffa19abc9729cf4db7b9..6ba633ccdd0377ff571a5c0bbf2017c8bb11807e 100644 (file)
@@ -792,6 +792,7 @@ struct rtw89_mac_size_set {
        const struct rtw89_dle_size wde_size0;
        const struct rtw89_dle_size wde_size4;
        const struct rtw89_dle_size wde_size6;
+       const struct rtw89_dle_size wde_size7;
        const struct rtw89_dle_size wde_size9;
        const struct rtw89_dle_size wde_size18;
        const struct rtw89_dle_size wde_size19;
@@ -804,6 +805,7 @@ struct rtw89_mac_size_set {
        const struct rtw89_wde_quota wde_qt0;
        const struct rtw89_wde_quota wde_qt4;
        const struct rtw89_wde_quota wde_qt6;
+       const struct rtw89_wde_quota wde_qt7;
        const struct rtw89_wde_quota wde_qt17;
        const struct rtw89_wde_quota wde_qt18;
        const struct rtw89_ple_quota ple_qt4;
index eaa2ea0586bc621852d2b318d107a4eb95099ee4..6da1b603a9a95c096fc531b727ea080c84ebeaa2 100644 (file)
        RTW8852B_FW_BASENAME "-" __stringify(RTW8852B_FW_FORMAT_MAX) ".bin"
 
 static const struct rtw89_hfc_ch_cfg rtw8852b_hfc_chcfg_pcie[] = {
-       {5, 343, grp_0}, /* ACH 0 */
-       {5, 343, grp_0}, /* ACH 1 */
-       {5, 343, grp_0}, /* ACH 2 */
-       {5, 343, grp_0}, /* ACH 3 */
+       {5, 341, grp_0}, /* ACH 0 */
+       {5, 341, grp_0}, /* ACH 1 */
+       {4, 342, grp_0}, /* ACH 2 */
+       {4, 342, grp_0}, /* ACH 3 */
        {0, 0, grp_0}, /* ACH 4 */
        {0, 0, grp_0}, /* ACH 5 */
        {0, 0, grp_0}, /* ACH 6 */
        {0, 0, grp_0}, /* ACH 7 */
-       {4, 344, grp_0}, /* B0MGQ */
-       {4, 344, grp_0}, /* B0HIQ */
+       {4, 342, grp_0}, /* B0MGQ */
+       {4, 342, grp_0}, /* B0HIQ */
        {0, 0, grp_0}, /* B1MGQ */
        {0, 0, grp_0}, /* B1HIQ */
        {40, 0, 0} /* FWCMDQ */
 };
 
 static const struct rtw89_hfc_pub_cfg rtw8852b_hfc_pubcfg_pcie = {
-       448, /* Group 0 */
+       446, /* Group 0 */
        0, /* Group 1 */
-       448, /* Public Max */
+       446, /* Public Max */
        0 /* WP threshold */
 };
 
@@ -49,13 +49,13 @@ static const struct rtw89_hfc_param_ini rtw8852b_hfc_param_ini_pcie[] = {
 };
 
 static const struct rtw89_dle_mem rtw8852b_dle_mem_pcie[] = {
-       [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size6,
-                          &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6,
-                          &rtw89_mac_size.wde_qt6, &rtw89_mac_size.ple_qt18,
+       [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size7,
+                          &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt7,
+                          &rtw89_mac_size.wde_qt7, &rtw89_mac_size.ple_qt18,
                           &rtw89_mac_size.ple_qt58},
-       [RTW89_QTA_WOW] = {RTW89_QTA_WOW, &rtw89_mac_size.wde_size6,
-                          &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6,
-                          &rtw89_mac_size.wde_qt6, &rtw89_mac_size.ple_qt18,
+       [RTW89_QTA_WOW] = {RTW89_QTA_WOW, &rtw89_mac_size.wde_size7,
+                          &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt7,
+                          &rtw89_mac_size.wde_qt7, &rtw89_mac_size.ple_qt18,
                           &rtw89_mac_size.ple_qt_52b_wow},
        [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size9,
                            &rtw89_mac_size.ple_size8, &rtw89_mac_size.wde_qt4,
index 9a8faaf4c6b642e9960ea593072f476f12ec3985..89c7a1420381d369930cf7e6907d08740638290f 100644 (file)
@@ -5964,10 +5964,11 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
                        ret = -ENOMEM;
                        goto out_free;
                }
+               param.pmsr_capa = pmsr_capa;
+
                ret = parse_pmsr_capa(info->attrs[HWSIM_ATTR_PMSR_SUPPORT], pmsr_capa, info);
                if (ret)
                        goto out_free;
-               param.pmsr_capa = pmsr_capa;
        }
 
        ret = mac80211_hwsim_new_radio(info, &param);
index c066b0040a3fe5fb6668bd35d45694495dc1647a..829515a601b379d3acb57927b67076a35ebf16c9 100644 (file)
@@ -565,24 +565,32 @@ static void ipc_imem_run_state_worker(struct work_struct *instance)
        struct ipc_mux_config mux_cfg;
        struct iosm_imem *ipc_imem;
        u8 ctrl_chl_idx = 0;
+       int ret;
 
        ipc_imem = container_of(instance, struct iosm_imem, run_state_worker);
 
        if (ipc_imem->phase != IPC_P_RUN) {
                dev_err(ipc_imem->dev,
                        "Modem link down. Exit run state worker.");
-               return;
+               goto err_out;
        }
 
        if (test_and_clear_bit(IOSM_DEVLINK_INIT, &ipc_imem->flag))
                ipc_devlink_deinit(ipc_imem->ipc_devlink);
 
-       if (!ipc_imem_setup_cp_mux_cap_init(ipc_imem, &mux_cfg))
-               ipc_imem->mux = ipc_mux_init(&mux_cfg, ipc_imem);
+       ret = ipc_imem_setup_cp_mux_cap_init(ipc_imem, &mux_cfg);
+       if (ret < 0)
+               goto err_out;
+
+       ipc_imem->mux = ipc_mux_init(&mux_cfg, ipc_imem);
+       if (!ipc_imem->mux)
+               goto err_out;
+
+       ret = ipc_imem_wwan_channel_init(ipc_imem, mux_cfg.protocol);
+       if (ret < 0)
+               goto err_ipc_mux_deinit;
 
-       ipc_imem_wwan_channel_init(ipc_imem, mux_cfg.protocol);
-       if (ipc_imem->mux)
-               ipc_imem->mux->wwan = ipc_imem->wwan;
+       ipc_imem->mux->wwan = ipc_imem->wwan;
 
        while (ctrl_chl_idx < IPC_MEM_MAX_CHANNELS) {
                if (!ipc_chnl_cfg_get(&chnl_cfg_port, ctrl_chl_idx)) {
@@ -622,6 +630,13 @@ static void ipc_imem_run_state_worker(struct work_struct *instance)
 
        /* Complete all memory stores after setting bit */
        smp_mb__after_atomic();
+
+       return;
+
+err_ipc_mux_deinit:
+       ipc_mux_deinit(ipc_imem->mux);
+err_out:
+       ipc_uevent_send(ipc_imem->dev, UEVENT_CD_READY_LINK_DOWN);
 }
 
 static void ipc_imem_handle_irq(struct iosm_imem *ipc_imem, int irq)
index 66b90cc4c3460f4d046037c6e51181322720f56e..109cf89304888bc15e045536daca29979bc8a8f2 100644 (file)
@@ -77,8 +77,8 @@ out:
 }
 
 /* Initialize wwan channel */
-void ipc_imem_wwan_channel_init(struct iosm_imem *ipc_imem,
-                               enum ipc_mux_protocol mux_type)
+int ipc_imem_wwan_channel_init(struct iosm_imem *ipc_imem,
+                              enum ipc_mux_protocol mux_type)
 {
        struct ipc_chnl_cfg chnl_cfg = { 0 };
 
@@ -87,7 +87,7 @@ void ipc_imem_wwan_channel_init(struct iosm_imem *ipc_imem,
        /* If modem version is invalid (0xffffffff), do not initialize WWAN. */
        if (ipc_imem->cp_version == -1) {
                dev_err(ipc_imem->dev, "invalid CP version");
-               return;
+               return -EIO;
        }
 
        ipc_chnl_cfg_get(&chnl_cfg, ipc_imem->nr_of_channels);
@@ -104,9 +104,13 @@ void ipc_imem_wwan_channel_init(struct iosm_imem *ipc_imem,
 
        /* WWAN registration. */
        ipc_imem->wwan = ipc_wwan_init(ipc_imem, ipc_imem->dev);
-       if (!ipc_imem->wwan)
+       if (!ipc_imem->wwan) {
                dev_err(ipc_imem->dev,
                        "failed to register the ipc_wwan interfaces");
+               return -ENOMEM;
+       }
+
+       return 0;
 }
 
 /* Map SKB to DMA for transfer */
index f8afb217d9e2fb8acad63e6b6de8b4f726542db9..026c5bd0f9992f7afeb03667149e4fbbd8dc83cc 100644 (file)
@@ -91,9 +91,11 @@ int ipc_imem_sys_wwan_transmit(struct iosm_imem *ipc_imem, int if_id,
  *                             MUX.
  * @ipc_imem:          Pointer to iosm_imem struct.
  * @mux_type:          Type of mux protocol.
+ *
+ * Return: 0 on success and failure value on error
  */
-void ipc_imem_wwan_channel_init(struct iosm_imem *ipc_imem,
-                               enum ipc_mux_protocol mux_type);
+int ipc_imem_wwan_channel_init(struct iosm_imem *ipc_imem,
+                              enum ipc_mux_protocol mux_type);
 
 /**
  * ipc_imem_sys_devlink_open - Open a Flash/CD Channel link to CP
index 226fc1703e90f2d56728cfbf73b64c9f5bf49849..91256e005b846f17f869d62ceb6ac645d698c5fc 100644 (file)
@@ -45,6 +45,7 @@
 #define T7XX_PCI_IREG_BASE             0
 #define T7XX_PCI_EREG_BASE             2
 
+#define T7XX_INIT_TIMEOUT              20
 #define PM_SLEEP_DIS_TIMEOUT_MS                20
 #define PM_ACK_TIMEOUT_MS              1500
 #define PM_AUTOSUSPEND_MS              20000
@@ -96,6 +97,7 @@ static int t7xx_pci_pm_init(struct t7xx_pci_dev *t7xx_dev)
        spin_lock_init(&t7xx_dev->md_pm_lock);
        init_completion(&t7xx_dev->sleep_lock_acquire);
        init_completion(&t7xx_dev->pm_sr_ack);
+       init_completion(&t7xx_dev->init_done);
        atomic_set(&t7xx_dev->md_pm_state, MTK_PM_INIT);
 
        device_init_wakeup(&pdev->dev, true);
@@ -124,6 +126,7 @@ void t7xx_pci_pm_init_late(struct t7xx_pci_dev *t7xx_dev)
        pm_runtime_mark_last_busy(&t7xx_dev->pdev->dev);
        pm_runtime_allow(&t7xx_dev->pdev->dev);
        pm_runtime_put_noidle(&t7xx_dev->pdev->dev);
+       complete_all(&t7xx_dev->init_done);
 }
 
 static int t7xx_pci_pm_reinit(struct t7xx_pci_dev *t7xx_dev)
@@ -529,6 +532,20 @@ static void t7xx_pci_shutdown(struct pci_dev *pdev)
        __t7xx_pci_pm_suspend(pdev);
 }
 
+static int t7xx_pci_pm_prepare(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct t7xx_pci_dev *t7xx_dev;
+
+       t7xx_dev = pci_get_drvdata(pdev);
+       if (!wait_for_completion_timeout(&t7xx_dev->init_done, T7XX_INIT_TIMEOUT * HZ)) {
+               dev_warn(dev, "Not ready for system sleep.\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
 static int t7xx_pci_pm_suspend(struct device *dev)
 {
        return __t7xx_pci_pm_suspend(to_pci_dev(dev));
@@ -555,6 +572,7 @@ static int t7xx_pci_pm_runtime_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops t7xx_pci_pm_ops = {
+       .prepare = t7xx_pci_pm_prepare,
        .suspend = t7xx_pci_pm_suspend,
        .resume = t7xx_pci_pm_resume,
        .resume_noirq = t7xx_pci_pm_resume_noirq,
index 112efa534eaceffb47a8b049d5126eae79c971e3..f08f1ab7446917b0b84f053fe31a0f9902d76f90 100644 (file)
@@ -69,6 +69,7 @@ struct t7xx_pci_dev {
        struct t7xx_modem       *md;
        struct t7xx_ccmni_ctrl  *ccmni_ctlb;
        bool                    rgu_pci_irq_en;
+       struct completion       init_done;
 
        /* Low Power Items */
        struct list_head        md_pm_entities;
index 44eeb17ae48d911fbb75b92d0d5d8987d5e5bea6..a55381f80cd6e4d98eaece05340269ab6a7f45ed 100644 (file)
@@ -336,10 +336,6 @@ static struct dentry *nfcsim_debugfs_root;
 static void nfcsim_debugfs_init(void)
 {
        nfcsim_debugfs_root = debugfs_create_dir("nfcsim", NULL);
-
-       if (!nfcsim_debugfs_root)
-               pr_err("Could not create debugfs entry\n");
-
 }
 
 static void nfcsim_debugfs_remove(void)
index bc523ca0225486776eba989fab6ed758b4c569d0..5e4f8848dce08e912d5c4d85b84ae70cf55c14e5 100644 (file)
@@ -21,7 +21,7 @@ static const char * const nvme_ops[] = {
        [nvme_cmd_resv_release] = "Reservation Release",
        [nvme_cmd_zone_mgmt_send] = "Zone Management Send",
        [nvme_cmd_zone_mgmt_recv] = "Zone Management Receive",
-       [nvme_cmd_zone_append] = "Zone Management Append",
+       [nvme_cmd_zone_append] = "Zone Append",
 };
 
 static const char * const nvme_admin_ops[] = {
index ccb6eb1282f82d8b801b38172261be1052119a6a..3ec38e2b91732691ae53ac50eb7fc8a45add5465 100644 (file)
@@ -397,7 +397,16 @@ void nvme_complete_rq(struct request *req)
        trace_nvme_complete_rq(req);
        nvme_cleanup_cmd(req);
 
-       if (ctrl->kas)
+       /*
+        * Completions of long-running commands should not be able to
+        * defer sending of periodic keep alives, since the controller
+        * may have completed processing such commands a long time ago
+        * (arbitrarily close to command submission time).
+        * req->deadline - req->timeout is the command submission time
+        * in jiffies.
+        */
+       if (ctrl->kas &&
+           req->deadline - req->timeout >= ctrl->ka_last_check_time)
                ctrl->comp_seen = true;
 
        switch (nvme_decide_disposition(req)) {
@@ -1115,7 +1124,7 @@ u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode)
 }
 EXPORT_SYMBOL_NS_GPL(nvme_passthru_start, NVME_TARGET_PASSTHRU);
 
-void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects,
+void nvme_passthru_end(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u32 effects,
                       struct nvme_command *cmd, int status)
 {
        if (effects & NVME_CMD_EFFECTS_CSE_MASK) {
@@ -1132,6 +1141,8 @@ void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects,
                nvme_queue_scan(ctrl);
                flush_work(&ctrl->scan_work);
        }
+       if (ns)
+               return;
 
        switch (cmd->common.opcode) {
        case nvme_admin_set_features:
@@ -1161,9 +1172,25 @@ EXPORT_SYMBOL_NS_GPL(nvme_passthru_end, NVME_TARGET_PASSTHRU);
  *   The host should send Keep Alive commands at half of the Keep Alive Timeout
  *   accounting for transport roundtrip times [..].
  */
+static unsigned long nvme_keep_alive_work_period(struct nvme_ctrl *ctrl)
+{
+       unsigned long delay = ctrl->kato * HZ / 2;
+
+       /*
+        * When using Traffic Based Keep Alive, we need to run
+        * nvme_keep_alive_work at twice the normal frequency, as one
+        * command completion can postpone sending a keep alive command
+        * by up to twice the delay between runs.
+        */
+       if (ctrl->ctratt & NVME_CTRL_ATTR_TBKAS)
+               delay /= 2;
+       return delay;
+}
+
 static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
 {
-       queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ / 2);
+       queue_delayed_work(nvme_wq, &ctrl->ka_work,
+                          nvme_keep_alive_work_period(ctrl));
 }
 
 static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
@@ -1172,6 +1199,20 @@ static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
        struct nvme_ctrl *ctrl = rq->end_io_data;
        unsigned long flags;
        bool startka = false;
+       unsigned long rtt = jiffies - (rq->deadline - rq->timeout);
+       unsigned long delay = nvme_keep_alive_work_period(ctrl);
+
+       /*
+        * Subtract off the keepalive RTT so nvme_keep_alive_work runs
+        * at the desired frequency.
+        */
+       if (rtt <= delay) {
+               delay -= rtt;
+       } else {
+               dev_warn(ctrl->device, "long keepalive RTT (%u ms)\n",
+                        jiffies_to_msecs(rtt));
+               delay = 0;
+       }
 
        blk_mq_free_request(rq);
 
@@ -1182,6 +1223,7 @@ static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
                return RQ_END_IO_NONE;
        }
 
+       ctrl->ka_last_check_time = jiffies;
        ctrl->comp_seen = false;
        spin_lock_irqsave(&ctrl->lock, flags);
        if (ctrl->state == NVME_CTRL_LIVE ||
@@ -1189,7 +1231,7 @@ static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
                startka = true;
        spin_unlock_irqrestore(&ctrl->lock, flags);
        if (startka)
-               nvme_queue_keep_alive_work(ctrl);
+               queue_delayed_work(nvme_wq, &ctrl->ka_work, delay);
        return RQ_END_IO_NONE;
 }
 
@@ -1200,6 +1242,8 @@ static void nvme_keep_alive_work(struct work_struct *work)
        bool comp_seen = ctrl->comp_seen;
        struct request *rq;
 
+       ctrl->ka_last_check_time = jiffies;
+
        if ((ctrl->ctratt & NVME_CTRL_ATTR_TBKAS) && comp_seen) {
                dev_dbg(ctrl->device,
                        "reschedule traffic based keep-alive timer\n");
@@ -3585,6 +3629,9 @@ static ssize_t nvme_sysfs_delete(struct device *dev,
 {
        struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
 
+       if (!test_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags))
+               return -EBUSY;
+
        if (device_remove_file_self(dev, attr))
                nvme_delete_ctrl_sync(ctrl);
        return count;
@@ -5045,7 +5092,7 @@ void nvme_start_ctrl(struct nvme_ctrl *ctrl)
         * that were missed. We identify persistent discovery controllers by
         * checking that they started once before, hence are reconnecting back.
         */
-       if (test_and_set_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags) &&
+       if (test_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags) &&
            nvme_discovery_ctrl(ctrl))
                nvme_change_uevent(ctrl, "NVME_EVENT=rediscover");
 
@@ -5056,6 +5103,7 @@ void nvme_start_ctrl(struct nvme_ctrl *ctrl)
        }
 
        nvme_change_uevent(ctrl, "NVME_EVENT=connected");
+       set_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags);
 }
 EXPORT_SYMBOL_GPL(nvme_start_ctrl);
 
index 9e6e56c20ec993bfca3ee2eb18d2e371d7225230..316f3e4ca7cc60da613e5f246f9e5a861d60e14f 100644 (file)
@@ -163,7 +163,9 @@ static umode_t nvme_hwmon_is_visible(const void *_data,
        case hwmon_temp_max:
        case hwmon_temp_min:
                if ((!channel && data->ctrl->wctemp) ||
-                   (channel && data->log->temp_sensor[channel - 1])) {
+                   (channel && data->log->temp_sensor[channel - 1] &&
+                    !(data->ctrl->quirks &
+                      NVME_QUIRK_NO_SECONDARY_TEMP_THRESH))) {
                        if (data->ctrl->quirks &
                            NVME_QUIRK_NO_TEMP_THRESH_CHANGE)
                                return 0444;
index 81c5c9e38477470c1134506b78bdd09ceaa36be5..f15e7330b75ac5c310bf05f88cd1275469461097 100644 (file)
@@ -254,7 +254,7 @@ static int nvme_submit_user_cmd(struct request_queue *q,
        blk_mq_free_request(req);
 
        if (effects)
-               nvme_passthru_end(ctrl, effects, cmd, ret);
+               nvme_passthru_end(ctrl, ns, effects, cmd, ret);
 
        return ret;
 }
index 9171452e2f6d4e2eed95d0c6ef9ec0cbf05bc7ef..2bc159a318ff0af19a06aa668aeb94bf8167ff1d 100644 (file)
@@ -884,7 +884,6 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head)
 {
        if (!head->disk)
                return;
-       blk_mark_disk_dead(head->disk);
        /* make sure all pending bios are cleaned up */
        kblockd_schedule_work(&head->requeue_work);
        flush_work(&head->requeue_work);
index bf46f122e9e1e476c7127186c356c3857c37c30a..8657811f8b8875e21a53732252d7f0738c85d678 100644 (file)
@@ -149,6 +149,11 @@ enum nvme_quirks {
         * Reports garbage in the namespace identifiers (eui64, nguid, uuid).
         */
        NVME_QUIRK_BOGUS_NID                    = (1 << 18),
+
+       /*
+        * No temperature thresholds for channels other than 0 (Composite).
+        */
+       NVME_QUIRK_NO_SECONDARY_TEMP_THRESH     = (1 << 19),
 };
 
 /*
@@ -323,6 +328,7 @@ struct nvme_ctrl {
        struct delayed_work ka_work;
        struct delayed_work failfast_work;
        struct nvme_command ka_cmd;
+       unsigned long ka_last_check_time;
        struct work_struct fw_act_work;
        unsigned long events;
 
@@ -1072,7 +1078,7 @@ u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
                         u8 opcode);
 u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode);
 int nvme_execute_rq(struct request *rq, bool at_head);
-void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects,
+void nvme_passthru_end(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u32 effects,
                       struct nvme_command *cmd, int status);
 struct nvme_ctrl *nvme_ctrl_from_file(struct file *file);
 struct nvme_ns *nvme_find_get_ns(struct nvme_ctrl *ctrl, unsigned nsid);
index 7f25c0fe3a0bf5baf92dcd5f81613ecac75bb593..492f319ebdf37ad838dacbb5237f1a804b243840 100644 (file)
@@ -2956,7 +2956,7 @@ static struct nvme_dev *nvme_pci_alloc_dev(struct pci_dev *pdev,
         * over a single page.
         */
        dev->ctrl.max_hw_sectors = min_t(u32,
-               NVME_MAX_KB_SZ << 1, dma_max_mapping_size(&pdev->dev) >> 9);
+               NVME_MAX_KB_SZ << 1, dma_opt_mapping_size(&pdev->dev) >> 9);
        dev->ctrl.max_segments = NVME_MAX_SEGS;
 
        /*
@@ -3402,6 +3402,8 @@ static const struct pci_device_id nvme_id_table[] = {
                .driver_data = NVME_QUIRK_NO_DEEPEST_PS, },
        { PCI_DEVICE(0x2646, 0x2263),   /* KINGSTON A2000 NVMe SSD  */
                .driver_data = NVME_QUIRK_NO_DEEPEST_PS, },
+       { PCI_DEVICE(0x2646, 0x5013),   /* Kingston KC3000, Kingston FURY Renegade */
+               .driver_data = NVME_QUIRK_NO_SECONDARY_TEMP_THRESH, },
        { PCI_DEVICE(0x2646, 0x5018),   /* KINGSTON OM8SFP4xxxxP OS21012 NVMe SSD */
                .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
        { PCI_DEVICE(0x2646, 0x5016),   /* KINGSTON OM3PGP4xxxxP OS21011 NVMe SSD */
@@ -3422,6 +3424,8 @@ static const struct pci_device_id nvme_id_table[] = {
                .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1e4B, 0x1202),   /* MAXIO MAP1202 */
                .driver_data = NVME_QUIRK_BOGUS_NID, },
+       { PCI_DEVICE(0x1e4B, 0x1602),   /* MAXIO MAP1602 */
+               .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1cc1, 0x5350),   /* ADATA XPG GAMMIX S50 */
                .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1dbe, 0x5236),   /* ADATA XPG GAMMIX S70 */
@@ -3441,6 +3445,10 @@ static const struct pci_device_id nvme_id_table[] = {
                                NVME_QUIRK_IGNORE_DEV_SUBNQN, },
        { PCI_DEVICE(0x10ec, 0x5763), /* TEAMGROUP T-FORCE CARDEA ZERO Z330 SSD */
                .driver_data = NVME_QUIRK_BOGUS_NID, },
+       { PCI_DEVICE(0x1e4b, 0x1602), /* HS-SSD-FUTURE 2048G  */
+               .driver_data = NVME_QUIRK_BOGUS_NID, },
+       { PCI_DEVICE(0x10ec, 0x5765), /* TEAMGROUP MP33 2TB SSD */
+               .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0061),
                .driver_data = NVME_QUIRK_DMA_ADDRESS_BITS_48, },
        { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0065),
index 511c980d538df3af57fa9f1d998607393c417008..71a9c1cc57f59c265478b8c816c8e4f5a9b65f61 100644 (file)
@@ -243,7 +243,7 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w)
        blk_mq_free_request(rq);
 
        if (effects)
-               nvme_passthru_end(ctrl, effects, req->cmd, status);
+               nvme_passthru_end(ctrl, ns, effects, req->cmd, status);
 }
 
 static enum rq_end_io_ret nvmet_passthru_req_done(struct request *rq,
index b291b27048c76f8d686c725665a545966d8deff3..da9befa3d6c43bfb2885459f1d2aef58904cfa11 100644 (file)
@@ -55,6 +55,7 @@ config NVMEM_BRCM_NVRAM
        tristate "Broadcom's NVRAM support"
        depends on ARCH_BCM_5301X || COMPILE_TEST
        depends on HAS_IOMEM
+       select GENERIC_NET_UTILS
        help
          This driver provides support for Broadcom's NVRAM that can be accessed
          using I/O mapping.
@@ -82,6 +83,15 @@ config NVMEM_IMX_OCOTP
          This driver can also be built as a module. If so, the module
          will be called nvmem-imx-ocotp.
 
+config NVMEM_IMX_OCOTP_ELE
+       tristate "i.MX On-Chip OTP Controller support"
+       depends on ARCH_MXC || COMPILE_TEST
+       depends on HAS_IOMEM
+       depends on OF
+       help
+         This is a driver for the On-Chip OTP Controller (OCOTP)
+         available on i.MX SoCs which has ELE.
+
 config NVMEM_IMX_OCOTP_SCU
        tristate "i.MX8 SCU On-Chip OTP Controller support"
        depends on IMX_SCU
index f82431ec8aef0c2ebdc89b83578a8bbe5a188b58..cc23ce4ffb1f1dd86a81aed84207415bdba2e24b 100644 (file)
@@ -18,6 +18,8 @@ obj-$(CONFIG_NVMEM_IMX_IIM)           += nvmem-imx-iim.o
 nvmem-imx-iim-y                                := imx-iim.o
 obj-$(CONFIG_NVMEM_IMX_OCOTP)          += nvmem-imx-ocotp.o
 nvmem-imx-ocotp-y                      := imx-ocotp.o
+obj-$(CONFIG_NVMEM_IMX_OCOTP_ELE)      += nvmem-imx-ocotp-ele.o
+nvmem-imx-ocotp-ele-y                  := imx-ocotp-ele.o
 obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU)      += nvmem-imx-ocotp-scu.o
 nvmem-imx-ocotp-scu-y                  := imx-ocotp-scu.o
 obj-$(CONFIG_NVMEM_JZ4780_EFUSE)       += nvmem_jz4780_efuse.o
index 39aa27942f28b3d49ed91327e574666023c4fd6f..4567c597c87f26c70402bced7d52bf5160094cf8 100644 (file)
@@ -4,6 +4,8 @@
  */
 
 #include <linux/bcm47xx_nvram.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
 #include <linux/io.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
@@ -42,6 +44,25 @@ static int brcm_nvram_read(void *context, unsigned int offset, void *val,
        return 0;
 }
 
+static int brcm_nvram_read_post_process_macaddr(void *context, const char *id, int index,
+                                               unsigned int offset, void *buf, size_t bytes)
+{
+       u8 mac[ETH_ALEN];
+
+       if (bytes != 3 * ETH_ALEN - 1)
+               return -EINVAL;
+
+       if (!mac_pton(buf, mac))
+               return -EINVAL;
+
+       if (index)
+               eth_addr_add(mac, index);
+
+       ether_addr_copy(buf, mac);
+
+       return 0;
+}
+
 static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data,
                                size_t len)
 {
@@ -75,6 +96,13 @@ static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data,
                priv->cells[idx].offset = value - (char *)data;
                priv->cells[idx].bytes = strlen(value);
                priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
+               if (!strcmp(var, "et0macaddr") ||
+                   !strcmp(var, "et1macaddr") ||
+                   !strcmp(var, "et2macaddr")) {
+                       priv->cells[idx].raw_len = strlen(value);
+                       priv->cells[idx].bytes = ETH_ALEN;
+                       priv->cells[idx].read_post_process = brcm_nvram_read_post_process_macaddr;
+               }
        }
 
        return 0;
index 342cd380b4201e13a48a2ccf8ba9b505ef1f27f5..3f8c7718412b484ba649dd9f540dd6479dbf0ab6 100644 (file)
@@ -696,7 +696,7 @@ static int nvmem_validate_keepouts(struct nvmem_device *nvmem)
        return 0;
 }
 
-static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
+static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np)
 {
        struct nvmem_layout *layout = nvmem->layout;
        struct device *dev = &nvmem->dev;
@@ -704,7 +704,7 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
        const __be32 *addr;
        int len, ret;
 
-       for_each_child_of_node(dev->of_node, child) {
+       for_each_child_of_node(np, child) {
                struct nvmem_cell_info info = {0};
 
                addr = of_get_property(child, "reg", &len);
@@ -742,6 +742,28 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
        return 0;
 }
 
+static int nvmem_add_cells_from_legacy_of(struct nvmem_device *nvmem)
+{
+       return nvmem_add_cells_from_dt(nvmem, nvmem->dev.of_node);
+}
+
+static int nvmem_add_cells_from_fixed_layout(struct nvmem_device *nvmem)
+{
+       struct device_node *layout_np;
+       int err = 0;
+
+       layout_np = of_nvmem_layout_get_container(nvmem);
+       if (!layout_np)
+               return 0;
+
+       if (of_device_is_compatible(layout_np, "fixed-layout"))
+               err = nvmem_add_cells_from_dt(nvmem, layout_np);
+
+       of_node_put(layout_np);
+
+       return err;
+}
+
 int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner)
 {
        layout->owner = owner;
@@ -972,7 +994,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
        if (rval)
                goto err_remove_cells;
 
-       rval = nvmem_add_cells_from_of(nvmem);
+       rval = nvmem_add_cells_from_legacy_of(nvmem);
        if (rval)
                goto err_remove_cells;
 
@@ -982,6 +1004,10 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
        if (rval)
                goto err_remove_cells;
 
+       rval = nvmem_add_cells_from_fixed_layout(nvmem);
+       if (rval)
+               goto err_remove_cells;
+
        rval = nvmem_add_cells_from_layout(nvmem);
        if (rval)
                goto err_remove_cells;
diff --git a/drivers/nvmem/imx-ocotp-ele.c b/drivers/nvmem/imx-ocotp-ele.c
new file mode 100644 (file)
index 0000000..f1cbbc9
--- /dev/null
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * i.MX9 OCOTP fusebox driver
+ *
+ * Copyright 2023 NXP
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+enum fuse_type {
+       FUSE_FSB = 1,
+       FUSE_ELE = 2,
+       FUSE_INVALID = -1
+};
+
+struct ocotp_map_entry {
+       u32 start; /* start word */
+       u32 num; /* num words */
+       enum fuse_type type;
+};
+
+struct ocotp_devtype_data {
+       u32 reg_off;
+       char *name;
+       u32 size;
+       u32 num_entry;
+       u32 flag;
+       nvmem_reg_read_t reg_read;
+       struct ocotp_map_entry entry[];
+};
+
+struct imx_ocotp_priv {
+       struct device *dev;
+       void __iomem *base;
+       struct nvmem_config config;
+       struct mutex lock;
+       const struct ocotp_devtype_data *data;
+};
+
+static enum fuse_type imx_ocotp_fuse_type(void *context, u32 index)
+{
+       struct imx_ocotp_priv *priv = context;
+       const struct ocotp_devtype_data *data = priv->data;
+       u32 start, end;
+       int i;
+
+       for (i = 0; i < data->num_entry; i++) {
+               start = data->entry[i].start;
+               end = data->entry[i].start + data->entry[i].num;
+
+               if (index >= start && index < end)
+                       return data->entry[i].type;
+       }
+
+       return FUSE_INVALID;
+}
+
+static int imx_ocotp_reg_read(void *context, unsigned int offset, void *val, size_t bytes)
+{
+       struct imx_ocotp_priv *priv = context;
+       void __iomem *reg = priv->base + priv->data->reg_off;
+       u32 count, index, num_bytes;
+       enum fuse_type type;
+       u32 *buf;
+       void *p;
+       int i;
+
+       index = offset;
+       num_bytes = round_up(bytes, 4);
+       count = num_bytes >> 2;
+
+       if (count > ((priv->data->size >> 2) - index))
+               count = (priv->data->size >> 2) - index;
+
+       p = kzalloc(num_bytes, GFP_KERNEL);
+       if (!p)
+               return -ENOMEM;
+
+       mutex_lock(&priv->lock);
+
+       buf = p;
+
+       for (i = index; i < (index + count); i++) {
+               type = imx_ocotp_fuse_type(context, i);
+               if (type == FUSE_INVALID || type == FUSE_ELE) {
+                       *buf++ = 0;
+                       continue;
+               }
+
+               *buf++ = readl_relaxed(reg + (i << 2));
+       }
+
+       memcpy(val, (u8 *)p, bytes);
+
+       mutex_unlock(&priv->lock);
+
+       kfree(p);
+
+       return 0;
+};
+
+static int imx_ele_ocotp_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct imx_ocotp_priv *priv;
+       struct nvmem_device *nvmem;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->data = of_device_get_match_data(dev);
+
+       priv->base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(priv->base))
+               return PTR_ERR(priv->base);
+
+       priv->config.dev = dev;
+       priv->config.name = "ELE-OCOTP";
+       priv->config.id = NVMEM_DEVID_AUTO;
+       priv->config.owner = THIS_MODULE;
+       priv->config.size = priv->data->size;
+       priv->config.reg_read = priv->data->reg_read;
+       priv->config.word_size = 4;
+       priv->config.stride = 1;
+       priv->config.priv = priv;
+       priv->config.read_only = true;
+       mutex_init(&priv->lock);
+
+       nvmem = devm_nvmem_register(dev, &priv->config);
+       if (IS_ERR(nvmem))
+               return PTR_ERR(nvmem);
+
+       return 0;
+}
+
+static const struct ocotp_devtype_data imx93_ocotp_data = {
+       .reg_off = 0x8000,
+       .reg_read = imx_ocotp_reg_read,
+       .size = 2048,
+       .num_entry = 6,
+       .entry = {
+               { 0, 52, FUSE_FSB },
+               { 63, 1, FUSE_ELE},
+               { 128, 16, FUSE_ELE },
+               { 182, 1, FUSE_ELE },
+               { 188, 1, FUSE_ELE },
+               { 312, 200, FUSE_FSB }
+       },
+};
+
+static const struct of_device_id imx_ele_ocotp_dt_ids[] = {
+       { .compatible = "fsl,imx93-ocotp", .data = &imx93_ocotp_data, },
+       {},
+};
+MODULE_DEVICE_TABLE(of, imx_ele_ocotp_dt_ids);
+
+static struct platform_driver imx_ele_ocotp_driver = {
+       .driver = {
+               .name = "imx_ele_ocotp",
+               .of_match_table = imx_ele_ocotp_dt_ids,
+       },
+       .probe = imx_ele_ocotp_probe,
+};
+module_platform_driver(imx_ele_ocotp_driver);
+
+MODULE_DESCRIPTION("i.MX OCOTP/ELE driver");
+MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
+MODULE_LICENSE("GPL");
index ac0edb6398f1eff41e72ae6f0d2e75f0c21cdf32..ab556c011f3e8e2eb441a003094fb296b485119c 100644 (file)
@@ -97,7 +97,6 @@ struct ocotp_params {
        unsigned int bank_address_words;
        void (*set_timing)(struct ocotp_priv *priv);
        struct ocotp_ctrl_reg ctrl;
-       bool reverse_mac_address;
 };
 
 static int imx_ocotp_wait_for_busy(struct ocotp_priv *priv, u32 flags)
@@ -545,7 +544,6 @@ static const struct ocotp_params imx8mq_params = {
        .bank_address_words = 0,
        .set_timing = imx_ocotp_set_imx6_timing,
        .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
-       .reverse_mac_address = true,
 };
 
 static const struct ocotp_params imx8mm_params = {
@@ -553,7 +551,6 @@ static const struct ocotp_params imx8mm_params = {
        .bank_address_words = 0,
        .set_timing = imx_ocotp_set_imx6_timing,
        .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
-       .reverse_mac_address = true,
 };
 
 static const struct ocotp_params imx8mn_params = {
@@ -561,7 +558,6 @@ static const struct ocotp_params imx8mn_params = {
        .bank_address_words = 0,
        .set_timing = imx_ocotp_set_imx6_timing,
        .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
-       .reverse_mac_address = true,
 };
 
 static const struct ocotp_params imx8mp_params = {
@@ -569,7 +565,6 @@ static const struct ocotp_params imx8mp_params = {
        .bank_address_words = 0,
        .set_timing = imx_ocotp_set_imx6_timing,
        .ctrl = IMX_OCOTP_BM_CTRL_8MP,
-       .reverse_mac_address = true,
 };
 
 static const struct of_device_id imx_ocotp_dt_ids[] = {
@@ -596,7 +591,7 @@ static void imx_ocotp_fixup_cell_info(struct nvmem_device *nvmem,
        cell->read_post_process = imx_ocotp_cell_pp;
 }
 
-struct nvmem_layout imx_ocotp_layout = {
+static struct nvmem_layout imx_ocotp_layout = {
        .fixup_cell_info = imx_ocotp_fixup_cell_info,
 };
 
@@ -624,8 +619,7 @@ static int imx_ocotp_probe(struct platform_device *pdev)
        imx_ocotp_nvmem_config.size = 4 * priv->params->nregs;
        imx_ocotp_nvmem_config.dev = dev;
        imx_ocotp_nvmem_config.priv = priv;
-       if (priv->params->reverse_mac_address)
-               imx_ocotp_nvmem_config.layout = &imx_ocotp_layout;
+       imx_ocotp_nvmem_config.layout = &imx_ocotp_layout;
 
        priv->config = &imx_ocotp_nvmem_config;
 
index 80cb187f14817b2961c6d1de885710387bcd33c4..752d0bf4445eef70c92e417a853a2b05506afbf1 100644 (file)
@@ -71,6 +71,7 @@ static int rmem_probe(struct platform_device *pdev)
        config.dev = dev;
        config.priv = priv;
        config.name = "rmem";
+       config.id = NVMEM_DEVID_AUTO;
        config.size = mem->size;
        config.reg_read = rmem_read;
 
index 9f53bcce2f877ff3fcfd7c850ed7960ef1f3755f..cb9aa5428350abd425639b29eb163f12e898909c 100644 (file)
 
 #define OTPC_TIMEOUT                   10000
 
+/* RK3588 Register */
+#define RK3588_OTPC_AUTO_CTRL          0x04
+#define RK3588_OTPC_AUTO_EN            0x08
+#define RK3588_OTPC_INT_ST             0x84
+#define RK3588_OTPC_DOUT0              0x20
+#define RK3588_NO_SECURE_OFFSET                0x300
+#define RK3588_NBYTES                  4
+#define RK3588_BURST_NUM               1
+#define RK3588_BURST_SHIFT             8
+#define RK3588_ADDR_SHIFT              16
+#define RK3588_AUTO_EN                 BIT(0)
+#define RK3588_RD_DONE                 BIT(1)
+
+struct rockchip_data {
+       int size;
+       const char * const *clks;
+       int num_clks;
+       nvmem_reg_read_t reg_read;
+};
+
 struct rockchip_otp {
        struct device *dev;
        void __iomem *base;
-       struct clk_bulk_data    *clks;
-       int num_clks;
+       struct clk_bulk_data *clks;
        struct reset_control *rst;
-};
-
-/* list of required clocks */
-static const char * const rockchip_otp_clocks[] = {
-       "otp", "apb_pclk", "phy",
-};
-
-struct rockchip_data {
-       int size;
+       const struct rockchip_data *data;
 };
 
 static int rockchip_otp_reset(struct rockchip_otp *otp)
@@ -92,18 +103,19 @@ static int rockchip_otp_reset(struct rockchip_otp *otp)
        return 0;
 }
 
-static int rockchip_otp_wait_status(struct rockchip_otp *otp, u32 flag)
+static int rockchip_otp_wait_status(struct rockchip_otp *otp,
+                                   unsigned int reg, u32 flag)
 {
        u32 status = 0;
        int ret;
 
-       ret = readl_poll_timeout_atomic(otp->base + OTPC_INT_STATUS, status,
+       ret = readl_poll_timeout_atomic(otp->base + reg, status,
                                        (status & flag), 1, OTPC_TIMEOUT);
        if (ret)
                return ret;
 
        /* clean int status */
-       writel(flag, otp->base + OTPC_INT_STATUS);
+       writel(flag, otp->base + reg);
 
        return 0;
 }
@@ -125,36 +137,30 @@ static int rockchip_otp_ecc_enable(struct rockchip_otp *otp, bool enable)
 
        writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
 
-       ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE);
+       ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_SBPI_DONE);
        if (ret < 0)
                dev_err(otp->dev, "timeout during ecc_enable\n");
 
        return ret;
 }
 
-static int rockchip_otp_read(void *context, unsigned int offset,
-                            void *val, size_t bytes)
+static int px30_otp_read(void *context, unsigned int offset,
+                        void *val, size_t bytes)
 {
        struct rockchip_otp *otp = context;
        u8 *buf = val;
-       int ret = 0;
-
-       ret = clk_bulk_prepare_enable(otp->num_clks, otp->clks);
-       if (ret < 0) {
-               dev_err(otp->dev, "failed to prepare/enable clks\n");
-               return ret;
-       }
+       int ret;
 
        ret = rockchip_otp_reset(otp);
        if (ret) {
                dev_err(otp->dev, "failed to reset otp phy\n");
-               goto disable_clks;
+               return ret;
        }
 
        ret = rockchip_otp_ecc_enable(otp, false);
        if (ret < 0) {
                dev_err(otp->dev, "rockchip_otp_ecc_enable err\n");
-               goto disable_clks;
+               return ret;
        }
 
        writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
@@ -164,7 +170,7 @@ static int rockchip_otp_read(void *context, unsigned int offset,
                       otp->base + OTPC_USER_ADDR);
                writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
                       otp->base + OTPC_USER_ENABLE);
-               ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE);
+               ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_USER_DONE);
                if (ret < 0) {
                        dev_err(otp->dev, "timeout during read setup\n");
                        goto read_end;
@@ -174,8 +180,74 @@ static int rockchip_otp_read(void *context, unsigned int offset,
 
 read_end:
        writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
-disable_clks:
-       clk_bulk_disable_unprepare(otp->num_clks, otp->clks);
+
+       return ret;
+}
+
+static int rk3588_otp_read(void *context, unsigned int offset,
+                          void *val, size_t bytes)
+{
+       struct rockchip_otp *otp = context;
+       unsigned int addr_start, addr_end, addr_len;
+       int ret, i = 0;
+       u32 data;
+       u8 *buf;
+
+       addr_start = round_down(offset, RK3588_NBYTES) / RK3588_NBYTES;
+       addr_end = round_up(offset + bytes, RK3588_NBYTES) / RK3588_NBYTES;
+       addr_len = addr_end - addr_start;
+       addr_start += RK3588_NO_SECURE_OFFSET;
+
+       buf = kzalloc(array_size(addr_len, RK3588_NBYTES), GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       while (addr_len--) {
+               writel((addr_start << RK3588_ADDR_SHIFT) |
+                      (RK3588_BURST_NUM << RK3588_BURST_SHIFT),
+                      otp->base + RK3588_OTPC_AUTO_CTRL);
+               writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN);
+
+               ret = rockchip_otp_wait_status(otp, RK3588_OTPC_INT_ST,
+                                              RK3588_RD_DONE);
+               if (ret < 0) {
+                       dev_err(otp->dev, "timeout during read setup\n");
+                       goto read_end;
+               }
+
+               data = readl(otp->base + RK3588_OTPC_DOUT0);
+               memcpy(&buf[i], &data, RK3588_NBYTES);
+
+               i += RK3588_NBYTES;
+               addr_start++;
+       }
+
+       memcpy(val, buf + offset % RK3588_NBYTES, bytes);
+
+read_end:
+       kfree(buf);
+
+       return ret;
+}
+
+static int rockchip_otp_read(void *context, unsigned int offset,
+                            void *val, size_t bytes)
+{
+       struct rockchip_otp *otp = context;
+       int ret;
+
+       if (!otp->data || !otp->data->reg_read)
+               return -EINVAL;
+
+       ret = clk_bulk_prepare_enable(otp->data->num_clks, otp->clks);
+       if (ret < 0) {
+               dev_err(otp->dev, "failed to prepare/enable clks\n");
+               return ret;
+       }
+
+       ret = otp->data->reg_read(context, offset, val, bytes);
+
+       clk_bulk_disable_unprepare(otp->data->num_clks, otp->clks);
 
        return ret;
 }
@@ -189,18 +261,40 @@ static struct nvmem_config otp_config = {
        .reg_read = rockchip_otp_read,
 };
 
+static const char * const px30_otp_clocks[] = {
+       "otp", "apb_pclk", "phy",
+};
+
 static const struct rockchip_data px30_data = {
        .size = 0x40,
+       .clks = px30_otp_clocks,
+       .num_clks = ARRAY_SIZE(px30_otp_clocks),
+       .reg_read = px30_otp_read,
+};
+
+static const char * const rk3588_otp_clocks[] = {
+       "otp", "apb_pclk", "phy", "arb",
+};
+
+static const struct rockchip_data rk3588_data = {
+       .size = 0x400,
+       .clks = rk3588_otp_clocks,
+       .num_clks = ARRAY_SIZE(rk3588_otp_clocks),
+       .reg_read = rk3588_otp_read,
 };
 
 static const struct of_device_id rockchip_otp_match[] = {
        {
                .compatible = "rockchip,px30-otp",
-               .data = (void *)&px30_data,
+               .data = &px30_data,
        },
        {
                .compatible = "rockchip,rk3308-otp",
-               .data = (void *)&px30_data,
+               .data = &px30_data,
+       },
+       {
+               .compatible = "rockchip,rk3588-otp",
+               .data = &rk3588_data,
        },
        { /* sentinel */ },
 };
@@ -215,44 +309,47 @@ static int rockchip_otp_probe(struct platform_device *pdev)
        int ret, i;
 
        data = of_device_get_match_data(dev);
-       if (!data) {
-               dev_err(dev, "failed to get match data\n");
-               return -EINVAL;
-       }
+       if (!data)
+               return dev_err_probe(dev, -EINVAL, "failed to get match data\n");
 
        otp = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_otp),
                           GFP_KERNEL);
        if (!otp)
                return -ENOMEM;
 
+       otp->data = data;
        otp->dev = dev;
        otp->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(otp->base))
-               return PTR_ERR(otp->base);
+               return dev_err_probe(dev, PTR_ERR(otp->base),
+                                    "failed to ioremap resource\n");
 
-       otp->num_clks = ARRAY_SIZE(rockchip_otp_clocks);
-       otp->clks = devm_kcalloc(dev, otp->num_clks,
-                                    sizeof(*otp->clks), GFP_KERNEL);
+       otp->clks = devm_kcalloc(dev, data->num_clks, sizeof(*otp->clks),
+                                GFP_KERNEL);
        if (!otp->clks)
                return -ENOMEM;
 
-       for (i = 0; i < otp->num_clks; ++i)
-               otp->clks[i].id = rockchip_otp_clocks[i];
+       for (i = 0; i < data->num_clks; ++i)
+               otp->clks[i].id = data->clks[i];
 
-       ret = devm_clk_bulk_get(dev, otp->num_clks, otp->clks);
+       ret = devm_clk_bulk_get(dev, data->num_clks, otp->clks);
        if (ret)
-               return ret;
+               return dev_err_probe(dev, ret, "failed to get clocks\n");
 
-       otp->rst = devm_reset_control_get(dev, "phy");
+       otp->rst = devm_reset_control_array_get_exclusive(dev);
        if (IS_ERR(otp->rst))
-               return PTR_ERR(otp->rst);
+               return dev_err_probe(dev, PTR_ERR(otp->rst),
+                                    "failed to get resets\n");
 
        otp_config.size = data->size;
        otp_config.priv = otp;
        otp_config.dev = dev;
-       nvmem = devm_nvmem_register(dev, &otp_config);
 
-       return PTR_ERR_OR_ZERO(nvmem);
+       nvmem = devm_nvmem_register(dev, &otp_config);
+       if (IS_ERR(nvmem))
+               return dev_err_probe(dev, PTR_ERR(nvmem),
+                                    "failed to register nvmem device\n");
+       return 0;
 }
 
 static struct platform_driver rockchip_otp_driver = {
index 52b928a7a6d580dae75ed0ea3cc104b96be4949f..f85350b17d6725f0b2a633156f9e95291c1c2e2b 100644 (file)
@@ -192,9 +192,11 @@ static int sp_ocotp_probe(struct platform_device *pdev)
        sp_ocotp_nvmem_config.dev = dev;
 
        nvmem = devm_nvmem_register(dev, &sp_ocotp_nvmem_config);
-       if (IS_ERR(nvmem))
-               return dev_err_probe(&pdev->dev, PTR_ERR(nvmem),
+       if (IS_ERR(nvmem)) {
+               ret = dev_err_probe(&pdev->dev, PTR_ERR(nvmem),
                                                "register nvmem device fail\n");
+               goto err;
+       }
 
        platform_set_drvdata(pdev, nvmem);
 
@@ -203,6 +205,9 @@ static int sp_ocotp_probe(struct platform_device *pdev)
                (int)OTP_WORD_SIZE, (int)QAC628_OTP_SIZE);
 
        return 0;
+err:
+       clk_unprepare(otp->clk);
+       return ret;
 }
 
 static const struct of_device_id sp_ocotp_dt_ids[] = {
index e28d7b133e11b07bd0f0277b9d6e1d85d9ee5b62..f49bb9a26d0532307d0ced507b1cbc1044160ef4 100644 (file)
@@ -76,6 +76,6 @@ static struct platform_driver zynqmp_nvmem_driver = {
 
 module_platform_driver(zynqmp_nvmem_driver);
 
-MODULE_AUTHOR("Michal Simek <michal.simek@xilinx.com>, Nava kishore Manne <navam@xilinx.com>");
+MODULE_AUTHOR("Michal Simek <michal.simek@amd.com>, Nava kishore Manne <nava.kishore.manne@amd.com>");
 MODULE_DESCRIPTION("ZynqMP NVMEM driver");
 MODULE_LICENSE("GPL");
index 5561362224e254a71857d04a9fb1c0e79bdc0227..631c193fe42c5280e6808f312243ecd770fdb4fb 100644 (file)
@@ -42,7 +42,8 @@ if PARPORT
 
 config PARPORT_PC
        tristate "PC-style hardware"
-       depends on ARCH_MIGHT_HAVE_PC_PARPORT || (PCI && !S390)
+       depends on ARCH_MIGHT_HAVE_PC_PARPORT || PCI
+       depends on HAS_IOPORT
        help
          You should say Y here if you have a PC-style parallel port. All
          IBM PC compatible computers and some Alphas have PC-style
index f4e2a88729fd144bfa125a7378153b4cd26fd34c..c525867760bf819c0af9ccf601844b2c37d0ca49 100644 (file)
@@ -6003,8 +6003,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x56c1, aspm_l1_acceptable_latency
 
 #ifdef CONFIG_PCIE_DPC
 /*
- * Intel Tiger Lake and Alder Lake BIOS has a bug that clears the DPC
- * RP PIO Log Size of the integrated Thunderbolt PCIe Root Ports.
+ * Intel Ice Lake, Tiger Lake and Alder Lake BIOS has a bug that clears
+ * the DPC RP PIO Log Size of the integrated Thunderbolt PCIe Root
+ * Ports.
  */
 static void dpc_log_size(struct pci_dev *dev)
 {
@@ -6027,6 +6028,10 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x461f, dpc_log_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x462f, dpc_log_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x463f, dpc_log_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x466e, dpc_log_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8a1d, dpc_log_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8a1f, dpc_log_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8a21, dpc_log_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8a23, dpc_log_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a23, dpc_log_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a25, dpc_log_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a27, dpc_log_size);
index 44c16508ef14fcb7e45b1c894428efc1738cc31c..e72419d7e72e5c5a53909f05d74a078a12d069ac 100644 (file)
@@ -5,7 +5,6 @@
 
 menuconfig PCCARD
        tristate "PCCard (PCMCIA/CardBus) support"
-       depends on !UML
        help
          Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
          computer.  These are credit-card size devices such as network cards,
@@ -113,7 +112,7 @@ config YENTA_TOSHIBA
 
 config PD6729
        tristate "Cirrus PD6729 compatible bridge support"
-       depends on PCMCIA && PCI
+       depends on PCMCIA && PCI && HAS_IOPORT
        select PCCARD_NONSTATIC
        help
          This provides support for the Cirrus PD6729 PCI-to-PCMCIA bridge
@@ -121,7 +120,7 @@ config PD6729
 
 config I82092
        tristate "i82092 compatible bridge support"
-       depends on PCMCIA && PCI
+       depends on PCMCIA && PCI && HAS_IOPORT
        select PCCARD_NONSTATIC
        help
          This provides support for the Intel I82092AA PCI-to-PCMCIA bridge device,
index 471e0c5815f390fb374f6295cb6ce1cd0a679b08..bf9d070a44966d0a4206a702d94038e52c45b02a 100644 (file)
@@ -1053,6 +1053,8 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s)
                q = p->next;
                kfree(p);
        }
+
+       kfree(data);
 }
 
 
index c14089fa7db495b869556e785a9ff1651419d0a4..cabdddbbabfd7dc251a7027b6e5745dea398d273 100644 (file)
@@ -70,7 +70,7 @@ static int phy_g12a_mipi_dphy_analog_power_on(struct phy *phy)
                     HHI_MIPI_CNTL1_BANDGAP);
 
        regmap_write(priv->regmap, HHI_MIPI_CNTL2,
-                    FIELD_PREP(HHI_MIPI_CNTL2_DIF_TX_CTL0, 0x459) |
+                    FIELD_PREP(HHI_MIPI_CNTL2_DIF_TX_CTL0, 0x45a) |
                     FIELD_PREP(HHI_MIPI_CNTL2_DIF_TX_CTL1, 0x2680));
 
        reg = DSI_LANE_CLK;
index caa953780beebb85a07fe2e582ad70fbfec43f55..8aa7251de4a96e48c4a0148950e0961d3ba6d9a0 100644 (file)
@@ -237,11 +237,11 @@ static int mtk_hdmi_pll_calc(struct mtk_hdmi_phy *hdmi_phy, struct clk_hw *hw,
         */
        if (tmds_clk < 54 * MEGA)
                txposdiv = 8;
-       else if (tmds_clk >= 54 * MEGA && tmds_clk < 148.35 * MEGA)
+       else if (tmds_clk >= 54 * MEGA && (tmds_clk * 100) < 14835 * MEGA)
                txposdiv = 4;
-       else if (tmds_clk >= 148.35 * MEGA && tmds_clk < 296.7 * MEGA)
+       else if ((tmds_clk * 100) >= 14835 * MEGA && (tmds_clk * 10) < 2967 * MEGA)
                txposdiv = 2;
-       else if (tmds_clk >= 296.7 * MEGA && tmds_clk <= 594 * MEGA)
+       else if ((tmds_clk * 10) >= 2967 * MEGA && tmds_clk <= 594 * MEGA)
                txposdiv = 1;
        else
                return -EINVAL;
@@ -324,12 +324,12 @@ static int mtk_hdmi_pll_drv_setting(struct clk_hw *hw)
                clk_channel_bias = 0x34; /* 20mA */
                impedance_en = 0xf;
                impedance = 0x36; /* 100ohm */
-       } else if (pixel_clk >= 74.175 * MEGA && pixel_clk <= 300 * MEGA) {
+       } else if (((u64)pixel_clk * 1000) >= 74175 * MEGA && pixel_clk <= 300 * MEGA) {
                data_channel_bias = 0x34; /* 20mA */
                clk_channel_bias = 0x2c; /* 16mA */
                impedance_en = 0xf;
                impedance = 0x36; /* 100ohm */
-       } else if (pixel_clk >= 27 * MEGA && pixel_clk < 74.175 * MEGA) {
+       } else if (pixel_clk >= 27 * MEGA && ((u64)pixel_clk * 1000) < 74175 * MEGA) {
                data_channel_bias = 0x14; /* 10mA */
                clk_channel_bias = 0x14; /* 10mA */
                impedance_en = 0x0;
index 6850e04c329b8e679814890d799e7f83e78176cc..87b17e5877ab8c6d9ed1ab082cda5ba974ab617b 100644 (file)
@@ -2472,7 +2472,7 @@ static int qmp_combo_com_init(struct qmp_combo *qmp)
        ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
        if (ret) {
                dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
-               goto err_unlock;
+               goto err_decrement_count;
        }
 
        ret = reset_control_bulk_assert(cfg->num_resets, qmp->resets);
@@ -2522,7 +2522,8 @@ err_assert_reset:
        reset_control_bulk_assert(cfg->num_resets, qmp->resets);
 err_disable_regulators:
        regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
-err_unlock:
+err_decrement_count:
+       qmp->init_count--;
        mutex_unlock(&qmp->phy_mutex);
 
        return ret;
index 09824be088c96c0b6354ff0488068b17e573a34b..0c603bc06e0998a95a0853072a10fffba87958ff 100644 (file)
@@ -379,7 +379,7 @@ static int qmp_pcie_msm8996_com_init(struct qmp_phy *qphy)
        ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
        if (ret) {
                dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
-               goto err_unlock;
+               goto err_decrement_count;
        }
 
        ret = reset_control_bulk_assert(cfg->num_resets, qmp->resets);
@@ -409,7 +409,8 @@ err_assert_reset:
        reset_control_bulk_assert(cfg->num_resets, qmp->resets);
 err_disable_regulators:
        regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
-err_unlock:
+err_decrement_count:
+       qmp->init_count--;
        mutex_unlock(&qmp->phy_mutex);
 
        return ret;
index a590635962140f817e0ee3287d576bbd043ffa3c..6c237f3cc66db8235dd3ae100ce11a487a8bf06c 100644 (file)
@@ -115,11 +115,11 @@ struct phy_override_seq {
  *
  * @cfg_ahb_clk: AHB2PHY interface clock
  * @ref_clk: phy reference clock
- * @iface_clk: phy interface clock
  * @phy_reset: phy reset control
  * @vregs: regulator supplies bulk data
  * @phy_initialized: if PHY has been initialized correctly
  * @mode: contains the current mode the PHY is in
+ * @update_seq_cfg: tuning parameters for phy init
  */
 struct qcom_snps_hsphy {
        struct phy *phy;
index c2c9b0d3244cbf2bc0cfad486169a0741d0d931e..be967d797c28e04c6ce726b434e0edb322737f88 100644 (file)
@@ -1348,9 +1348,8 @@ static int mlxbf_pmc_map_counters(struct device *dev)
 
        for (i = 0; i < pmc->total_blocks; ++i) {
                if (strstr(pmc->block_name[i], "tile")) {
-                       ret = sscanf(pmc->block_name[i], "tile%d", &tile_num);
-                       if (ret < 0)
-                               return ret;
+                       if (sscanf(pmc->block_name[i], "tile%d", &tile_num) != 1)
+                               return -EINVAL;
 
                        if (tile_num >= pmc->tile_count)
                                continue;
index 91a077c35b8b86426d380446bb9d80a77152463e..a79318e90a13917ab090c363de3cb6c038a57bb0 100644 (file)
@@ -784,7 +784,7 @@ static void mlxbf_tmfifo_rxtx(struct mlxbf_tmfifo_vring *vring, bool is_rx)
        fifo = vring->fifo;
 
        /* Return if vdev is not ready. */
-       if (!fifo->vdev[devid])
+       if (!fifo || !fifo->vdev[devid])
                return;
 
        /* Return if another vring is running. */
@@ -980,9 +980,13 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev,
 
                vq->num_max = vring->num;
 
+               vq->priv = vring;
+
+               /* Make vq update visible before using it. */
+               virtio_mb(false);
+
                vqs[i] = vq;
                vring->vq = vq;
-               vq->priv = vring;
        }
 
        return 0;
@@ -1302,6 +1306,9 @@ static int mlxbf_tmfifo_probe(struct platform_device *pdev)
 
        mod_timer(&fifo->timer, jiffies + MLXBF_TMFIFO_TIMER_INTERVAL);
 
+       /* Make all updates visible before setting the 'is_ready' flag. */
+       virtio_mb(false);
+
        fifo->is_ready = true;
        return 0;
 
index d5bb775dadcf20328294da3cea153075c6456138..ee5f124f78b6d712a58e944fe114f817e6c76ae3 100644 (file)
@@ -245,24 +245,29 @@ static const struct pci_device_id pmf_pci_ids[] = {
        { }
 };
 
-int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
+static void amd_pmf_set_dram_addr(struct amd_pmf_dev *dev)
 {
        u64 phys_addr;
        u32 hi, low;
 
-       INIT_DELAYED_WORK(&dev->work_buffer, amd_pmf_get_metrics);
+       phys_addr = virt_to_phys(dev->buf);
+       hi = phys_addr >> 32;
+       low = phys_addr & GENMASK(31, 0);
+
+       amd_pmf_send_cmd(dev, SET_DRAM_ADDR_HIGH, 0, hi, NULL);
+       amd_pmf_send_cmd(dev, SET_DRAM_ADDR_LOW, 0, low, NULL);
+}
 
+int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
+{
        /* Get Metrics Table Address */
        dev->buf = kzalloc(sizeof(dev->m_table), GFP_KERNEL);
        if (!dev->buf)
                return -ENOMEM;
 
-       phys_addr = virt_to_phys(dev->buf);
-       hi = phys_addr >> 32;
-       low = phys_addr & GENMASK(31, 0);
+       INIT_DELAYED_WORK(&dev->work_buffer, amd_pmf_get_metrics);
 
-       amd_pmf_send_cmd(dev, SET_DRAM_ADDR_HIGH, 0, hi, NULL);
-       amd_pmf_send_cmd(dev, SET_DRAM_ADDR_LOW, 0, low, NULL);
+       amd_pmf_set_dram_addr(dev);
 
        /*
         * Start collecting the metrics data after a small delay
@@ -273,6 +278,18 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
        return 0;
 }
 
+static int amd_pmf_resume_handler(struct device *dev)
+{
+       struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
+
+       if (pdev->buf)
+               amd_pmf_set_dram_addr(pdev);
+
+       return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmf_pm, NULL, amd_pmf_resume_handler);
+
 static void amd_pmf_init_features(struct amd_pmf_dev *dev)
 {
        int ret;
@@ -413,6 +430,7 @@ static struct platform_driver amd_pmf_driver = {
                .name = "amd-pmf",
                .acpi_match_table = amd_pmf_acpi_ids,
                .dev_groups = amd_pmf_driver_groups,
+               .pm = pm_sleep_ptr(&amd_pmf_pm),
        },
        .probe = amd_pmf_probe,
        .remove_new = amd_pmf_remove,
index e2c9a68d12df9cc00ce3deda7964fb12bfd23a0f..fdf7da06af3067495fe7132e725a52542010ff8d 100644 (file)
@@ -555,6 +555,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
        { KE_KEY, 0x71, { KEY_F13 } }, /* General-purpose button */
        { KE_IGNORE, 0x79, },  /* Charger type dectection notification */
        { KE_KEY, 0x7a, { KEY_ALS_TOGGLE } }, /* Ambient Light Sensor Toggle */
+       { KE_IGNORE, 0x7B, }, /* Charger connect/disconnect notification */
        { KE_KEY, 0x7c, { KEY_MICMUTE } },
        { KE_KEY, 0x7D, { KEY_BLUETOOTH } }, /* Bluetooth Enable */
        { KE_KEY, 0x7E, { KEY_BLUETOOTH } }, /* Bluetooth Disable */
@@ -584,6 +585,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
        { KE_KEY, 0xAE, { KEY_FN_F5 } }, /* Fn+F5 fan mode on 2020+ */
        { KE_KEY, 0xB3, { KEY_PROG4 } }, /* AURA */
        { KE_KEY, 0xB5, { KEY_CALC } },
+       { KE_IGNORE, 0xC0, }, /* External display connect/disconnect notification */
        { KE_KEY, 0xC4, { KEY_KBDILLUMUP } },
        { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } },
        { KE_IGNORE, 0xC6, },  /* Ambient Light Sensor notification */
index 873f59c3e280420f8635ccdb76f8906d877ed7ec..6364ae2627058384a71da53504693e067687f204 100644 (file)
@@ -211,6 +211,7 @@ struct bios_rfkill2_state {
 static const struct key_entry hp_wmi_keymap[] = {
        { KE_KEY, 0x02,    { KEY_BRIGHTNESSUP } },
        { KE_KEY, 0x03,    { KEY_BRIGHTNESSDOWN } },
+       { KE_KEY, 0x270,   { KEY_MICMUTE } },
        { KE_KEY, 0x20e6,  { KEY_PROG1 } },
        { KE_KEY, 0x20e8,  { KEY_MEDIA } },
        { KE_KEY, 0x2142,  { KEY_MEDIA } },
index 61dffb4c8a1dcd07c42623b78b90d7eda8dba884..e6ae8265f3a37eab17d9698a78363fbadf562265 100644 (file)
@@ -208,7 +208,7 @@ static int scan_chunks_sanity_check(struct device *dev)
                        continue;
                reinit_completion(&ifs_done);
                local_work.dev = dev;
-               INIT_WORK(&local_work.w, copy_hashes_authenticate_chunks);
+               INIT_WORK_ONSTACK(&local_work.w, copy_hashes_authenticate_chunks);
                schedule_work_on(cpu, &local_work.w);
                wait_for_completion(&ifs_done);
                if (ifsd->loading_error) {
index e0572a29212e850c28313bcca2822ca0097ba3c1..02fe360a59c7cf427c7293f5a0f3d89c78fe92ae 100644 (file)
@@ -304,14 +304,13 @@ struct isst_if_pkg_info {
 static struct isst_if_cpu_info *isst_cpu_info;
 static struct isst_if_pkg_info *isst_pkg_info;
 
-#define ISST_MAX_PCI_DOMAINS   8
-
 static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn)
 {
        struct pci_dev *matched_pci_dev = NULL;
        struct pci_dev *pci_dev = NULL;
+       struct pci_dev *_pci_dev = NULL;
        int no_matches = 0, pkg_id;
-       int i, bus_number;
+       int bus_number;
 
        if (bus_no < 0 || bus_no >= ISST_MAX_BUS_NUMBER || cpu < 0 ||
            cpu >= nr_cpu_ids || cpu >= num_possible_cpus())
@@ -323,12 +322,11 @@ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn
        if (bus_number < 0)
                return NULL;
 
-       for (i = 0; i < ISST_MAX_PCI_DOMAINS; ++i) {
-               struct pci_dev *_pci_dev;
+       for_each_pci_dev(_pci_dev) {
                int node;
 
-               _pci_dev = pci_get_domain_bus_and_slot(i, bus_number, PCI_DEVFN(dev, fn));
-               if (!_pci_dev)
+               if (_pci_dev->bus->number != bus_number ||
+                   _pci_dev->devfn != PCI_DEVFN(dev, fn))
                        continue;
 
                ++no_matches;
index 1a300e14f350cccb65e920f16c0772c3603a1baa..064f186ae81b30573695e91e34c4061416cdec66 100644 (file)
@@ -44,14 +44,18 @@ static ssize_t store_min_max_freq_khz(struct uncore_data *data,
                                      int min_max)
 {
        unsigned int input;
+       int ret;
 
        if (kstrtouint(buf, 10, &input))
                return -EINVAL;
 
        mutex_lock(&uncore_lock);
-       uncore_write(data, input, min_max);
+       ret = uncore_write(data, input, min_max);
        mutex_unlock(&uncore_lock);
 
+       if (ret)
+               return ret;
+
        return count;
 }
 
index 80abc708e4f2f90c023db6d404dfd9626bf261af..d904fad499aa5de916ce58ff448ab478ee249cda 100644 (file)
@@ -34,6 +34,7 @@ static int intel_scu_pci_probe(struct pci_dev *pdev,
 
 static const struct pci_device_id pci_ids[] = {
        { PCI_VDEVICE(INTEL, 0x080e) },
+       { PCI_VDEVICE(INTEL, 0x082a) },
        { PCI_VDEVICE(INTEL, 0x08ea) },
        { PCI_VDEVICE(INTEL, 0x0a94) },
        { PCI_VDEVICE(INTEL, 0x11a0) },
index 6fe82f805ea85c0700dc620123c7c8e165fcc482..b3808ad77278d957ba5a2ab5d2e0dda6b91a155d 100644 (file)
@@ -10318,6 +10318,7 @@ static atomic_t dytc_ignore_event = ATOMIC_INIT(0);
 static DEFINE_MUTEX(dytc_mutex);
 static int dytc_capabilities;
 static bool dytc_mmc_get_available;
+static int profile_force;
 
 static int convert_dytc_to_profile(int funcmode, int dytcmode,
                enum platform_profile_option *profile)
@@ -10580,6 +10581,21 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
        if (err)
                return err;
 
+       /* Check if user wants to override the profile selection */
+       if (profile_force) {
+               switch (profile_force) {
+               case -1:
+                       dytc_capabilities = 0;
+                       break;
+               case 1:
+                       dytc_capabilities = BIT(DYTC_FC_MMC);
+                       break;
+               case 2:
+                       dytc_capabilities = BIT(DYTC_FC_PSC);
+                       break;
+               }
+               pr_debug("Profile selection forced: 0x%x\n", dytc_capabilities);
+       }
        if (dytc_capabilities & BIT(DYTC_FC_MMC)) { /* MMC MODE */
                pr_debug("MMC is supported\n");
                /*
@@ -10593,11 +10609,6 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
                                dytc_mmc_get_available = true;
                }
        } else if (dytc_capabilities & BIT(DYTC_FC_PSC)) { /* PSC MODE */
-               /* Support for this only works on AMD platforms */
-               if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) {
-                       dbg_printk(TPACPI_DBG_INIT, "PSC not support on Intel platforms\n");
-                       return -ENODEV;
-               }
                pr_debug("PSC is supported\n");
        } else {
                dbg_printk(TPACPI_DBG_INIT, "No DYTC support available\n");
@@ -11646,6 +11657,9 @@ MODULE_PARM_DESC(uwb_state,
                 "Initial state of the emulated UWB switch");
 #endif
 
+module_param(profile_force, int, 0444);
+MODULE_PARM_DESC(profile_force, "Force profile mode. -1=off, 1=MMC, 2=PSC");
+
 static void thinkpad_acpi_module_exit(void)
 {
        struct ibm_struct *ibm, *itmp;
index 13802a3c3591d8cd71f5c96928a6162875d10cf9..68e66b60445c3e40946308d3be7cc5421543d5a3 100644 (file)
@@ -336,6 +336,22 @@ static const struct ts_dmi_data dexp_ursus_7w_data = {
        .properties     = dexp_ursus_7w_props,
 };
 
+static const struct property_entry dexp_ursus_kx210i_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 5),
+       PROPERTY_ENTRY_U32("touchscreen-min-y",  2),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1720),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1137),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-dexp-ursus-kx210i.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
+       { }
+};
+
+static const struct ts_dmi_data dexp_ursus_kx210i_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = dexp_ursus_kx210i_props,
+};
+
 static const struct property_entry digma_citi_e200_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
@@ -378,6 +394,11 @@ static const struct ts_dmi_data gdix1001_01_upside_down_data = {
        .properties     = gdix1001_upside_down_props,
 };
 
+static const struct ts_dmi_data gdix1002_00_upside_down_data = {
+       .acpi_name      = "GDIX1002:00",
+       .properties     = gdix1001_upside_down_props,
+};
+
 static const struct property_entry gp_electronic_t701_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-size-x", 960),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 640),
@@ -1185,6 +1206,14 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "7W"),
                },
        },
+       {
+               /* DEXP Ursus KX210i */
+               .driver_data = (void *)&dexp_ursus_kx210i_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "INSYDE Corp."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S107I"),
+               },
+       },
        {
                /* Digma Citi E200 */
                .driver_data = (void *)&digma_citi_e200_data,
@@ -1295,6 +1324,18 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
                        DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"),
                },
        },
+       {
+               /* Juno Tablet */
+               .driver_data = (void *)&gdix1002_00_upside_down_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Default string"),
+                       /* Both product- and board-name being "Default string" is somewhat rare */
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
+                       DMI_MATCH(DMI_BOARD_NAME, "Default string"),
+                       /* Above matches are too generic, add partial bios-version match */
+                       DMI_MATCH(DMI_BIOS_VERSION, "JP2V1."),
+               },
+       },
        {
                /* Mediacom WinPad 7.0 W700 (same hw as Wintron surftab 7") */
                .driver_data = (void *)&trekstor_surftab_wintron70_data,
index 307ee6f71042e953f26a8f9c552aef63e10a6a13..6f83e99d2eb72e34b5666a76ecff1cf7ffd367ab 100644 (file)
@@ -624,10 +624,8 @@ static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data)
  */
 static void ab8500_btemp_external_power_changed(struct power_supply *psy)
 {
-       struct ab8500_btemp *di = power_supply_get_drvdata(psy);
-
-       class_for_each_device(power_supply_class, NULL,
-               di->btemp_psy, ab8500_btemp_get_ext_psy_data);
+       class_for_each_device(power_supply_class, NULL, psy,
+                             ab8500_btemp_get_ext_psy_data);
 }
 
 /* ab8500 btemp driver interrupts and their respective isr */
index 41a7bff9ac3765639a463b24aa94da8ef105dc51..53560fbb6dcd34bb08db8543ce9eb7e338afdb40 100644 (file)
@@ -2407,10 +2407,8 @@ out:
  */
 static void ab8500_fg_external_power_changed(struct power_supply *psy)
 {
-       struct ab8500_fg *di = power_supply_get_drvdata(psy);
-
-       class_for_each_device(power_supply_class, NULL,
-               di->fg_psy, ab8500_fg_get_ext_psy_data);
+       class_for_each_device(power_supply_class, NULL, psy,
+                             ab8500_fg_get_ext_psy_data);
 }
 
 /**
index 05f41317846296b067f41d050abc66d26cf09ff0..3be6f3b10ea4286e218f876798a0c7f0b99e4aa0 100644 (file)
@@ -507,7 +507,7 @@ static void fuel_gauge_external_power_changed(struct power_supply *psy)
        mutex_lock(&info->lock);
        info->valid = 0; /* Force updating of the cached registers */
        mutex_unlock(&info->lock);
-       power_supply_changed(info->bat);
+       power_supply_changed(psy);
 }
 
 static struct power_supply_desc fuel_gauge_desc = {
index de67b985f0a913a355ea3c27e3897d7373b78db2..dc33f00fcc0682a3c69ead86186df4219a1cd879 100644 (file)
@@ -1262,6 +1262,7 @@ static void bq24190_input_current_limit_work(struct work_struct *work)
        bq24190_charger_set_property(bdi->charger,
                                     POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
                                     &val);
+       power_supply_changed(bdi->charger);
 }
 
 /* Sync the input-current-limit with our parent supply (if we have one) */
index 22cde35eb144c612edc491307c06f5dddad9e3ab..f8636cf86505a7749eb7835eb422eda819137cf6 100644 (file)
@@ -750,7 +750,7 @@ static void bq25890_charger_external_power_changed(struct power_supply *psy)
        if (bq->chip_version != BQ25892)
                return;
 
-       ret = power_supply_get_property_from_supplier(bq->charger,
+       ret = power_supply_get_property_from_supplier(psy,
                                                      POWER_SUPPLY_PROP_USB_TYPE,
                                                      &val);
        if (ret)
@@ -775,6 +775,7 @@ static void bq25890_charger_external_power_changed(struct power_supply *psy)
        }
 
        bq25890_field_write(bq, F_IINLIM, input_current_limit);
+       power_supply_changed(psy);
 }
 
 static int bq25890_get_chip_state(struct bq25890_device *bq,
@@ -1106,6 +1107,8 @@ static void bq25890_pump_express_work(struct work_struct *data)
        dev_info(bq->dev, "Hi-voltage charging requested, input voltage is %d mV\n",
                 voltage);
 
+       power_supply_changed(bq->charger);
+
        return;
 error_print:
        bq25890_field_write(bq, F_PUMPX_EN, 0);
index 5ff6f44fd47b22e709813fbfdb3eedd7a4320aa5..4296600e8912a3988c45286f58420ffabb547345 100644 (file)
@@ -1083,10 +1083,8 @@ static int poll_interval_param_set(const char *val, const struct kernel_param *k
                return ret;
 
        mutex_lock(&bq27xxx_list_lock);
-       list_for_each_entry(di, &bq27xxx_battery_devices, list) {
-               cancel_delayed_work_sync(&di->work);
-               schedule_delayed_work(&di->work, 0);
-       }
+       list_for_each_entry(di, &bq27xxx_battery_devices, list)
+               mod_delayed_work(system_wq, &di->work, 0);
        mutex_unlock(&bq27xxx_list_lock);
 
        return ret;
@@ -1761,60 +1759,6 @@ static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di)
        return POWER_SUPPLY_HEALTH_GOOD;
 }
 
-void bq27xxx_battery_update(struct bq27xxx_device_info *di)
-{
-       struct bq27xxx_reg_cache cache = {0, };
-       bool has_singe_flag = di->opts & BQ27XXX_O_ZERO;
-
-       cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag);
-       if ((cache.flags & 0xff) == 0xff)
-               cache.flags = -1; /* read error */
-       if (cache.flags >= 0) {
-               cache.temperature = bq27xxx_battery_read_temperature(di);
-               if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR)
-                       cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE);
-               if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR)
-                       cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
-               if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR)
-                       cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);
-
-               cache.charge_full = bq27xxx_battery_read_fcc(di);
-               cache.capacity = bq27xxx_battery_read_soc(di);
-               if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
-                       cache.energy = bq27xxx_battery_read_energy(di);
-               di->cache.flags = cache.flags;
-               cache.health = bq27xxx_battery_read_health(di);
-               if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
-                       cache.cycle_count = bq27xxx_battery_read_cyct(di);
-
-               /* We only have to read charge design full once */
-               if (di->charge_design_full <= 0)
-                       di->charge_design_full = bq27xxx_battery_read_dcap(di);
-       }
-
-       if ((di->cache.capacity != cache.capacity) ||
-           (di->cache.flags != cache.flags))
-               power_supply_changed(di->bat);
-
-       if (memcmp(&di->cache, &cache, sizeof(cache)) != 0)
-               di->cache = cache;
-
-       di->last_update = jiffies;
-}
-EXPORT_SYMBOL_GPL(bq27xxx_battery_update);
-
-static void bq27xxx_battery_poll(struct work_struct *work)
-{
-       struct bq27xxx_device_info *di =
-                       container_of(work, struct bq27xxx_device_info,
-                                    work.work);
-
-       bq27xxx_battery_update(di);
-
-       if (poll_interval > 0)
-               schedule_delayed_work(&di->work, poll_interval * HZ);
-}
-
 static bool bq27xxx_battery_is_full(struct bq27xxx_device_info *di, int flags)
 {
        if (di->opts & BQ27XXX_O_ZERO)
@@ -1833,7 +1777,8 @@ static bool bq27xxx_battery_is_full(struct bq27xxx_device_info *di, int flags)
 static int bq27xxx_battery_current_and_status(
        struct bq27xxx_device_info *di,
        union power_supply_propval *val_curr,
-       union power_supply_propval *val_status)
+       union power_supply_propval *val_status,
+       struct bq27xxx_reg_cache *cache)
 {
        bool single_flags = (di->opts & BQ27XXX_O_ZERO);
        int curr;
@@ -1845,10 +1790,14 @@ static int bq27xxx_battery_current_and_status(
                return curr;
        }
 
-       flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, single_flags);
-       if (flags < 0) {
-               dev_err(di->dev, "error reading flags\n");
-               return flags;
+       if (cache) {
+               flags = cache->flags;
+       } else {
+               flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, single_flags);
+               if (flags < 0) {
+                       dev_err(di->dev, "error reading flags\n");
+                       return flags;
+               }
        }
 
        if (di->opts & BQ27XXX_O_ZERO) {
@@ -1883,6 +1832,78 @@ static int bq27xxx_battery_current_and_status(
        return 0;
 }
 
+static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
+{
+       union power_supply_propval status = di->last_status;
+       struct bq27xxx_reg_cache cache = {0, };
+       bool has_singe_flag = di->opts & BQ27XXX_O_ZERO;
+
+       cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag);
+       if ((cache.flags & 0xff) == 0xff)
+               cache.flags = -1; /* read error */
+       if (cache.flags >= 0) {
+               cache.temperature = bq27xxx_battery_read_temperature(di);
+               if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR)
+                       cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE);
+               if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR)
+                       cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
+               if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR)
+                       cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);
+
+               cache.charge_full = bq27xxx_battery_read_fcc(di);
+               cache.capacity = bq27xxx_battery_read_soc(di);
+               if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
+                       cache.energy = bq27xxx_battery_read_energy(di);
+               di->cache.flags = cache.flags;
+               cache.health = bq27xxx_battery_read_health(di);
+               if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
+                       cache.cycle_count = bq27xxx_battery_read_cyct(di);
+
+               /*
+                * On gauges with signed current reporting the current must be
+                * checked to detect charging <-> discharging status changes.
+                */
+               if (!(di->opts & BQ27XXX_O_ZERO))
+                       bq27xxx_battery_current_and_status(di, NULL, &status, &cache);
+
+               /* We only have to read charge design full once */
+               if (di->charge_design_full <= 0)
+                       di->charge_design_full = bq27xxx_battery_read_dcap(di);
+       }
+
+       if ((di->cache.capacity != cache.capacity) ||
+           (di->cache.flags != cache.flags) ||
+           (di->last_status.intval != status.intval)) {
+               di->last_status.intval = status.intval;
+               power_supply_changed(di->bat);
+       }
+
+       if (memcmp(&di->cache, &cache, sizeof(cache)) != 0)
+               di->cache = cache;
+
+       di->last_update = jiffies;
+
+       if (!di->removed && poll_interval > 0)
+               mod_delayed_work(system_wq, &di->work, poll_interval * HZ);
+}
+
+void bq27xxx_battery_update(struct bq27xxx_device_info *di)
+{
+       mutex_lock(&di->lock);
+       bq27xxx_battery_update_unlocked(di);
+       mutex_unlock(&di->lock);
+}
+EXPORT_SYMBOL_GPL(bq27xxx_battery_update);
+
+static void bq27xxx_battery_poll(struct work_struct *work)
+{
+       struct bq27xxx_device_info *di =
+                       container_of(work, struct bq27xxx_device_info,
+                                    work.work);
+
+       bq27xxx_battery_update(di);
+}
+
 /*
  * Get the average power in ÂµW
  * Return < 0 if something fails.
@@ -1985,10 +2006,8 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
        struct bq27xxx_device_info *di = power_supply_get_drvdata(psy);
 
        mutex_lock(&di->lock);
-       if (time_is_before_jiffies(di->last_update + 5 * HZ)) {
-               cancel_delayed_work_sync(&di->work);
-               bq27xxx_battery_poll(&di->work.work);
-       }
+       if (time_is_before_jiffies(di->last_update + 5 * HZ))
+               bq27xxx_battery_update_unlocked(di);
        mutex_unlock(&di->lock);
 
        if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0)
@@ -1996,7 +2015,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
-               ret = bq27xxx_battery_current_and_status(di, NULL, val);
+               ret = bq27xxx_battery_current_and_status(di, NULL, val, NULL);
                break;
        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
                ret = bq27xxx_battery_voltage(di, val);
@@ -2005,7 +2024,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
                val->intval = di->cache.flags < 0 ? 0 : 1;
                break;
        case POWER_SUPPLY_PROP_CURRENT_NOW:
-               ret = bq27xxx_battery_current_and_status(di, val, NULL);
+               ret = bq27xxx_battery_current_and_status(di, val, NULL, NULL);
                break;
        case POWER_SUPPLY_PROP_CAPACITY:
                ret = bq27xxx_simple_value(di->cache.capacity, val);
@@ -2078,8 +2097,8 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)
 {
        struct bq27xxx_device_info *di = power_supply_get_drvdata(psy);
 
-       cancel_delayed_work_sync(&di->work);
-       schedule_delayed_work(&di->work, 0);
+       /* After charger plug in/out wait 0.5s for things to stabilize */
+       mod_delayed_work(system_wq, &di->work, HZ / 2);
 }
 
 int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
@@ -2127,22 +2146,18 @@ EXPORT_SYMBOL_GPL(bq27xxx_battery_setup);
 
 void bq27xxx_battery_teardown(struct bq27xxx_device_info *di)
 {
-       /*
-        * power_supply_unregister call bq27xxx_battery_get_property which
-        * call bq27xxx_battery_poll.
-        * Make sure that bq27xxx_battery_poll will not call
-        * schedule_delayed_work again after unregister (which cause OOPS).
-        */
-       poll_interval = 0;
-
-       cancel_delayed_work_sync(&di->work);
-
-       power_supply_unregister(di->bat);
-
        mutex_lock(&bq27xxx_list_lock);
        list_del(&di->list);
        mutex_unlock(&bq27xxx_list_lock);
 
+       /* Set removed to avoid bq27xxx_battery_update() re-queuing the work */
+       mutex_lock(&di->lock);
+       di->removed = true;
+       mutex_unlock(&di->lock);
+
+       cancel_delayed_work_sync(&di->work);
+
+       power_supply_unregister(di->bat);
        mutex_destroy(&di->lock);
 }
 EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown);
index f8768997333bc59412d040cee7427efad086a7f2..6d3c748763390675f759388cc1ceef3d73afee02 100644 (file)
@@ -179,7 +179,7 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client)
        i2c_set_clientdata(client, di);
 
        if (client->irq) {
-               ret = devm_request_threaded_irq(&client->dev, client->irq,
+               ret = request_threaded_irq(client->irq,
                                NULL, bq27xxx_battery_irq_handler_thread,
                                IRQF_ONESHOT,
                                di->name, di);
@@ -209,6 +209,7 @@ static void bq27xxx_battery_i2c_remove(struct i2c_client *client)
 {
        struct bq27xxx_device_info *di = i2c_get_clientdata(client);
 
+       free_irq(client->irq, di);
        bq27xxx_battery_teardown(di);
 
        mutex_lock(&battery_mutex);
index 92e48e3a485364dd154e8489398488494215874c..1305cba61edd4b957313d7d86fb05158975b3086 100644 (file)
@@ -796,7 +796,9 @@ static int mt6360_charger_probe(struct platform_device *pdev)
        mci->vinovp = 6500000;
        mutex_init(&mci->chgdet_lock);
        platform_set_drvdata(pdev, mci);
-       devm_work_autocancel(&pdev->dev, &mci->chrdet_work, mt6360_chrdet_work);
+       ret = devm_work_autocancel(&pdev->dev, &mci->chrdet_work, mt6360_chrdet_work);
+       if (ret)
+               return dev_err_probe(&pdev->dev, ret, "Failed to set delayed work\n");
 
        ret = device_property_read_u32(&pdev->dev, "richtek,vinovp-microvolt", &mci->vinovp);
        if (ret)
index ab986dbace16a309e8598d802095efab4ae4d3a9..3791aec69ddc675404ccc5974710a01ca49be9ad 100644 (file)
@@ -348,6 +348,10 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data)
        struct power_supply *psy = dev_get_drvdata(dev);
        unsigned int *count = data;
 
+       if (!psy->desc->get_property(psy, POWER_SUPPLY_PROP_SCOPE, &ret))
+               if (ret.intval == POWER_SUPPLY_SCOPE_DEVICE)
+                       return 0;
+
        (*count)++;
        if (psy->desc->type != POWER_SUPPLY_TYPE_BATTERY)
                if (!psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE,
@@ -366,8 +370,8 @@ int power_supply_is_system_supplied(void)
                                      __power_supply_is_system_supplied);
 
        /*
-        * If no power class device was found at all, most probably we are
-        * running on a desktop system, so assume we are on mains power.
+        * If no system scope power class device was found at all, most probably we
+        * are running on a desktop system, so assume we are on mains power.
         */
        if (count == 0)
                return 1;
@@ -573,7 +577,7 @@ int power_supply_get_battery_info(struct power_supply *psy,
        struct power_supply_battery_info *info;
        struct device_node *battery_np = NULL;
        struct fwnode_reference_args args;
-       struct fwnode_handle *fwnode;
+       struct fwnode_handle *fwnode = NULL;
        const char *value;
        int err, len, index;
        const __be32 *list;
@@ -585,7 +589,7 @@ int power_supply_get_battery_info(struct power_supply *psy,
                        return -ENODEV;
 
                fwnode = fwnode_handle_get(of_fwnode_handle(battery_np));
-       } else {
+       } else if (psy->dev.parent) {
                err = fwnode_property_get_reference_args(
                                        dev_fwnode(psy->dev.parent),
                                        "monitored-battery", NULL, 0, 0, &args);
@@ -595,6 +599,9 @@ int power_supply_get_battery_info(struct power_supply *psy,
                fwnode = args.fwnode;
        }
 
+       if (!fwnode)
+               return -ENOENT;
+
        err = fwnode_property_read_string(fwnode, "compatible", &value);
        if (err)
                goto out_put_node;
index 702bf83f6e6d256e7012c9657b750ee3f51d2ca4..0674483279d77c2b7bd1e8e687839332074d1ca8 100644 (file)
@@ -35,8 +35,9 @@ static void power_supply_update_bat_leds(struct power_supply *psy)
                led_trigger_event(psy->charging_full_trig, LED_FULL);
                led_trigger_event(psy->charging_trig, LED_OFF);
                led_trigger_event(psy->full_trig, LED_FULL);
-               led_trigger_event(psy->charging_blink_full_solid_trig,
-                       LED_FULL);
+               /* Going from blink to LED on requires a LED_OFF event to stop blink */
+               led_trigger_event(psy->charging_blink_full_solid_trig, LED_OFF);
+               led_trigger_event(psy->charging_blink_full_solid_trig, LED_FULL);
                break;
        case POWER_SUPPLY_STATUS_CHARGING:
                led_trigger_event(psy->charging_full_trig, LED_FULL);
index ba3b125cd66e432631d6170b048bc089870aedd7..06e5b6b0e255ce8bf159c2f5f0e012916fe12551 100644 (file)
@@ -286,7 +286,8 @@ static ssize_t power_supply_show_property(struct device *dev,
 
                if (ret < 0) {
                        if (ret == -ENODATA)
-                               dev_dbg(dev, "driver has no data for `%s' property\n",
+                               dev_dbg_ratelimited(dev,
+                                       "driver has no data for `%s' property\n",
                                        attr->attr.name);
                        else if (ret != -ENODEV && ret != -EAGAIN)
                                dev_err_ratelimited(dev,
index 73f744a3155d4ce55011d26310173b6eb69803cb..ea33693b69779ac0928d112ec8ec5d45dc5a90e3 100644 (file)
@@ -1023,7 +1023,7 @@ static int rt9467_request_interrupt(struct rt9467_chg_data *data)
        for (i = 0; i < num_chg_irqs; i++) {
                virq = regmap_irq_get_virq(data->irq_chip_data, chg_irqs[i].hwirq);
                if (virq <= 0)
-                       return dev_err_probe(dev, virq, "Failed to get (%s) irq\n",
+                       return dev_err_probe(dev, -EINVAL, "Failed to get (%s) irq\n",
                                             chg_irqs[i].name);
 
                ret = devm_request_threaded_irq(dev, virq, NULL, chg_irqs[i].handler,
index 75ebcbf0a7883750b009ef21a6bd10692f138b1a..a14e89ac0369cae0a0990775eb41fec84d537c4b 100644 (file)
@@ -24,7 +24,7 @@
 #define SBS_CHARGER_REG_STATUS                 0x13
 #define SBS_CHARGER_REG_ALARM_WARNING          0x16
 
-#define SBS_CHARGER_STATUS_CHARGE_INHIBITED    BIT(1)
+#define SBS_CHARGER_STATUS_CHARGE_INHIBITED    BIT(0)
 #define SBS_CHARGER_STATUS_RES_COLD            BIT(9)
 #define SBS_CHARGER_STATUS_RES_HOT             BIT(10)
 #define SBS_CHARGER_STATUS_BATTERY_PRESENT     BIT(14)
index 632977f84b954e6355e87a1edcac7b24020f16c1..bd23c4d9fed43482e972ccc086311e7bfcec2d54 100644 (file)
@@ -733,13 +733,6 @@ static int sc27xx_fgu_set_property(struct power_supply *psy,
        return ret;
 }
 
-static void sc27xx_fgu_external_power_changed(struct power_supply *psy)
-{
-       struct sc27xx_fgu_data *data = power_supply_get_drvdata(psy);
-
-       power_supply_changed(data->battery);
-}
-
 static int sc27xx_fgu_property_is_writeable(struct power_supply *psy,
                                            enum power_supply_property psp)
 {
@@ -774,7 +767,7 @@ static const struct power_supply_desc sc27xx_fgu_desc = {
        .num_properties         = ARRAY_SIZE(sc27xx_fgu_props),
        .get_property           = sc27xx_fgu_get_property,
        .set_property           = sc27xx_fgu_set_property,
-       .external_power_changed = sc27xx_fgu_external_power_changed,
+       .external_power_changed = power_supply_changed,
        .property_is_writeable  = sc27xx_fgu_property_is_writeable,
        .no_thermal             = true,
 };
index dc741ac156c32c084c7f469e44feccf297863ece..698ab7f5004bf6b74e2e57ac224f6138139f4666 100644 (file)
@@ -5256,7 +5256,7 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
        }
 
        rdev->debugfs = debugfs_create_dir(rname, debugfs_root);
-       if (!rdev->debugfs) {
+       if (IS_ERR(rdev->debugfs)) {
                rdev_warn(rdev, "Failed to create debugfs directory\n");
                return;
        }
@@ -6178,7 +6178,7 @@ static int __init regulator_init(void)
        ret = class_register(&regulator_class);
 
        debugfs_root = debugfs_create_dir("regulator", NULL);
-       if (!debugfs_root)
+       if (IS_ERR(debugfs_root))
                pr_warn("regulator: Failed to create debugfs directory\n");
 
 #ifdef CONFIG_DEBUG_FS
index 1849566784ab5e60b75cba257b965baa3bc388e7..3eb86ec21d08800bac3838f443f6615e75cb1562 100644 (file)
@@ -951,9 +951,12 @@ static int mt6359_regulator_probe(struct platform_device *pdev)
        struct regulator_config config = {};
        struct regulator_dev *rdev;
        struct mt6359_regulator_info *mt6359_info;
-       int i, hw_ver;
+       int i, hw_ver, ret;
+
+       ret = regmap_read(mt6397->regmap, MT6359P_HWCID, &hw_ver);
+       if (ret)
+               return ret;
 
-       regmap_read(mt6397->regmap, MT6359P_HWCID, &hw_ver);
        if (hw_ver >= MT6359P_CHIP_VER)
                mt6359_info = mt6359p_regulators;
        else
index 87a746dcb5169759f5413dfd8fe150933e267c3e..e75dd92f86ca728435247b1523a1a3283e0e0efc 100644 (file)
@@ -264,7 +264,7 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
                        .vsel_reg = PCA9450_REG_BUCK2OUT_DVS0,
                        .vsel_mask = BUCK2OUT_DVS0_MASK,
                        .enable_reg = PCA9450_REG_BUCK2CTRL,
-                       .enable_mask = BUCK1_ENMODE_MASK,
+                       .enable_mask = BUCK2_ENMODE_MASK,
                        .ramp_reg = PCA9450_REG_BUCK2CTRL,
                        .ramp_mask = BUCK2_RAMP_MASK,
                        .ramp_delay_table = pca9450_dvs_buck_ramp_table,
@@ -502,7 +502,7 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
                        .vsel_reg = PCA9450_REG_BUCK2OUT_DVS0,
                        .vsel_mask = BUCK2OUT_DVS0_MASK,
                        .enable_reg = PCA9450_REG_BUCK2CTRL,
-                       .enable_mask = BUCK1_ENMODE_MASK,
+                       .enable_mask = BUCK2_ENMODE_MASK,
                        .ramp_reg = PCA9450_REG_BUCK2CTRL,
                        .ramp_mask = BUCK2_RAMP_MASK,
                        .ramp_delay_table = pca9450_dvs_buck_ramp_table,
index ade1369fe5ed3056706b3f8361af2efe8dc6e327..113c509bf6d052bf70b3642adcf4bb6ad41ffeea 100644 (file)
@@ -127,6 +127,8 @@ static int prepare_itcw(struct itcw *, unsigned int, unsigned int, int,
                        struct dasd_device *, struct dasd_device *,
                        unsigned int, int, unsigned int, unsigned int,
                        unsigned int, unsigned int);
+static int dasd_eckd_query_pprc_status(struct dasd_device *,
+                                      struct dasd_pprc_data_sc4 *);
 
 /* initial attempt at a probe function. this can be simplified once
  * the other detection code is gone */
@@ -3733,6 +3735,26 @@ static int count_exts(unsigned int from, unsigned int to, int trks_per_ext)
        return count;
 }
 
+static int dasd_in_copy_relation(struct dasd_device *device)
+{
+       struct dasd_pprc_data_sc4 *temp;
+       int rc;
+
+       if (!dasd_eckd_pprc_enabled(device))
+               return 0;
+
+       temp = kzalloc(sizeof(*temp), GFP_KERNEL);
+       if (!temp)
+               return -ENOMEM;
+
+       rc = dasd_eckd_query_pprc_status(device, temp);
+       if (!rc)
+               rc = temp->dev_info[0].state;
+
+       kfree(temp);
+       return rc;
+}
+
 /*
  * Release allocated space for a given range or an entire volume.
  */
@@ -3749,6 +3771,7 @@ dasd_eckd_dso_ras(struct dasd_device *device, struct dasd_block *block,
        int cur_to_trk, cur_from_trk;
        struct dasd_ccw_req *cqr;
        u32 beg_cyl, end_cyl;
+       int copy_relation;
        struct ccw1 *ccw;
        int trks_per_ext;
        size_t ras_size;
@@ -3760,6 +3783,10 @@ dasd_eckd_dso_ras(struct dasd_device *device, struct dasd_block *block,
        if (dasd_eckd_ras_sanity_checks(device, first_trk, last_trk))
                return ERR_PTR(-EINVAL);
 
+       copy_relation = dasd_in_copy_relation(device);
+       if (copy_relation < 0)
+               return ERR_PTR(copy_relation);
+
        rq = req ? blk_mq_rq_to_pdu(req) : NULL;
 
        features = &private->features;
@@ -3788,9 +3815,11 @@ dasd_eckd_dso_ras(struct dasd_device *device, struct dasd_block *block,
        /*
         * This bit guarantees initialisation of tracks within an extent that is
         * not fully specified, but is only supported with a certain feature
-        * subset.
+        * subset and for devices not in a copy relation.
         */
-       ras_data->op_flags.guarantee_init = !!(features->feature[56] & 0x01);
+       if (features->feature[56] & 0x01 && !copy_relation)
+               ras_data->op_flags.guarantee_init = 1;
+
        ras_data->lss = private->conf.ned->ID;
        ras_data->dev_addr = private->conf.ned->unit_addr;
        ras_data->nr_exts = nr_exts;
index 8eb089b99cde92bad4670656b281b4cfcc8425b6..d5c43e9b5128948b0d1a2e1d7bbf8a6a225c5747 100644 (file)
@@ -1111,6 +1111,8 @@ static void io_subchannel_verify(struct subchannel *sch)
        cdev = sch_get_cdev(sch);
        if (cdev)
                dev_fsm_event(cdev, DEV_EVENT_VERIFY);
+       else
+               css_schedule_eval(sch->schid);
 }
 
 static void io_subchannel_terminate_path(struct subchannel *sch, u8 mask)
index 5ea6249d81803ad2358592f2e4c40cb167692828..641f0dbb65a90b15577b27a941a8b65718b09159 100644 (file)
@@ -95,7 +95,7 @@ static inline int do_sqbs(u64 token, unsigned char state, int queue,
                "       lgr     1,%[token]\n"
                "       .insn   rsy,0xeb000000008a,%[qs],%[ccq],0(%[state])"
                : [ccq] "+&d" (_ccq), [qs] "+&d" (_queuestart)
-               : [state] "d" ((unsigned long)state), [token] "d" (token)
+               : [state] "a" ((unsigned long)state), [token] "d" (token)
                : "memory", "cc", "1");
        *count = _ccq & 0xff;
        *start = _queuestart & 0xff;
index 5a05d1cdfec20adf5bc43a6fad6fa2f219fc9805..a8def50c149bd433b1324cbd6d3798ea4130bc7e 100644 (file)
@@ -1293,6 +1293,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
                        return PTR_ERR(kkey);
                rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey);
                DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc);
+               memzero_explicit(kkey, ktp.keylen);
                kfree(kkey);
                if (rc)
                        break;
@@ -1426,6 +1427,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
                                        kkey, ktp.keylen, &ktp.protkey);
                DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc);
                kfree(apqns);
+               memzero_explicit(kkey, ktp.keylen);
                kfree(kkey);
                if (rc)
                        break;
@@ -1552,6 +1554,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
                                        protkey, &protkeylen);
                DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc);
                kfree(apqns);
+               memzero_explicit(kkey, ktp.keylen);
                kfree(kkey);
                if (rc) {
                        kfree(protkey);
index df5e5b7fdcfe73accb080e412f43372c44974cbe..84aa3571be6d4de1f8e7cf7e2e0a011a6c4b6fd1 100644 (file)
@@ -3796,6 +3796,7 @@ struct qla_qpair {
        uint64_t retry_term_jiff;
        struct qla_tgt_counters tgt_counters;
        uint16_t cpuid;
+       bool cpu_mapped;
        struct qla_fw_resources fwres ____cacheline_aligned;
        struct  qla_buf_pool buf_pool;
        u32     cmd_cnt;
index ec0423ec66817c1a54ea00d508aeaccc02def258..1a955c3ff3d6ce2732e3fd03e65203a5162dbc9a 100644 (file)
@@ -9426,6 +9426,9 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos,
                qpair->rsp->req = qpair->req;
                qpair->rsp->qpair = qpair;
 
+               if (!qpair->cpu_mapped)
+                       qla_cpu_update(qpair, raw_smp_processor_id());
+
                if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) {
                        if (ha->fw_attributes & BIT_4)
                                qpair->difdix_supported = 1;
index cce6e425c1214a9aabaf9fe2677ba1ef0419cdb9..7b42558a8839ad51e0b92ede49c89656a16b03f7 100644 (file)
@@ -539,11 +539,14 @@ qla_mapq_init_qp_cpu_map(struct qla_hw_data *ha,
        if (!ha->qp_cpu_map)
                return;
        mask = pci_irq_get_affinity(ha->pdev, msix->vector_base0);
+       if (!mask)
+               return;
        qpair->cpuid = cpumask_first(mask);
        for_each_cpu(cpu, mask) {
                ha->qp_cpu_map[cpu] = qpair;
        }
        msix->cpuid = qpair->cpuid;
+       qpair->cpu_mapped = true;
 }
 
 static inline void
index 71feda2cdb63046a713c5018ae64948abed1084f..245e3a5d81fd33b3040df3000712d5d961ec9d6e 100644 (file)
@@ -3770,6 +3770,9 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 
        if (rsp->qpair->cpuid != smp_processor_id() || !rsp->qpair->rcv_intr) {
                rsp->qpair->rcv_intr = 1;
+
+               if (!rsp->qpair->cpu_mapped)
+                       qla_cpu_update(rsp->qpair, raw_smp_processor_id());
        }
 
 #define __update_rsp_in(_is_shadow_hba, _rsp, _rsp_in)                 \
index b7c569a42aa477551597ff0629fc6c04888277fb..0226c9279cef60b0daf3cebfba77c467200975c9 100644 (file)
@@ -1463,6 +1463,8 @@ static int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
        struct Scsi_Host *host = cmd->device->host;
        int rtn = 0;
 
+       atomic_inc(&cmd->device->iorequest_cnt);
+
        /* check if the device is still usable */
        if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
                /* in SDEV_DEL we error all commands. DID_NO_CONNECT
@@ -1483,6 +1485,7 @@ static int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
                 */
                SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd,
                        "queuecommand : device blocked\n"));
+               atomic_dec(&cmd->device->iorequest_cnt);
                return SCSI_MLQUEUE_DEVICE_BUSY;
        }
 
@@ -1515,6 +1518,7 @@ static int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
        trace_scsi_dispatch_cmd_start(cmd);
        rtn = host->hostt->queuecommand(host, cmd);
        if (rtn) {
+               atomic_dec(&cmd->device->iorequest_cnt);
                trace_scsi_dispatch_cmd_error(cmd, rtn);
                if (rtn != SCSI_MLQUEUE_DEVICE_BUSY &&
                    rtn != SCSI_MLQUEUE_TARGET_BUSY)
@@ -1761,7 +1765,6 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
                goto out_dec_host_busy;
        }
 
-       atomic_inc(&cmd->device->iorequest_cnt);
        return BLK_STS_OK;
 
 out_dec_host_busy:
index 5b230e149c3dfe346588121e03ed81efd64cde95..8ffb75be99bc8fab964fc6df5663f9392c844258 100644 (file)
@@ -109,7 +109,9 @@ enum {
        TASK_ATTRIBUTE_HEADOFQUEUE              = 0x1,
        TASK_ATTRIBUTE_ORDERED                  = 0x2,
        TASK_ATTRIBUTE_ACA                      = 0x4,
+};
 
+enum {
        SS_STS_NORMAL                           = 0x80000000,
        SS_STS_DONE                             = 0x40000000,
        SS_STS_HANDSHAKE                        = 0x20000000,
@@ -121,7 +123,9 @@ enum {
        SS_I2H_REQUEST_RESET                    = 0x2000,
 
        SS_MU_OPERATIONAL                       = 0x80000000,
+};
 
+enum {
        STEX_CDB_LENGTH                         = 16,
        STATUS_VAR_LEN                          = 128,
 
index d9ce379c4d2e836476a04a724622d80a0a85a36a..e6bc622954cfab8118cb9d9cef891bdd3c54dc23 100644 (file)
@@ -1780,7 +1780,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
 
        length = scsi_bufflen(scmnd);
        payload = (struct vmbus_packet_mpb_array *)&cmd_request->mpb;
-       payload_sz = sizeof(cmd_request->mpb);
+       payload_sz = 0;
 
        if (scsi_sg_count(scmnd)) {
                unsigned long offset_in_hvpg = offset_in_hvpage(sgl->offset);
@@ -1789,10 +1789,10 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
                unsigned long hvpfn, hvpfns_to_add;
                int j, i = 0, sg_count;
 
-               if (hvpg_count > MAX_PAGE_BUFFER_COUNT) {
+               payload_sz = (hvpg_count * sizeof(u64) +
+                             sizeof(struct vmbus_packet_mpb_array));
 
-                       payload_sz = (hvpg_count * sizeof(u64) +
-                                     sizeof(struct vmbus_packet_mpb_array));
+               if (hvpg_count > MAX_PAGE_BUFFER_COUNT) {
                        payload = kzalloc(payload_sz, GFP_ATOMIC);
                        if (!payload)
                                return SCSI_MLQUEUE_DEVICE_BUSY;
index 7268c2fbcbc1d80b7b72b45ae4668584016f92c8..e0d096607fefbaf4f9ee93921046ec675a9af05f 100644 (file)
@@ -36,7 +36,7 @@ config UCC
 config CPM_TSA
        tristate "CPM TSA support"
        depends on OF && HAS_IOMEM
-       depends on CPM1 || COMPILE_TEST
+       depends on CPM1 || (CPM && COMPILE_TEST)
        help
          Freescale CPM Time Slot Assigner (TSA)
          controller.
@@ -47,7 +47,7 @@ config CPM_TSA
 config CPM_QMC
        tristate "CPM QMC support"
        depends on OF && HAS_IOMEM
-       depends on CPM1 || (FSL_SOC && COMPILE_TEST)
+       depends on CPM1 || (FSL_SOC && CPM && COMPILE_TEST)
        depends on CPM_TSA
        help
          Freescale CPM QUICC Multichannel Controller
index ac85d5562212705a9fd8c0bb5f13c73f024fbf67..26e6633693196ef20ae95b93114627a9d97a2e7b 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
@@ -301,49 +302,43 @@ static int cdns_spi_setup_transfer(struct spi_device *spi,
 }
 
 /**
- * cdns_spi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible
+ * cdns_spi_process_fifo - Fills the TX FIFO, and drain the RX FIFO
  * @xspi:      Pointer to the cdns_spi structure
+ * @ntx:       Number of bytes to pack into the TX FIFO
+ * @nrx:       Number of bytes to drain from the RX FIFO
  */
-static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi)
+static void cdns_spi_process_fifo(struct cdns_spi *xspi, int ntx, int nrx)
 {
-       unsigned long trans_cnt = 0;
+       ntx = clamp(ntx, 0, xspi->tx_bytes);
+       nrx = clamp(nrx, 0, xspi->rx_bytes);
 
-       while ((trans_cnt < xspi->tx_fifo_depth) &&
-              (xspi->tx_bytes > 0)) {
+       xspi->tx_bytes -= ntx;
+       xspi->rx_bytes -= nrx;
 
+       while (ntx || nrx) {
                /* When xspi in busy condition, bytes may send failed,
                 * then spi control did't work thoroughly, add one byte delay
                 */
-               if (cdns_spi_read(xspi, CDNS_SPI_ISR) &
-                   CDNS_SPI_IXR_TXFULL)
+               if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL)
                        udelay(10);
 
-               if (xspi->txbuf)
-                       cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++);
-               else
-                       cdns_spi_write(xspi, CDNS_SPI_TXD, 0);
+               if (ntx) {
+                       if (xspi->txbuf)
+                               cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++);
+                       else
+                               cdns_spi_write(xspi, CDNS_SPI_TXD, 0);
 
-               xspi->tx_bytes--;
-               trans_cnt++;
-       }
-}
+                       ntx--;
+               }
 
-/**
- * cdns_spi_read_rx_fifo - Reads the RX FIFO with as many bytes as possible
- * @xspi:       Pointer to the cdns_spi structure
- * @count:     Read byte count
- */
-static void cdns_spi_read_rx_fifo(struct cdns_spi *xspi, unsigned long count)
-{
-       u8 data;
-
-       /* Read out the data from the RX FIFO */
-       while (count > 0) {
-               data = cdns_spi_read(xspi, CDNS_SPI_RXD);
-               if (xspi->rxbuf)
-                       *xspi->rxbuf++ = data;
-               xspi->rx_bytes--;
-               count--;
+               if (nrx) {
+                       u8 data = cdns_spi_read(xspi, CDNS_SPI_RXD);
+
+                       if (xspi->rxbuf)
+                               *xspi->rxbuf++ = data;
+
+                       nrx--;
+               }
        }
 }
 
@@ -381,33 +376,22 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id)
                spi_finalize_current_transfer(ctlr);
                status = IRQ_HANDLED;
        } else if (intr_status & CDNS_SPI_IXR_TXOW) {
-               int trans_cnt = cdns_spi_read(xspi, CDNS_SPI_THLD);
+               int threshold = cdns_spi_read(xspi, CDNS_SPI_THLD);
+               int trans_cnt = xspi->rx_bytes - xspi->tx_bytes;
+
+               if (threshold > 1)
+                       trans_cnt -= threshold;
+
                /* Set threshold to one if number of pending are
                 * less than half fifo
                 */
                if (xspi->tx_bytes < xspi->tx_fifo_depth >> 1)
                        cdns_spi_write(xspi, CDNS_SPI_THLD, 1);
 
-               while (trans_cnt) {
-                       cdns_spi_read_rx_fifo(xspi, 1);
-
-                       if (xspi->tx_bytes) {
-                               if (xspi->txbuf)
-                                       cdns_spi_write(xspi, CDNS_SPI_TXD,
-                                                      *xspi->txbuf++);
-                               else
-                                       cdns_spi_write(xspi, CDNS_SPI_TXD, 0);
-                               xspi->tx_bytes--;
-                       }
-                       trans_cnt--;
-               }
-               if (!xspi->tx_bytes) {
-                       /* Fixed delay due to controller limitation with
-                        * RX_NEMPTY incorrect status
-                        * Xilinx AR:65885 contains more details
-                        */
-                       udelay(10);
-                       cdns_spi_read_rx_fifo(xspi, xspi->rx_bytes);
+               if (xspi->tx_bytes) {
+                       cdns_spi_process_fifo(xspi, trans_cnt, trans_cnt);
+               } else {
+                       cdns_spi_process_fifo(xspi, 0, trans_cnt);
                        cdns_spi_write(xspi, CDNS_SPI_IDR,
                                       CDNS_SPI_IXR_DEFAULT);
                        spi_finalize_current_transfer(ctlr);
@@ -450,16 +434,17 @@ static int cdns_transfer_one(struct spi_controller *ctlr,
        xspi->tx_bytes = transfer->len;
        xspi->rx_bytes = transfer->len;
 
-       if (!spi_controller_is_slave(ctlr))
+       if (!spi_controller_is_slave(ctlr)) {
                cdns_spi_setup_transfer(spi, transfer);
+       } else {
+               /* Set TX empty threshold to half of FIFO depth
+                * only if TX bytes are more than half FIFO depth.
+                */
+               if (xspi->tx_bytes > xspi->tx_fifo_depth)
+                       cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1);
+       }
 
-       /* Set TX empty threshold to half of FIFO depth
-        * only if TX bytes are more than half FIFO depth.
-        */
-       if (xspi->tx_bytes > (xspi->tx_fifo_depth >> 1))
-               cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1);
-
-       cdns_spi_fill_tx_fifo(xspi);
+       cdns_spi_process_fifo(xspi, xspi->tx_fifo_depth, 0);
        spi_transfer_delay_exec(transfer);
 
        cdns_spi_write(xspi, CDNS_SPI_IER, CDNS_SPI_IXR_DEFAULT);
index 5e6faa98aa8523d0229454afebcdb6beb50af109..5f2aee69c1c131730849cd9ebcf3f8c0facffa4c 100644 (file)
@@ -264,17 +264,17 @@ static void dw_spi_elba_set_cs(struct spi_device *spi, bool enable)
        struct regmap *syscon = dwsmmio->priv;
        u8 cs;
 
-       cs = spi->chip_select;
+       cs = spi_get_chipselect(spi, 0);
        if (cs < 2)
-               dw_spi_elba_override_cs(syscon, spi->chip_select, enable);
+               dw_spi_elba_override_cs(syscon, spi_get_chipselect(spi, 0), enable);
 
        /*
         * The DW SPI controller needs a native CS bit selected to start
         * the serial engine.
         */
-       spi->chip_select = 0;
+       spi_set_chipselect(spi, 0, 0);
        dw_spi_set_cs(spi, enable);
-       spi->chip_select = cs;
+       spi_get_chipselect(spi, cs);
 }
 
 static int dw_spi_elba_init(struct platform_device *pdev,
index ba7be505ec4ef5594ea9e9d4ee6e24c247f10140..a98b781b103ab31b93aed20fc3bf6b167a3c55cb 100644 (file)
@@ -294,6 +294,8 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag)
        mas->cs_flag = set_flag;
        /* set xfer_mode to FIFO to complete cs_done in isr */
        mas->cur_xfer_mode = GENI_SE_FIFO;
+       geni_se_select_mode(se, mas->cur_xfer_mode);
+
        reinit_completion(&mas->cs_done);
        if (set_flag)
                geni_se_setup_m_cmd(se, SPI_CS_ASSERT, 0);
index 7e3d1a6f30ba96dc25591e4b889fba01b7b96740..6c1f91c859ca613b00d7f577a2242cff969d536b 100644 (file)
@@ -138,7 +138,7 @@ static struct i2c_driver adt7316_driver = {
                .of_match_table = adt7316_of_match,
                .pm = ADT7316_PM_OPS,
        },
-       .probe_new = adt7316_i2c_probe,
+       .probe = adt7316_i2c_probe,
        .id_table = adt7316_i2c_id,
 };
 module_i2c_driver(adt7316_driver);
index b3152f7153fbb1cf2199c32b2e384c18d2d87c36..46db6d91542a40a6ee9fcd683b911fac201deb31 100644 (file)
@@ -781,7 +781,7 @@ static struct i2c_driver ad5933_driver = {
                .name = "ad5933",
                .of_match_table = ad5933_of_match,
        },
-       .probe_new = ad5933_probe,
+       .probe = ad5933_probe,
        .id_table = ad5933_id,
 };
 module_i2c_driver(ad5933_driver);
index 63de214916f59ad7ceb27a2ac7761ae4aa6862a6..c079368019e87f5d7d5695ad9c2cff47e922042a 100644 (file)
@@ -373,7 +373,7 @@ static int ov2680_get_fmt(struct v4l2_subdev *sd,
 static int ov2680_detect(struct i2c_client *client)
 {
        struct i2c_adapter *adapter = client->adapter;
-       u32 high, low;
+       u32 high = 0, low = 0;
        int ret;
        u16 id;
        u8 revision;
@@ -383,7 +383,7 @@ static int ov2680_detect(struct i2c_client *client)
 
        ret = ov_read_reg8(client, OV2680_SC_CMMN_CHIP_ID_H, &high);
        if (ret) {
-               dev_err(&client->dev, "sensor_id_high = 0x%x\n", high);
+               dev_err(&client->dev, "sensor_id_high read failed (%d)\n", ret);
                return -ENODEV;
        }
        ret = ov_read_reg8(client, OV2680_SC_CMMN_CHIP_ID_L, &low);
index 32700cb8bc4d551055b8d6f36618acbe07088042..ca2efcc21efe3063df15e811d2cb9a317bd3b8c1 100644 (file)
@@ -354,7 +354,7 @@ static int imx8mq_mipi_csi_start_stream(struct csi_state *state,
                                        struct v4l2_subdev_state *sd_state)
 {
        int ret;
-       u32 hs_settle;
+       u32 hs_settle = 0;
 
        ret = imx8mq_mipi_csi_sw_reset(state);
        if (ret)
index 834cce50f9b00ae5588abaf1c2c657203176ee39..b516c2893420bc142412061aa5db056d6732b685 100644 (file)
@@ -364,8 +364,6 @@ struct iscsi_np *iscsit_add_np(
        init_completion(&np->np_restart_comp);
        INIT_LIST_HEAD(&np->np_list);
 
-       timer_setup(&np->np_login_timer, iscsi_handle_login_thread_timeout, 0);
-
        ret = iscsi_target_setup_login_socket(np, sockaddr);
        if (ret != 0) {
                kfree(np);
index 274bdd7845ca936a038dc5e602dc34e3750cbcbd..90b870f234f03cd9033418387482a34bf9d4ede1 100644 (file)
@@ -811,59 +811,6 @@ void iscsi_post_login_handler(
        iscsit_dec_conn_usage_count(conn);
 }
 
-void iscsi_handle_login_thread_timeout(struct timer_list *t)
-{
-       struct iscsi_np *np = from_timer(np, t, np_login_timer);
-
-       spin_lock_bh(&np->np_thread_lock);
-       pr_err("iSCSI Login timeout on Network Portal %pISpc\n",
-                       &np->np_sockaddr);
-
-       if (np->np_login_timer_flags & ISCSI_TF_STOP) {
-               spin_unlock_bh(&np->np_thread_lock);
-               return;
-       }
-
-       if (np->np_thread)
-               send_sig(SIGINT, np->np_thread, 1);
-
-       np->np_login_timer_flags &= ~ISCSI_TF_RUNNING;
-       spin_unlock_bh(&np->np_thread_lock);
-}
-
-static void iscsi_start_login_thread_timer(struct iscsi_np *np)
-{
-       /*
-        * This used the TA_LOGIN_TIMEOUT constant because at this
-        * point we do not have access to ISCSI_TPG_ATTRIB(tpg)->login_timeout
-        */
-       spin_lock_bh(&np->np_thread_lock);
-       np->np_login_timer_flags &= ~ISCSI_TF_STOP;
-       np->np_login_timer_flags |= ISCSI_TF_RUNNING;
-       mod_timer(&np->np_login_timer, jiffies + TA_LOGIN_TIMEOUT * HZ);
-
-       pr_debug("Added timeout timer to iSCSI login request for"
-                       " %u seconds.\n", TA_LOGIN_TIMEOUT);
-       spin_unlock_bh(&np->np_thread_lock);
-}
-
-static void iscsi_stop_login_thread_timer(struct iscsi_np *np)
-{
-       spin_lock_bh(&np->np_thread_lock);
-       if (!(np->np_login_timer_flags & ISCSI_TF_RUNNING)) {
-               spin_unlock_bh(&np->np_thread_lock);
-               return;
-       }
-       np->np_login_timer_flags |= ISCSI_TF_STOP;
-       spin_unlock_bh(&np->np_thread_lock);
-
-       del_timer_sync(&np->np_login_timer);
-
-       spin_lock_bh(&np->np_thread_lock);
-       np->np_login_timer_flags &= ~ISCSI_TF_RUNNING;
-       spin_unlock_bh(&np->np_thread_lock);
-}
-
 int iscsit_setup_np(
        struct iscsi_np *np,
        struct sockaddr_storage *sockaddr)
@@ -1123,10 +1070,13 @@ static struct iscsit_conn *iscsit_alloc_conn(struct iscsi_np *np)
        spin_lock_init(&conn->nopin_timer_lock);
        spin_lock_init(&conn->response_queue_lock);
        spin_lock_init(&conn->state_lock);
+       spin_lock_init(&conn->login_worker_lock);
+       spin_lock_init(&conn->login_timer_lock);
 
        timer_setup(&conn->nopin_response_timer,
                    iscsit_handle_nopin_response_timeout, 0);
        timer_setup(&conn->nopin_timer, iscsit_handle_nopin_timeout, 0);
+       timer_setup(&conn->login_timer, iscsit_login_timeout, 0);
 
        if (iscsit_conn_set_transport(conn, np->np_transport) < 0)
                goto free_conn;
@@ -1304,7 +1254,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
                goto new_sess_out;
        }
 
-       iscsi_start_login_thread_timer(np);
+       iscsit_start_login_timer(conn, current);
 
        pr_debug("Moving to TARG_CONN_STATE_XPT_UP.\n");
        conn->conn_state = TARG_CONN_STATE_XPT_UP;
@@ -1417,8 +1367,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
        if (ret < 0)
                goto new_sess_out;
 
-       iscsi_stop_login_thread_timer(np);
-
        if (ret == 1) {
                tpg_np = conn->tpg_np;
 
@@ -1434,7 +1382,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
 new_sess_out:
        new_sess = true;
 old_sess_out:
-       iscsi_stop_login_thread_timer(np);
+       iscsit_stop_login_timer(conn);
        tpg_np = conn->tpg_np;
        iscsi_target_login_sess_out(conn, zero_tsih, new_sess);
        new_sess = false;
@@ -1448,7 +1396,6 @@ old_sess_out:
        return 1;
 
 exit:
-       iscsi_stop_login_thread_timer(np);
        spin_lock_bh(&np->np_thread_lock);
        np->np_thread_state = ISCSI_NP_THREAD_EXIT;
        spin_unlock_bh(&np->np_thread_lock);
index 24040c118e49d26145eceaaa3b6ce34331366a8f..fa3fb5f4e6bc44db94eb42740dec672c099dd889 100644 (file)
@@ -535,25 +535,6 @@ static void iscsi_target_login_drop(struct iscsit_conn *conn, struct iscsi_login
        iscsi_target_login_sess_out(conn, zero_tsih, true);
 }
 
-struct conn_timeout {
-       struct timer_list timer;
-       struct iscsit_conn *conn;
-};
-
-static void iscsi_target_login_timeout(struct timer_list *t)
-{
-       struct conn_timeout *timeout = from_timer(timeout, t, timer);
-       struct iscsit_conn *conn = timeout->conn;
-
-       pr_debug("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n");
-
-       if (conn->login_kworker) {
-               pr_debug("Sending SIGINT to conn->login_kworker %s/%d\n",
-                        conn->login_kworker->comm, conn->login_kworker->pid);
-               send_sig(SIGINT, conn->login_kworker, 1);
-       }
-}
-
 static void iscsi_target_do_login_rx(struct work_struct *work)
 {
        struct iscsit_conn *conn = container_of(work,
@@ -562,12 +543,15 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
        struct iscsi_np *np = login->np;
        struct iscsi_portal_group *tpg = conn->tpg;
        struct iscsi_tpg_np *tpg_np = conn->tpg_np;
-       struct conn_timeout timeout;
        int rc, zero_tsih = login->zero_tsih;
        bool state;
 
        pr_debug("entering iscsi_target_do_login_rx, conn: %p, %s:%d\n",
                        conn, current->comm, current->pid);
+
+       spin_lock(&conn->login_worker_lock);
+       set_bit(LOGIN_FLAGS_WORKER_RUNNING, &conn->login_flags);
+       spin_unlock(&conn->login_worker_lock);
        /*
         * If iscsi_target_do_login_rx() has been invoked by ->sk_data_ready()
         * before initial PDU processing in iscsi_target_start_negotiation()
@@ -597,19 +581,16 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
                goto err;
        }
 
-       conn->login_kworker = current;
        allow_signal(SIGINT);
-
-       timeout.conn = conn;
-       timer_setup_on_stack(&timeout.timer, iscsi_target_login_timeout, 0);
-       mod_timer(&timeout.timer, jiffies + TA_LOGIN_TIMEOUT * HZ);
-       pr_debug("Starting login timer for %s/%d\n", current->comm, current->pid);
+       rc = iscsit_set_login_timer_kworker(conn, current);
+       if (rc < 0) {
+               /* The login timer has already expired */
+               pr_debug("iscsi_target_do_login_rx, login failed\n");
+               goto err;
+       }
 
        rc = conn->conn_transport->iscsit_get_login_rx(conn, login);
-       del_timer_sync(&timeout.timer);
-       destroy_timer_on_stack(&timeout.timer);
        flush_signals(current);
-       conn->login_kworker = NULL;
 
        if (rc < 0)
                goto err;
@@ -646,7 +627,17 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
                if (iscsi_target_sk_check_and_clear(conn,
                                                    LOGIN_FLAGS_WRITE_ACTIVE))
                        goto err;
+
+               /*
+                * Set the login timer thread pointer to NULL to prevent the
+                * login process from getting stuck if the initiator
+                * stops sending data.
+                */
+               rc = iscsit_set_login_timer_kworker(conn, NULL);
+               if (rc < 0)
+                       goto err;
        } else if (rc == 1) {
+               iscsit_stop_login_timer(conn);
                cancel_delayed_work(&conn->login_work);
                iscsi_target_nego_release(conn);
                iscsi_post_login_handler(np, conn, zero_tsih);
@@ -656,6 +647,7 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
 
 err:
        iscsi_target_restore_sock_callbacks(conn);
+       iscsit_stop_login_timer(conn);
        cancel_delayed_work(&conn->login_work);
        iscsi_target_login_drop(conn, login);
        iscsit_deaccess_np(np, tpg, tpg_np);
@@ -1130,6 +1122,7 @@ int iscsi_target_locate_portal(
        iscsi_target_set_sock_callbacks(conn);
 
        login->np = np;
+       conn->tpg = NULL;
 
        login_req = (struct iscsi_login_req *) login->req;
        payload_length = ntoh24(login_req->dlength);
@@ -1197,7 +1190,6 @@ int iscsi_target_locate_portal(
         */
        sessiontype = strncmp(s_buf, DISCOVERY, 9);
        if (!sessiontype) {
-               conn->tpg = iscsit_global->discovery_tpg;
                if (!login->leading_connection)
                        goto get_target;
 
@@ -1214,9 +1206,11 @@ int iscsi_target_locate_portal(
                 * Serialize access across the discovery struct iscsi_portal_group to
                 * process login attempt.
                 */
+               conn->tpg = iscsit_global->discovery_tpg;
                if (iscsit_access_np(np, conn->tpg) < 0) {
                        iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
                                ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE);
+                       conn->tpg = NULL;
                        ret = -1;
                        goto out;
                }
@@ -1368,14 +1362,30 @@ int iscsi_target_start_negotiation(
         * and perform connection cleanup now.
         */
        ret = iscsi_target_do_login(conn, login);
-       if (!ret && iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_INITIAL_PDU))
-               ret = -1;
+       if (!ret) {
+               spin_lock(&conn->login_worker_lock);
+
+               if (iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_INITIAL_PDU))
+                       ret = -1;
+               else if (!test_bit(LOGIN_FLAGS_WORKER_RUNNING, &conn->login_flags)) {
+                       if (iscsit_set_login_timer_kworker(conn, NULL) < 0) {
+                               /*
+                                * The timeout has expired already.
+                                * Schedule login_work to perform the cleanup.
+                                */
+                               schedule_delayed_work(&conn->login_work, 0);
+                       }
+               }
+
+               spin_unlock(&conn->login_worker_lock);
+       }
 
        if (ret < 0) {
                iscsi_target_restore_sock_callbacks(conn);
                iscsi_remove_failed_auth_entry(conn);
        }
        if (ret != 0) {
+               iscsit_stop_login_timer(conn);
                cancel_delayed_work_sync(&conn->login_work);
                iscsi_target_nego_release(conn);
        }
index 26dc8ed3045b6ad9aee85d543bd2ed144e77d2ed..b14835fcb03344780b764bbeeee21bbf53838b86 100644 (file)
@@ -1040,6 +1040,57 @@ void iscsit_stop_nopin_timer(struct iscsit_conn *conn)
        spin_unlock_bh(&conn->nopin_timer_lock);
 }
 
+void iscsit_login_timeout(struct timer_list *t)
+{
+       struct iscsit_conn *conn = from_timer(conn, t, login_timer);
+       struct iscsi_login *login = conn->login;
+
+       pr_debug("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n");
+
+       spin_lock_bh(&conn->login_timer_lock);
+       login->login_failed = 1;
+
+       if (conn->login_kworker) {
+               pr_debug("Sending SIGINT to conn->login_kworker %s/%d\n",
+                        conn->login_kworker->comm, conn->login_kworker->pid);
+               send_sig(SIGINT, conn->login_kworker, 1);
+       } else {
+               schedule_delayed_work(&conn->login_work, 0);
+       }
+       spin_unlock_bh(&conn->login_timer_lock);
+}
+
+void iscsit_start_login_timer(struct iscsit_conn *conn, struct task_struct *kthr)
+{
+       pr_debug("Login timer started\n");
+
+       conn->login_kworker = kthr;
+       mod_timer(&conn->login_timer, jiffies + TA_LOGIN_TIMEOUT * HZ);
+}
+
+int iscsit_set_login_timer_kworker(struct iscsit_conn *conn, struct task_struct *kthr)
+{
+       struct iscsi_login *login = conn->login;
+       int ret = 0;
+
+       spin_lock_bh(&conn->login_timer_lock);
+       if (login->login_failed) {
+               /* The timer has already expired */
+               ret = -1;
+       } else {
+               conn->login_kworker = kthr;
+       }
+       spin_unlock_bh(&conn->login_timer_lock);
+
+       return ret;
+}
+
+void iscsit_stop_login_timer(struct iscsit_conn *conn)
+{
+       pr_debug("Login timer stopped\n");
+       timer_delete_sync(&conn->login_timer);
+}
+
 int iscsit_send_tx_data(
        struct iscsit_cmd *cmd,
        struct iscsit_conn *conn,
index 33ea799a08508f16c59ca931e8182d9afeec9dac..24b8e577575a6ba567b0ca33cc21d3e8e10dd678 100644 (file)
@@ -56,6 +56,10 @@ extern void iscsit_handle_nopin_timeout(struct timer_list *t);
 extern void __iscsit_start_nopin_timer(struct iscsit_conn *);
 extern void iscsit_start_nopin_timer(struct iscsit_conn *);
 extern void iscsit_stop_nopin_timer(struct iscsit_conn *);
+extern void iscsit_login_timeout(struct timer_list *t);
+extern void iscsit_start_login_timer(struct iscsit_conn *, struct task_struct *kthr);
+extern void iscsit_stop_login_timer(struct iscsit_conn *);
+extern int iscsit_set_login_timer_kworker(struct iscsit_conn *, struct task_struct *kthr);
 extern int iscsit_send_tx_data(struct iscsit_cmd *, struct iscsit_conn *, int);
 extern int iscsit_fe_sendpage_sg(struct iscsit_cmd *, struct iscsit_conn *);
 extern int iscsit_tx_login_rsp(struct iscsit_conn *, u8, u8);
index 49702cb08f4fb3a56f28f3bd9f643268b68cba1f..3861ae06d902f072451bd46d99206ab8bb8e53f5 100644 (file)
@@ -1004,8 +1004,10 @@ static u32 get_async_notif_value(optee_invoke_fn *invoke_fn, bool *value_valid,
 
        invoke_fn(OPTEE_SMC_GET_ASYNC_NOTIF_VALUE, 0, 0, 0, 0, 0, 0, 0, &res);
 
-       if (res.a0)
+       if (res.a0) {
+               *value_valid = false;
                return 0;
+       }
        *value_valid = (res.a2 & OPTEE_SMC_ASYNC_NOTIF_VALUE_VALID);
        *value_pending = (res.a2 & OPTEE_SMC_ASYNC_NOTIF_VALUE_PENDING);
        return res.a1;
index 810231b59dcdcc7b1e2943a603b099ac40a3e33b..5e1164226ada21b93d2ef2eb954d17a5d214b4bc 100644 (file)
@@ -131,7 +131,7 @@ static ssize_t available_uuids_show(struct device *dev,
 
        for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; i++) {
                if (priv->uuid_bitmap & (1 << i))
-                       length += sysfs_emit_at(buf, length, int3400_thermal_uuids[i]);
+                       length += sysfs_emit_at(buf, length, "%s\n", int3400_thermal_uuids[i]);
        }
 
        return length;
@@ -149,7 +149,7 @@ static ssize_t current_uuid_show(struct device *dev,
 
        for (i = 0; i <= INT3400_THERMAL_CRITICAL; i++) {
                if (priv->os_uuid_mask & BIT(i))
-                       length += sysfs_emit_at(buf, length, int3400_thermal_uuids[i]);
+                       length += sysfs_emit_at(buf, length, "%s\n", int3400_thermal_uuids[i]);
        }
 
        if (length)
index d76e923fbc6a01fcc8ce93bb998d4231511ffa39..c0aee5dc5237f76e7256d014c80fc9cc030418f5 100644 (file)
@@ -54,6 +54,21 @@ static int ring_interrupt_index(const struct tb_ring *ring)
        return bit;
 }
 
+static void nhi_mask_interrupt(struct tb_nhi *nhi, int mask, int ring)
+{
+       if (nhi->quirks & QUIRK_AUTO_CLEAR_INT)
+               return;
+       iowrite32(mask, nhi->iobase + REG_RING_INTERRUPT_MASK_CLEAR_BASE + ring);
+}
+
+static void nhi_clear_interrupt(struct tb_nhi *nhi, int ring)
+{
+       if (nhi->quirks & QUIRK_AUTO_CLEAR_INT)
+               ioread32(nhi->iobase + REG_RING_NOTIFY_BASE + ring);
+       else
+               iowrite32(~0, nhi->iobase + REG_RING_INT_CLEAR + ring);
+}
+
 /*
  * ring_interrupt_active() - activate/deactivate interrupts for a single ring
  *
@@ -61,8 +76,8 @@ static int ring_interrupt_index(const struct tb_ring *ring)
  */
 static void ring_interrupt_active(struct tb_ring *ring, bool active)
 {
-       int reg = REG_RING_INTERRUPT_BASE +
-                 ring_interrupt_index(ring) / 32 * 4;
+       int index = ring_interrupt_index(ring) / 32 * 4;
+       int reg = REG_RING_INTERRUPT_BASE + index;
        int interrupt_bit = ring_interrupt_index(ring) & 31;
        int mask = 1 << interrupt_bit;
        u32 old, new;
@@ -123,7 +138,11 @@ static void ring_interrupt_active(struct tb_ring *ring, bool active)
                                         "interrupt for %s %d is already %s\n",
                                         RING_TYPE(ring), ring->hop,
                                         active ? "enabled" : "disabled");
-       iowrite32(new, ring->nhi->iobase + reg);
+
+       if (active)
+               iowrite32(new, ring->nhi->iobase + reg);
+       else
+               nhi_mask_interrupt(ring->nhi, mask, index);
 }
 
 /*
@@ -136,11 +155,11 @@ static void nhi_disable_interrupts(struct tb_nhi *nhi)
        int i = 0;
        /* disable interrupts */
        for (i = 0; i < RING_INTERRUPT_REG_COUNT(nhi); i++)
-               iowrite32(0, nhi->iobase + REG_RING_INTERRUPT_BASE + 4 * i);
+               nhi_mask_interrupt(nhi, ~0, 4 * i);
 
        /* clear interrupt status bits */
        for (i = 0; i < RING_NOTIFY_REG_COUNT(nhi); i++)
-               ioread32(nhi->iobase + REG_RING_NOTIFY_BASE + 4 * i);
+               nhi_clear_interrupt(nhi, 4 * i);
 }
 
 /* ring helper methods */
index faef165a919ccda93a00fea018151210f68aec1b..6ba2958154770f9d2f2e11251b754c818baf360e 100644 (file)
@@ -93,6 +93,8 @@ struct ring_desc {
 #define REG_RING_INTERRUPT_BASE        0x38200
 #define RING_INTERRUPT_REG_COUNT(nhi) ((31 + 2 * nhi->hop_count) / 32)
 
+#define REG_RING_INTERRUPT_MASK_CLEAR_BASE     0x38208
+
 #define REG_INT_THROTTLING_RATE        0x38c00
 
 /* Interrupt Vector Allocation */
index f801b1f5b46c0cd98df6ed19e9c76d7342765585..af0e1c07018795d406bab65eea73181f79920c57 100644 (file)
@@ -1012,7 +1012,7 @@ static int brcmuart_probe(struct platform_device *pdev)
        of_property_read_u32(np, "clock-frequency", &clk_rate);
 
        /* See if a Baud clock has been specified */
-       baud_mux_clk = of_clk_get_by_name(np, "sw_baud");
+       baud_mux_clk = devm_clk_get(dev, "sw_baud");
        if (IS_ERR(baud_mux_clk)) {
                if (PTR_ERR(baud_mux_clk) == -EPROBE_DEFER) {
                        ret = -EPROBE_DEFER;
@@ -1032,7 +1032,7 @@ static int brcmuart_probe(struct platform_device *pdev)
        if (clk_rate == 0) {
                dev_err(dev, "clock-frequency or clk not defined\n");
                ret = -EINVAL;
-               goto release_dma;
+               goto err_clk_disable;
        }
 
        dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not ");
@@ -1119,6 +1119,8 @@ err1:
        serial8250_unregister_port(priv->line);
 err:
        brcmuart_free_bufs(dev, priv);
+err_clk_disable:
+       clk_disable_unprepare(baud_mux_clk);
 release_dma:
        if (priv->dma_enabled)
                brcmuart_arbitration(priv, 0);
@@ -1133,6 +1135,7 @@ static int brcmuart_remove(struct platform_device *pdev)
        hrtimer_cancel(&priv->hrt);
        serial8250_unregister_port(priv->line);
        brcmuart_free_bufs(&pdev->dev, priv);
+       clk_disable_unprepare(priv->baud_mux_clk);
        if (priv->dma_enabled)
                brcmuart_arbitration(priv, 0);
        return 0;
index 64770c62bbec5436d332821ffaf57074276b2422..b406cba10b0eb4b6bb97aacb18d938000efb1903 100644 (file)
 #define PCI_DEVICE_ID_COMMTECH_4224PCIE                0x0020
 #define PCI_DEVICE_ID_COMMTECH_4228PCIE                0x0021
 #define PCI_DEVICE_ID_COMMTECH_4222PCIE                0x0022
+
 #define PCI_DEVICE_ID_EXAR_XR17V4358           0x4358
 #define PCI_DEVICE_ID_EXAR_XR17V8358           0x8358
 
+#define PCI_SUBDEVICE_ID_USR_2980              0x0128
+#define PCI_SUBDEVICE_ID_USR_2981              0x0129
+
 #define PCI_DEVICE_ID_SEALEVEL_710xC           0x1001
 #define PCI_DEVICE_ID_SEALEVEL_720xC           0x1002
 #define PCI_DEVICE_ID_SEALEVEL_740xC           0x1004
@@ -829,6 +833,15 @@ static const struct exar8250_board pbn_exar_XR17V8358 = {
                (kernel_ulong_t)&bd                     \
        }
 
+#define USR_DEVICE(devid, sdevid, bd) {                        \
+       PCI_DEVICE_SUB(                                 \
+               PCI_VENDOR_ID_USR,                      \
+               PCI_DEVICE_ID_EXAR_##devid,             \
+               PCI_VENDOR_ID_EXAR,                     \
+               PCI_SUBDEVICE_ID_USR_##sdevid), 0, 0,   \
+               (kernel_ulong_t)&bd                     \
+       }
+
 static const struct pci_device_id exar_pci_tbl[] = {
        EXAR_DEVICE(ACCESSIO, COM_2S, pbn_exar_XR17C15x),
        EXAR_DEVICE(ACCESSIO, COM_4S, pbn_exar_XR17C15x),
@@ -853,6 +866,10 @@ static const struct pci_device_id exar_pci_tbl[] = {
 
        IBM_DEVICE(XR17C152, SATURN_SERIAL_ONE_PORT, pbn_exar_ibm_saturn),
 
+       /* USRobotics USR298x-OEM PCI Modems */
+       USR_DEVICE(XR17C152, 2980, pbn_exar_XR17C15x),
+       USR_DEVICE(XR17C152, 2981, pbn_exar_XR17C15x),
+
        /* Exar Corp. XR17C15[248] Dual/Quad/Octal UART */
        EXAR_DEVICE(EXAR, XR17C152, pbn_exar_XR17C15x),
        EXAR_DEVICE(EXAR, XR17C154, pbn_exar_XR17C15x),
index c55be6fda0cab1fb9cedc6014fb8b90e5094a492..e80c4f6551a1c26c701729d2eb6d22623016c3d4 100644 (file)
@@ -1920,6 +1920,8 @@ pci_moxa_setup(struct serial_private *priv,
 #define PCI_SUBDEVICE_ID_SIIG_DUAL_30  0x2530
 #define PCI_VENDOR_ID_ADVANTECH                0x13fe
 #define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66
+#define PCI_DEVICE_ID_ADVANTECH_PCI1600        0x1600
+#define PCI_DEVICE_ID_ADVANTECH_PCI1600_1611   0x1611
 #define PCI_DEVICE_ID_ADVANTECH_PCI3620        0x3620
 #define PCI_DEVICE_ID_ADVANTECH_PCI3618        0x3618
 #define PCI_DEVICE_ID_ADVANTECH_PCIf618        0xf618
@@ -4085,6 +4087,9 @@ static SIMPLE_DEV_PM_OPS(pciserial_pm_ops, pciserial_suspend_one,
                         pciserial_resume_one);
 
 static const struct pci_device_id serial_pci_tbl[] = {
+       {       PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI1600,
+               PCI_DEVICE_ID_ADVANTECH_PCI1600_1611, PCI_ANY_ID, 0, 0,
+               pbn_b0_4_921600 },
        /* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */
        {       PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620,
                PCI_DEVICE_ID_ADVANTECH_PCI3620, 0x0001, 0, 0,
index fe8d79c4ae95e5c0cb944c6906f9b286832f46e6..c153ba3a018a255bd4304099d951a017f3482502 100644 (file)
@@ -669,6 +669,7 @@ EXPORT_SYMBOL_GPL(serial8250_em485_supported);
 /**
  * serial8250_em485_config() - generic ->rs485_config() callback
  * @port: uart port
+ * @termios: termios structure
  * @rs485: rs485 settings
  *
  * Generic callback usable by 8250 uart drivers to activate rs485 settings
index 2509e7f74ccf2bcd7a366c90dee0724a9b38ef06..89956bbf34d9e4d4ad6b921db7a13b039629741a 100644 (file)
@@ -113,13 +113,15 @@ static int tegra_uart_probe(struct platform_device *pdev)
 
        ret = serial8250_register_8250_port(&port8250);
        if (ret < 0)
-               goto err_clkdisable;
+               goto err_ctrl_assert;
 
        platform_set_drvdata(pdev, uart);
        uart->line = ret;
 
        return 0;
 
+err_ctrl_assert:
+       reset_control_assert(uart->rst);
 err_clkdisable:
        clk_disable_unprepare(uart->clk);
 
index 398e5aac2e77a326686310d4b3c2355502765ce2..3e3fb377d90d4c9f15ad55055025d4d6d8883c25 100644 (file)
@@ -762,7 +762,7 @@ config SERIAL_PMACZILOG_CONSOLE
 
 config SERIAL_CPM
        tristate "CPM SCC/SMC serial port support"
-       depends on CPM2 || CPM1 || (PPC32 && COMPILE_TEST)
+       depends on CPM2 || CPM1
        select SERIAL_CORE
        help
          This driver supports the SCC and SMC serial ports on Motorola 
index 59e25f2b6632215cbb06a60a4c17e57402abc53e..4b2512eef577b431748cf539609cb4e72678633c 100644 (file)
@@ -606,10 +606,11 @@ static int arc_serial_probe(struct platform_device *pdev)
        }
        uart->baud = val;
 
-       port->membase = of_iomap(np, 0);
-       if (!port->membase)
+       port->membase = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(port->membase)) {
                /* No point of dev_err since UART itself is hosed here */
-               return -ENXIO;
+               return PTR_ERR(port->membase);
+       }
 
        port->irq = irq_of_parse_and_map(np, 0);
 
index 0577618e78c041af601b2f238f86b67de4ab2f1a..46c03ed71c31bb346e67e48cd998500f903b53fa 100644 (file)
@@ -19,8 +19,6 @@ struct gpio_desc;
 #include "cpm_uart_cpm2.h"
 #elif defined(CONFIG_CPM1)
 #include "cpm_uart_cpm1.h"
-#elif defined(CONFIG_COMPILE_TEST)
-#include "cpm_uart_cpm2.h"
 #endif
 
 #define SERIAL_CPM_MAJOR       204
index c91916e13648302545d8e60727d8615fa94ca436..7486a2b8556c803b23eec8502d65936ee7ccfe4c 100644 (file)
@@ -1495,34 +1495,36 @@ static void lpuart_break_ctl(struct uart_port *port, int break_state)
 
 static void lpuart32_break_ctl(struct uart_port *port, int break_state)
 {
-       unsigned long temp, modem;
-       struct tty_struct *tty;
-       unsigned int cflag = 0;
-
-       tty = tty_port_tty_get(&port->state->port);
-       if (tty) {
-               cflag = tty->termios.c_cflag;
-               tty_kref_put(tty);
-       }
+       unsigned long temp;
 
-       temp = lpuart32_read(port, UARTCTRL) & ~UARTCTRL_SBK;
-       modem = lpuart32_read(port, UARTMODIR);
+       temp = lpuart32_read(port, UARTCTRL);
 
+       /*
+        * LPUART IP now has two known bugs, one is CTS has higher priority than the
+        * break signal, which causes the break signal sending through UARTCTRL_SBK
+        * may impacted by the CTS input if the HW flow control is enabled. It
+        * exists on all platforms we support in this driver.
+        * Another bug is i.MX8QM LPUART may have an additional break character
+        * being sent after SBK was cleared.
+        * To avoid above two bugs, we use Transmit Data Inversion function to send
+        * the break signal instead of UARTCTRL_SBK.
+        */
        if (break_state != 0) {
-               temp |= UARTCTRL_SBK;
                /*
-                * LPUART CTS has higher priority than SBK, need to disable CTS before
-                * asserting SBK to avoid any interference if flow control is enabled.
+                * Disable the transmitter to prevent any data from being sent out
+                * during break, then invert the TX line to send break.
                 */
-               if (cflag & CRTSCTS && modem & UARTMODIR_TXCTSE)
-                       lpuart32_write(port, modem & ~UARTMODIR_TXCTSE, UARTMODIR);
+               temp &= ~UARTCTRL_TE;
+               lpuart32_write(port, temp, UARTCTRL);
+               temp |= UARTCTRL_TXINV;
+               lpuart32_write(port, temp, UARTCTRL);
        } else {
-               /* Re-enable the CTS when break off. */
-               if (cflag & CRTSCTS && !(modem & UARTMODIR_TXCTSE))
-                       lpuart32_write(port, modem | UARTMODIR_TXCTSE, UARTMODIR);
+               /* Disable the TXINV to turn off break and re-enable transmitter. */
+               temp &= ~UARTCTRL_TXINV;
+               lpuart32_write(port, temp, UARTCTRL);
+               temp |= UARTCTRL_TE;
+               lpuart32_write(port, temp, UARTCTRL);
        }
-
-       lpuart32_write(port, temp, UARTCTRL);
 }
 
 static void lpuart_setup_watermark(struct lpuart_port *sport)
index 08dc3e2a729c76af3cb1ccb2658831c83873b45a..8582479f0211a082cfe1209dcee1aacc3cdc1459 100644 (file)
@@ -1664,19 +1664,18 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
        uport->private_data = &port->private_data;
        platform_set_drvdata(pdev, port);
 
-       ret = uart_add_one_port(drv, uport);
-       if (ret)
-               return ret;
-
        irq_set_status_flags(uport->irq, IRQ_NOAUTOEN);
        ret = devm_request_irq(uport->dev, uport->irq, qcom_geni_serial_isr,
                        IRQF_TRIGGER_HIGH, port->name, uport);
        if (ret) {
                dev_err(uport->dev, "Failed to get IRQ ret %d\n", ret);
-               uart_remove_one_port(drv, uport);
                return ret;
        }
 
+       ret = uart_add_one_port(drv, uport);
+       if (ret)
+               return ret;
+
        /*
         * Set pm_runtime status as ACTIVE so that wakeup_irq gets
         * enabled/disabled from dev_pm_arm_wake_irq during system
index 498ba9c0ee9374f971854009ce39f64dfef345b9..829c4be66f3b036e1941a7e6fab286f90d9e8725 100644 (file)
@@ -656,10 +656,17 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
                        }
                }
 
-               /* The vcs_size might have changed while we slept to grab
-                * the user buffer, so recheck.
+               /* The vc might have been freed or vcs_size might have changed
+                * while we slept to grab the user buffer, so recheck.
                 * Return data written up to now on failure.
                 */
+               vc = vcs_vc(inode, &viewed);
+               if (!vc) {
+                       if (written)
+                               break;
+                       ret = -ENXIO;
+                       goto unlock_out;
+               }
                size = vcs_size(vc, attr, false);
                if (size < 0) {
                        if (written)
index 202ff71e1b582132f474c91379a63b158074a928..51b3c6ae781df4a4ab93f5ac5a61f71e622c27e2 100644 (file)
@@ -150,7 +150,8 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba)
        u32 hba_maxq, rem, tot_queues;
        struct Scsi_Host *host = hba->host;
 
-       hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities);
+       /* maxq is 0 based value */
+       hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities) + 1;
 
        tot_queues = UFS_MCQ_NUM_DEV_CMD_QUEUES + read_queues + poll_queues +
                        rw_queues;
@@ -265,7 +266,7 @@ static int ufshcd_mcq_get_tag(struct ufs_hba *hba,
        addr = (le64_to_cpu(cqe->command_desc_base_addr) & CQE_UCD_BA) -
                hba->ucdl_dma_addr;
 
-       return div_u64(addr, sizeof(struct utp_transfer_cmd_desc));
+       return div_u64(addr, ufshcd_get_ucd_size(hba));
 }
 
 static void ufshcd_mcq_process_cqe(struct ufs_hba *hba,
index 17d7bb875fee8355b796c2bc842a260ce8e44dbf..e7e79f515e14182c627069ea231fd8c2a0f0baaf 100644 (file)
@@ -2849,10 +2849,10 @@ static void ufshcd_map_queues(struct Scsi_Host *shost)
 static void ufshcd_init_lrb(struct ufs_hba *hba, struct ufshcd_lrb *lrb, int i)
 {
        struct utp_transfer_cmd_desc *cmd_descp = (void *)hba->ucdl_base_addr +
-               i * sizeof_utp_transfer_cmd_desc(hba);
+               i * ufshcd_get_ucd_size(hba);
        struct utp_transfer_req_desc *utrdlp = hba->utrdl_base_addr;
        dma_addr_t cmd_desc_element_addr = hba->ucdl_dma_addr +
-               i * sizeof_utp_transfer_cmd_desc(hba);
+               i * ufshcd_get_ucd_size(hba);
        u16 response_offset = offsetof(struct utp_transfer_cmd_desc,
                                       response_upiu);
        u16 prdt_offset = offsetof(struct utp_transfer_cmd_desc, prd_table);
@@ -3761,7 +3761,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
        size_t utmrdl_size, utrdl_size, ucdl_size;
 
        /* Allocate memory for UTP command descriptors */
-       ucdl_size = sizeof_utp_transfer_cmd_desc(hba) * hba->nutrs;
+       ucdl_size = ufshcd_get_ucd_size(hba) * hba->nutrs;
        hba->ucdl_base_addr = dmam_alloc_coherent(hba->dev,
                                                  ucdl_size,
                                                  &hba->ucdl_dma_addr,
@@ -3861,7 +3861,7 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)
        prdt_offset =
                offsetof(struct utp_transfer_cmd_desc, prd_table);
 
-       cmd_desc_size = sizeof_utp_transfer_cmd_desc(hba);
+       cmd_desc_size = ufshcd_get_ucd_size(hba);
        cmd_desc_dma_addr = hba->ucdl_dma_addr;
 
        for (i = 0; i < hba->nutrs; i++) {
@@ -8452,7 +8452,7 @@ static void ufshcd_release_sdb_queue(struct ufs_hba *hba, int nutrs)
 {
        size_t ucdl_size, utrdl_size;
 
-       ucdl_size = sizeof(struct utp_transfer_cmd_desc) * nutrs;
+       ucdl_size = ufshcd_get_ucd_size(hba) * nutrs;
        dmam_free_coherent(hba->dev, ucdl_size, hba->ucdl_base_addr,
                           hba->ucdl_dma_addr);
 
@@ -9459,8 +9459,16 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
                         * that performance might be impacted.
                         */
                        ret = ufshcd_urgent_bkops(hba);
-                       if (ret)
+                       if (ret) {
+                               /*
+                                * If return err in suspend flow, IO will hang.
+                                * Trigger error handler and break suspend for
+                                * error recovery.
+                                */
+                               ufshcd_force_error_recovery(hba);
+                               ret = -EBUSY;
                                goto enable_scaling;
+                       }
                } else {
                        /* make sure that auto bkops is disabled */
                        ufshcd_disable_auto_bkops(hba);
index 69e93f3e7faf4bf1e1cdbd587305b198cd68be6c..6d99e5a06ae8c27a100f35f3e8076385b0d6b3d5 100644 (file)
@@ -46,11 +46,13 @@ static int uio_dfl_probe(struct dfl_device *ddev)
 
 #define FME_FEATURE_ID_ETH_GROUP       0x10
 #define FME_FEATURE_ID_HSSI_SUBSYS     0x15
+#define FME_FEATURE_ID_VENDOR_SPECIFIC 0x23
 #define PORT_FEATURE_ID_IOPLL_USRCLK   0x14
 
 static const struct dfl_device_id uio_dfl_ids[] = {
        { FME_ID, FME_FEATURE_ID_ETH_GROUP },
        { FME_ID, FME_FEATURE_ID_HSSI_SUBSYS },
+       { FME_ID, FME_FEATURE_ID_VENDOR_SPECIFIC },
        { PORT_ID, PORT_FEATURE_ID_IOPLL_USRCLK },
        { }
 };
index ccfaebca6faa7512ac92ad0beeea239f467bbb52..1dcadef933e3a6fb3e163ec5061a8f391960baa5 100644 (file)
@@ -2097,6 +2097,19 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
        else
                priv_ep->trb_burst_size = 16;
 
+       /*
+        * In versions preceding DEV_VER_V2, for example, iMX8QM, there exit the bugs
+        * in the DMA. These bugs occur when the trb_burst_size exceeds 16 and the
+        * address is not aligned to 128 Bytes (which is a product of the 64-bit AXI
+        * and AXI maximum burst length of 16 or 0xF+1, dma_axi_ctrl0[3:0]). This
+        * results in data corruption when it crosses the 4K border. The corruption
+        * specifically occurs from the position (4K - (address & 0x7F)) to 4K.
+        *
+        * So force trb_burst_size to 16 at such platform.
+        */
+       if (priv_dev->dev_ver < DEV_VER_V2)
+               priv_ep->trb_burst_size = 16;
+
        mult = min_t(u8, mult, EP_CFG_MULT_MAX);
        buffering = min_t(u8, buffering, EP_CFG_BUFFERING_MAX);
        maxburst = min_t(u8, maxburst, EP_CFG_MAXBURST_MAX);
index 4bb6d304eb4b21fe3049f44ca000826af2c40ff0..311007b1d9046566b8a155c21ef8188cca13a819 100644 (file)
@@ -1928,6 +1928,8 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data,
 
        if (request.req.wLength > USBTMC_BUFSIZE)
                return -EMSGSIZE;
+       if (request.req.wLength == 0)   /* Length-0 requests are never IN */
+               request.req.bRequestType &= ~USB_DIR_IN;
 
        is_in = request.req.bRequestType & USB_DIR_IN;
 
index fbb087b728dc987fbcda7d56fbba97b0d6a948a5..268ccbec88f951ab44ad5f410dc19a3a22e3c7a7 100644 (file)
@@ -172,3 +172,44 @@ void hcd_buffer_free(
        }
        dma_free_coherent(hcd->self.sysdev, size, addr, dma);
 }
+
+void *hcd_buffer_alloc_pages(struct usb_hcd *hcd,
+               size_t size, gfp_t mem_flags, dma_addr_t *dma)
+{
+       if (size == 0)
+               return NULL;
+
+       if (hcd->localmem_pool)
+               return gen_pool_dma_alloc_align(hcd->localmem_pool,
+                               size, dma, PAGE_SIZE);
+
+       /* some USB hosts just use PIO */
+       if (!hcd_uses_dma(hcd)) {
+               *dma = DMA_MAPPING_ERROR;
+               return (void *)__get_free_pages(mem_flags,
+                               get_order(size));
+       }
+
+       return dma_alloc_coherent(hcd->self.sysdev,
+                       size, dma, mem_flags);
+}
+
+void hcd_buffer_free_pages(struct usb_hcd *hcd,
+               size_t size, void *addr, dma_addr_t dma)
+{
+       if (!addr)
+               return;
+
+       if (hcd->localmem_pool) {
+               gen_pool_free(hcd->localmem_pool,
+                               (unsigned long)addr, size);
+               return;
+       }
+
+       if (!hcd_uses_dma(hcd)) {
+               free_pages((unsigned long)addr, get_order(size));
+               return;
+       }
+
+       dma_free_coherent(hcd->self.sysdev, size, addr, dma);
+}
index e501a03d6c700b930b0a152bcb9c87dfe6f5ae7e..fcf68818e999286296e51626e72b25461ab3ea7f 100644 (file)
@@ -186,6 +186,7 @@ static int connected(struct usb_dev_state *ps)
 static void dec_usb_memory_use_count(struct usb_memory *usbm, int *count)
 {
        struct usb_dev_state *ps = usbm->ps;
+       struct usb_hcd *hcd = bus_to_hcd(ps->dev->bus);
        unsigned long flags;
 
        spin_lock_irqsave(&ps->lock, flags);
@@ -194,8 +195,8 @@ static void dec_usb_memory_use_count(struct usb_memory *usbm, int *count)
                list_del(&usbm->memlist);
                spin_unlock_irqrestore(&ps->lock, flags);
 
-               usb_free_coherent(ps->dev, usbm->size, usbm->mem,
-                               usbm->dma_handle);
+               hcd_buffer_free_pages(hcd, usbm->size,
+                               usbm->mem, usbm->dma_handle);
                usbfs_decrease_memory_usage(
                        usbm->size + sizeof(struct usb_memory));
                kfree(usbm);
@@ -234,7 +235,7 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma)
        size_t size = vma->vm_end - vma->vm_start;
        void *mem;
        unsigned long flags;
-       dma_addr_t dma_handle;
+       dma_addr_t dma_handle = DMA_MAPPING_ERROR;
        int ret;
 
        ret = usbfs_increase_memory_usage(size + sizeof(struct usb_memory));
@@ -247,8 +248,8 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma)
                goto error_decrease_mem;
        }
 
-       mem = usb_alloc_coherent(ps->dev, size, GFP_USER | __GFP_NOWARN,
-                       &dma_handle);
+       mem = hcd_buffer_alloc_pages(hcd,
+                       size, GFP_USER | __GFP_NOWARN, &dma_handle);
        if (!mem) {
                ret = -ENOMEM;
                goto error_free_usbm;
@@ -264,7 +265,14 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma)
        usbm->vma_use_count = 1;
        INIT_LIST_HEAD(&usbm->memlist);
 
-       if (hcd->localmem_pool || !hcd_uses_dma(hcd)) {
+       /*
+        * In DMA-unavailable cases, hcd_buffer_alloc_pages allocates
+        * normal pages and assigns DMA_MAPPING_ERROR to dma_handle. Check
+        * whether we are in such cases, and then use remap_pfn_range (or
+        * dma_mmap_coherent) to map normal (or DMA) pages into the user
+        * space, respectively.
+        */
+       if (dma_handle == DMA_MAPPING_ERROR) {
                if (remap_pfn_range(vma, vma->vm_start,
                                    virt_to_phys(usbm->mem) >> PAGE_SHIFT,
                                    size, vma->vm_page_prot) < 0) {
index 0beaab932e7db2122e05bf52ef84c0c4b538d434..7b2ce013cc5bab35a2abcb90bcaedd0f91afbe62 100644 (file)
@@ -1137,7 +1137,7 @@ static int dwc3_core_init(struct dwc3 *dwc)
 
        dwc3_set_incr_burst_type(dwc);
 
-       dwc3_phy_power_on(dwc);
+       ret = dwc3_phy_power_on(dwc);
        if (ret)
                goto err_exit_phy;
 
index d56457c02996b669c60a096533a506c324ad4a98..1f043c31a0969ffc427f62b56974162c0cf0651b 100644 (file)
@@ -1116,6 +1116,7 @@ struct dwc3_scratchpad_array {
  * @dis_metastability_quirk: set to disable metastability quirk.
  * @dis_split_quirk: set to disable split boundary.
  * @wakeup_configured: set if the device is configured for remote wakeup.
+ * @suspended: set to track suspend event due to U3/L2.
  * @imod_interval: set the interrupt moderation interval in 250ns
  *                     increments or 0 to disable.
  * @max_cfg_eps: current max number of IN eps used across all USB configs.
@@ -1332,6 +1333,7 @@ struct dwc3 {
        unsigned                dis_split_quirk:1;
        unsigned                async_callbacks:1;
        unsigned                wakeup_configured:1;
+       unsigned                suspended:1;
 
        u16                     imod_interval;
 
index e4a2560b9dc0c670d9a5c775a73d17c340b5a992..ebf03468fac4a9f89cefa093c6ba346f0b1035dd 100644 (file)
@@ -332,6 +332,11 @@ static int dwc3_lsp_show(struct seq_file *s, void *unused)
        unsigned int            current_mode;
        unsigned long           flags;
        u32                     reg;
+       int                     ret;
+
+       ret = pm_runtime_resume_and_get(dwc->dev);
+       if (ret < 0)
+               return ret;
 
        spin_lock_irqsave(&dwc->lock, flags);
        reg = dwc3_readl(dwc->regs, DWC3_GSTS);
@@ -350,6 +355,8 @@ static int dwc3_lsp_show(struct seq_file *s, void *unused)
        }
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       pm_runtime_put_sync(dwc->dev);
+
        return 0;
 }
 
@@ -395,6 +402,11 @@ static int dwc3_mode_show(struct seq_file *s, void *unused)
        struct dwc3             *dwc = s->private;
        unsigned long           flags;
        u32                     reg;
+       int                     ret;
+
+       ret = pm_runtime_resume_and_get(dwc->dev);
+       if (ret < 0)
+               return ret;
 
        spin_lock_irqsave(&dwc->lock, flags);
        reg = dwc3_readl(dwc->regs, DWC3_GCTL);
@@ -414,6 +426,8 @@ static int dwc3_mode_show(struct seq_file *s, void *unused)
                seq_printf(s, "UNKNOWN %08x\n", DWC3_GCTL_PRTCAP(reg));
        }
 
+       pm_runtime_put_sync(dwc->dev);
+
        return 0;
 }
 
@@ -463,6 +477,11 @@ static int dwc3_testmode_show(struct seq_file *s, void *unused)
        struct dwc3             *dwc = s->private;
        unsigned long           flags;
        u32                     reg;
+       int                     ret;
+
+       ret = pm_runtime_resume_and_get(dwc->dev);
+       if (ret < 0)
+               return ret;
 
        spin_lock_irqsave(&dwc->lock, flags);
        reg = dwc3_readl(dwc->regs, DWC3_DCTL);
@@ -493,6 +512,8 @@ static int dwc3_testmode_show(struct seq_file *s, void *unused)
                seq_printf(s, "UNKNOWN %d\n", reg);
        }
 
+       pm_runtime_put_sync(dwc->dev);
+
        return 0;
 }
 
@@ -509,6 +530,7 @@ static ssize_t dwc3_testmode_write(struct file *file,
        unsigned long           flags;
        u32                     testmode = 0;
        char                    buf[32];
+       int                     ret;
 
        if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
                return -EFAULT;
@@ -526,10 +548,16 @@ static ssize_t dwc3_testmode_write(struct file *file,
        else
                testmode = 0;
 
+       ret = pm_runtime_resume_and_get(dwc->dev);
+       if (ret < 0)
+               return ret;
+
        spin_lock_irqsave(&dwc->lock, flags);
        dwc3_gadget_set_test_mode(dwc, testmode);
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       pm_runtime_put_sync(dwc->dev);
+
        return count;
 }
 
@@ -548,12 +576,18 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused)
        enum dwc3_link_state    state;
        u32                     reg;
        u8                      speed;
+       int                     ret;
+
+       ret = pm_runtime_resume_and_get(dwc->dev);
+       if (ret < 0)
+               return ret;
 
        spin_lock_irqsave(&dwc->lock, flags);
        reg = dwc3_readl(dwc->regs, DWC3_GSTS);
        if (DWC3_GSTS_CURMOD(reg) != DWC3_GSTS_CURMOD_DEVICE) {
                seq_puts(s, "Not available\n");
                spin_unlock_irqrestore(&dwc->lock, flags);
+               pm_runtime_put_sync(dwc->dev);
                return 0;
        }
 
@@ -566,6 +600,8 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused)
                   dwc3_gadget_hs_link_string(state));
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       pm_runtime_put_sync(dwc->dev);
+
        return 0;
 }
 
@@ -584,6 +620,7 @@ static ssize_t dwc3_link_state_write(struct file *file,
        char                    buf[32];
        u32                     reg;
        u8                      speed;
+       int                     ret;
 
        if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
                return -EFAULT;
@@ -603,10 +640,15 @@ static ssize_t dwc3_link_state_write(struct file *file,
        else
                return -EINVAL;
 
+       ret = pm_runtime_resume_and_get(dwc->dev);
+       if (ret < 0)
+               return ret;
+
        spin_lock_irqsave(&dwc->lock, flags);
        reg = dwc3_readl(dwc->regs, DWC3_GSTS);
        if (DWC3_GSTS_CURMOD(reg) != DWC3_GSTS_CURMOD_DEVICE) {
                spin_unlock_irqrestore(&dwc->lock, flags);
+               pm_runtime_put_sync(dwc->dev);
                return -EINVAL;
        }
 
@@ -616,12 +658,15 @@ static ssize_t dwc3_link_state_write(struct file *file,
        if (speed < DWC3_DSTS_SUPERSPEED &&
            state != DWC3_LINK_STATE_RECOV) {
                spin_unlock_irqrestore(&dwc->lock, flags);
+               pm_runtime_put_sync(dwc->dev);
                return -EINVAL;
        }
 
        dwc3_gadget_set_link_state(dwc, state);
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       pm_runtime_put_sync(dwc->dev);
+
        return count;
 }
 
@@ -645,6 +690,11 @@ static int dwc3_tx_fifo_size_show(struct seq_file *s, void *unused)
        unsigned long           flags;
        u32                     mdwidth;
        u32                     val;
+       int                     ret;
+
+       ret = pm_runtime_resume_and_get(dwc->dev);
+       if (ret < 0)
+               return ret;
 
        spin_lock_irqsave(&dwc->lock, flags);
        val = dwc3_core_fifo_space(dep, DWC3_TXFIFO);
@@ -657,6 +707,8 @@ static int dwc3_tx_fifo_size_show(struct seq_file *s, void *unused)
        seq_printf(s, "%u\n", val);
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       pm_runtime_put_sync(dwc->dev);
+
        return 0;
 }
 
@@ -667,6 +719,11 @@ static int dwc3_rx_fifo_size_show(struct seq_file *s, void *unused)
        unsigned long           flags;
        u32                     mdwidth;
        u32                     val;
+       int                     ret;
+
+       ret = pm_runtime_resume_and_get(dwc->dev);
+       if (ret < 0)
+               return ret;
 
        spin_lock_irqsave(&dwc->lock, flags);
        val = dwc3_core_fifo_space(dep, DWC3_RXFIFO);
@@ -679,6 +736,8 @@ static int dwc3_rx_fifo_size_show(struct seq_file *s, void *unused)
        seq_printf(s, "%u\n", val);
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       pm_runtime_put_sync(dwc->dev);
+
        return 0;
 }
 
@@ -688,12 +747,19 @@ static int dwc3_tx_request_queue_show(struct seq_file *s, void *unused)
        struct dwc3             *dwc = dep->dwc;
        unsigned long           flags;
        u32                     val;
+       int                     ret;
+
+       ret = pm_runtime_resume_and_get(dwc->dev);
+       if (ret < 0)
+               return ret;
 
        spin_lock_irqsave(&dwc->lock, flags);
        val = dwc3_core_fifo_space(dep, DWC3_TXREQQ);
        seq_printf(s, "%u\n", val);
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       pm_runtime_put_sync(dwc->dev);
+
        return 0;
 }
 
@@ -703,12 +769,19 @@ static int dwc3_rx_request_queue_show(struct seq_file *s, void *unused)
        struct dwc3             *dwc = dep->dwc;
        unsigned long           flags;
        u32                     val;
+       int                     ret;
+
+       ret = pm_runtime_resume_and_get(dwc->dev);
+       if (ret < 0)
+               return ret;
 
        spin_lock_irqsave(&dwc->lock, flags);
        val = dwc3_core_fifo_space(dep, DWC3_RXREQQ);
        seq_printf(s, "%u\n", val);
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       pm_runtime_put_sync(dwc->dev);
+
        return 0;
 }
 
@@ -718,12 +791,19 @@ static int dwc3_rx_info_queue_show(struct seq_file *s, void *unused)
        struct dwc3             *dwc = dep->dwc;
        unsigned long           flags;
        u32                     val;
+       int                     ret;
+
+       ret = pm_runtime_resume_and_get(dwc->dev);
+       if (ret < 0)
+               return ret;
 
        spin_lock_irqsave(&dwc->lock, flags);
        val = dwc3_core_fifo_space(dep, DWC3_RXINFOQ);
        seq_printf(s, "%u\n", val);
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       pm_runtime_put_sync(dwc->dev);
+
        return 0;
 }
 
@@ -733,12 +813,19 @@ static int dwc3_descriptor_fetch_queue_show(struct seq_file *s, void *unused)
        struct dwc3             *dwc = dep->dwc;
        unsigned long           flags;
        u32                     val;
+       int                     ret;
+
+       ret = pm_runtime_resume_and_get(dwc->dev);
+       if (ret < 0)
+               return ret;
 
        spin_lock_irqsave(&dwc->lock, flags);
        val = dwc3_core_fifo_space(dep, DWC3_DESCFETCHQ);
        seq_printf(s, "%u\n", val);
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       pm_runtime_put_sync(dwc->dev);
+
        return 0;
 }
 
@@ -748,12 +835,19 @@ static int dwc3_event_queue_show(struct seq_file *s, void *unused)
        struct dwc3             *dwc = dep->dwc;
        unsigned long           flags;
        u32                     val;
+       int                     ret;
+
+       ret = pm_runtime_resume_and_get(dwc->dev);
+       if (ret < 0)
+               return ret;
 
        spin_lock_irqsave(&dwc->lock, flags);
        val = dwc3_core_fifo_space(dep, DWC3_EVENTQ);
        seq_printf(s, "%u\n", val);
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       pm_runtime_put_sync(dwc->dev);
+
        return 0;
 }
 
@@ -798,6 +892,11 @@ static int dwc3_trb_ring_show(struct seq_file *s, void *unused)
        struct dwc3             *dwc = dep->dwc;
        unsigned long           flags;
        int                     i;
+       int                     ret;
+
+       ret = pm_runtime_resume_and_get(dwc->dev);
+       if (ret < 0)
+               return ret;
 
        spin_lock_irqsave(&dwc->lock, flags);
        if (dep->number <= 1) {
@@ -827,6 +926,8 @@ static int dwc3_trb_ring_show(struct seq_file *s, void *unused)
 out:
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       pm_runtime_put_sync(dwc->dev);
+
        return 0;
 }
 
@@ -839,6 +940,11 @@ static int dwc3_ep_info_register_show(struct seq_file *s, void *unused)
        u32                     lower_32_bits;
        u32                     upper_32_bits;
        u32                     reg;
+       int                     ret;
+
+       ret = pm_runtime_resume_and_get(dwc->dev);
+       if (ret < 0)
+               return ret;
 
        spin_lock_irqsave(&dwc->lock, flags);
        reg = DWC3_GDBGLSPMUX_EPSELECT(dep->number);
@@ -851,6 +957,8 @@ static int dwc3_ep_info_register_show(struct seq_file *s, void *unused)
        seq_printf(s, "0x%016llx\n", ep_info);
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       pm_runtime_put_sync(dwc->dev);
+
        return 0;
 }
 
@@ -910,6 +1018,7 @@ void dwc3_debugfs_init(struct dwc3 *dwc)
        dwc->regset->regs = dwc3_regs;
        dwc->regset->nregs = ARRAY_SIZE(dwc3_regs);
        dwc->regset->base = dwc->regs - DWC3_GLOBALS_REGS_START;
+       dwc->regset->dev = dwc->dev;
 
        root = debugfs_create_dir(dev_name(dwc->dev), usb_debug_root);
        dwc->debug_root = root;
index c0ca4d12f95d96b189128456d1b7c33455c02723..d831f5acf7b56bd34390f5539c8654571a537dea 100644 (file)
@@ -2440,6 +2440,7 @@ static int dwc3_gadget_func_wakeup(struct usb_gadget *g, int intf_id)
                        return -EINVAL;
                }
                dwc3_resume_gadget(dwc);
+               dwc->suspended = false;
                dwc->link_state = DWC3_LINK_STATE_U0;
        }
 
@@ -2699,6 +2700,21 @@ static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc)
        return ret;
 }
 
+static int dwc3_gadget_soft_connect(struct dwc3 *dwc)
+{
+       /*
+        * In the Synopsys DWC_usb31 1.90a programming guide section
+        * 4.1.9, it specifies that for a reconnect after a
+        * device-initiated disconnect requires a core soft reset
+        * (DCTL.CSftRst) before enabling the run/stop bit.
+        */
+       dwc3_core_soft_reset(dwc);
+
+       dwc3_event_buffers_setup(dwc);
+       __dwc3_gadget_start(dwc);
+       return dwc3_gadget_run_stop(dwc, true);
+}
+
 static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 {
        struct dwc3             *dwc = gadget_to_dwc(g);
@@ -2737,21 +2753,10 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 
        synchronize_irq(dwc->irq_gadget);
 
-       if (!is_on) {
+       if (!is_on)
                ret = dwc3_gadget_soft_disconnect(dwc);
-       } else {
-               /*
-                * In the Synopsys DWC_usb31 1.90a programming guide section
-                * 4.1.9, it specifies that for a reconnect after a
-                * device-initiated disconnect requires a core soft reset
-                * (DCTL.CSftRst) before enabling the run/stop bit.
-                */
-               dwc3_core_soft_reset(dwc);
-
-               dwc3_event_buffers_setup(dwc);
-               __dwc3_gadget_start(dwc);
-               ret = dwc3_gadget_run_stop(dwc, true);
-       }
+       else
+               ret = dwc3_gadget_soft_connect(dwc);
 
        pm_runtime_put(dwc->dev);
 
@@ -3938,6 +3943,8 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
 {
        int                     reg;
 
+       dwc->suspended = false;
+
        dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RX_DET);
 
        reg = dwc3_readl(dwc->regs, DWC3_DCTL);
@@ -3962,6 +3969,8 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 {
        u32                     reg;
 
+       dwc->suspended = false;
+
        /*
         * Ideally, dwc3_reset_gadget() would trigger the function
         * drivers to stop any active transfers through ep disable.
@@ -4180,6 +4189,8 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 
 static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, unsigned int evtinfo)
 {
+       dwc->suspended = false;
+
        /*
         * TODO take core out of low power mode when that's
         * implemented.
@@ -4277,6 +4288,7 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
                if (dwc->gadget->wakeup_armed) {
                        dwc3_gadget_enable_linksts_evts(dwc, false);
                        dwc3_resume_gadget(dwc);
+                       dwc->suspended = false;
                }
                break;
        case DWC3_LINK_STATE_U1:
@@ -4303,8 +4315,10 @@ static void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc,
 {
        enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK;
 
-       if (dwc->link_state != next && next == DWC3_LINK_STATE_U3)
+       if (!dwc->suspended && next == DWC3_LINK_STATE_U3) {
+               dwc->suspended = true;
                dwc3_suspend_gadget(dwc);
+       }
 
        dwc->link_state = next;
 }
@@ -4655,42 +4669,39 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 int dwc3_gadget_suspend(struct dwc3 *dwc)
 {
        unsigned long flags;
+       int ret;
 
        if (!dwc->gadget_driver)
                return 0;
 
-       dwc3_gadget_run_stop(dwc, false);
+       ret = dwc3_gadget_soft_disconnect(dwc);
+       if (ret)
+               goto err;
 
        spin_lock_irqsave(&dwc->lock, flags);
        dwc3_disconnect_gadget(dwc);
-       __dwc3_gadget_stop(dwc);
        spin_unlock_irqrestore(&dwc->lock, flags);
 
        return 0;
+
+err:
+       /*
+        * Attempt to reset the controller's state. Likely no
+        * communication can be established until the host
+        * performs a port reset.
+        */
+       if (dwc->softconnect)
+               dwc3_gadget_soft_connect(dwc);
+
+       return ret;
 }
 
 int dwc3_gadget_resume(struct dwc3 *dwc)
 {
-       int                     ret;
-
        if (!dwc->gadget_driver || !dwc->softconnect)
                return 0;
 
-       ret = __dwc3_gadget_start(dwc);
-       if (ret < 0)
-               goto err0;
-
-       ret = dwc3_gadget_run_stop(dwc, true);
-       if (ret < 0)
-               goto err1;
-
-       return 0;
-
-err1:
-       __dwc3_gadget_stop(dwc);
-
-err0:
-       return ret;
+       return dwc3_gadget_soft_connect(dwc);
 }
 
 void dwc3_gadget_process_pending_events(struct dwc3 *dwc)
index a13c946e0663c2c41736bc04f0dcfae44895a93b..f41a385a5c421adbdeee11f1f010fb3a885a0b30 100644 (file)
@@ -3535,6 +3535,7 @@ static void ffs_func_unbind(struct usb_configuration *c,
        /* Drain any pending AIO completions */
        drain_workqueue(ffs->io_completion_wq);
 
+       ffs_event_add(ffs, FUNCTIONFS_UNBIND);
        if (!--opts->refcnt)
                functionfs_unbind(ffs);
 
@@ -3559,7 +3560,6 @@ static void ffs_func_unbind(struct usb_configuration *c,
        func->function.ssp_descriptors = NULL;
        func->interfaces_nums = NULL;
 
-       ffs_event_add(ffs, FUNCTIONFS_UNBIND);
 }
 
 static struct usb_function *ffs_alloc(struct usb_function_instance *fi)
index 6956ad8ba8dd86e5c1a3fd6e10bc25adc8a734f2..a366abb456236c7033b6fbd1c7cfb9b4dcc1a7cf 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
+#include <linux/string_helpers.h>
 #include <linux/usb/composite.h>
 
 #include "u_ether.h"
@@ -965,6 +966,8 @@ int gether_get_host_addr_cdc(struct net_device *net, char *host_addr, int len)
        dev = netdev_priv(net);
        snprintf(host_addr, len, "%pm", dev->host_mac);
 
+       string_upper(host_addr, host_addr);
+
        return strlen(host_addr);
 }
 EXPORT_SYMBOL_GPL(gether_get_host_addr_cdc);
index c80f9bd51b7501eef578fde52dae2d40dc712ca6..a36913ae31f9ef56f5814e61bc01d6da1769f8a4 100644 (file)
@@ -170,6 +170,9 @@ static int udc_pci_probe(
                retval = -ENODEV;
                goto err_probe;
        }
+
+       udc = dev;
+
        return 0;
 
 err_probe:
index 4641153e9706b161889ec3836d5807ec71552309..52e6d2e84e35283be4aa3f28c6cb6106c55008da 100644 (file)
@@ -37,10 +37,6 @@ static const struct bus_type gadget_bus_type;
  * @vbus: for udcs who care about vbus status, this value is real vbus status;
  * for udcs who do not care about vbus status, this value is always true
  * @started: the UDC's started state. True if the UDC had started.
- * @connect_lock: protects udc->vbus, udc->started, gadget->connect, gadget->deactivate related
- * functions. usb_gadget_connect_locked, usb_gadget_disconnect_locked,
- * usb_udc_connect_control_locked, usb_gadget_udc_start_locked, usb_gadget_udc_stop_locked are
- * called with this lock held.
  *
  * This represents the internal data structure which is used by the UDC-class
  * to hold information about udc driver and gadget together.
@@ -52,7 +48,6 @@ struct usb_udc {
        struct list_head                list;
        bool                            vbus;
        bool                            started;
-       struct mutex                    connect_lock;
 };
 
 static struct class *udc_class;
@@ -692,9 +687,17 @@ out:
 }
 EXPORT_SYMBOL_GPL(usb_gadget_vbus_disconnect);
 
-/* Internal version of usb_gadget_connect needs to be called with connect_lock held. */
-static int usb_gadget_connect_locked(struct usb_gadget *gadget)
-       __must_hold(&gadget->udc->connect_lock)
+/**
+ * usb_gadget_connect - software-controlled connect to USB host
+ * @gadget:the peripheral being connected
+ *
+ * Enables the D+ (or potentially D-) pullup.  The host will start
+ * enumerating this gadget when the pullup is active and a VBUS session
+ * is active (the link is powered).
+ *
+ * Returns zero on success, else negative errno.
+ */
+int usb_gadget_connect(struct usb_gadget *gadget)
 {
        int ret = 0;
 
@@ -703,15 +706,10 @@ static int usb_gadget_connect_locked(struct usb_gadget *gadget)
                goto out;
        }
 
-       if (gadget->connected)
-               goto out;
-
-       if (gadget->deactivated || !gadget->udc->started) {
+       if (gadget->deactivated) {
                /*
                 * If gadget is deactivated we only save new state.
                 * Gadget will be connected automatically after activation.
-                *
-                * udc first needs to be started before gadget can be pulled up.
                 */
                gadget->connected = true;
                goto out;
@@ -726,32 +724,22 @@ out:
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(usb_gadget_connect);
 
 /**
- * usb_gadget_connect - software-controlled connect to USB host
- * @gadget:the peripheral being connected
+ * usb_gadget_disconnect - software-controlled disconnect from USB host
+ * @gadget:the peripheral being disconnected
  *
- * Enables the D+ (or potentially D-) pullup.  The host will start
- * enumerating this gadget when the pullup is active and a VBUS session
- * is active (the link is powered).
+ * Disables the D+ (or potentially D-) pullup, which the host may see
+ * as a disconnect (when a VBUS session is active).  Not all systems
+ * support software pullup controls.
+ *
+ * Following a successful disconnect, invoke the ->disconnect() callback
+ * for the current gadget driver so that UDC drivers don't need to.
  *
  * Returns zero on success, else negative errno.
  */
-int usb_gadget_connect(struct usb_gadget *gadget)
-{
-       int ret;
-
-       mutex_lock(&gadget->udc->connect_lock);
-       ret = usb_gadget_connect_locked(gadget);
-       mutex_unlock(&gadget->udc->connect_lock);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(usb_gadget_connect);
-
-/* Internal version of usb_gadget_disconnect needs to be called with connect_lock held. */
-static int usb_gadget_disconnect_locked(struct usb_gadget *gadget)
-       __must_hold(&gadget->udc->connect_lock)
+int usb_gadget_disconnect(struct usb_gadget *gadget)
 {
        int ret = 0;
 
@@ -763,12 +751,10 @@ static int usb_gadget_disconnect_locked(struct usb_gadget *gadget)
        if (!gadget->connected)
                goto out;
 
-       if (gadget->deactivated || !gadget->udc->started) {
+       if (gadget->deactivated) {
                /*
                 * If gadget is deactivated we only save new state.
                 * Gadget will stay disconnected after activation.
-                *
-                * udc should have been started before gadget being pulled down.
                 */
                gadget->connected = false;
                goto out;
@@ -788,30 +774,6 @@ out:
 
        return ret;
 }
-
-/**
- * usb_gadget_disconnect - software-controlled disconnect from USB host
- * @gadget:the peripheral being disconnected
- *
- * Disables the D+ (or potentially D-) pullup, which the host may see
- * as a disconnect (when a VBUS session is active).  Not all systems
- * support software pullup controls.
- *
- * Following a successful disconnect, invoke the ->disconnect() callback
- * for the current gadget driver so that UDC drivers don't need to.
- *
- * Returns zero on success, else negative errno.
- */
-int usb_gadget_disconnect(struct usb_gadget *gadget)
-{
-       int ret;
-
-       mutex_lock(&gadget->udc->connect_lock);
-       ret = usb_gadget_disconnect_locked(gadget);
-       mutex_unlock(&gadget->udc->connect_lock);
-
-       return ret;
-}
 EXPORT_SYMBOL_GPL(usb_gadget_disconnect);
 
 /**
@@ -832,11 +794,10 @@ int usb_gadget_deactivate(struct usb_gadget *gadget)
        if (gadget->deactivated)
                goto out;
 
-       mutex_lock(&gadget->udc->connect_lock);
        if (gadget->connected) {
-               ret = usb_gadget_disconnect_locked(gadget);
+               ret = usb_gadget_disconnect(gadget);
                if (ret)
-                       goto unlock;
+                       goto out;
 
                /*
                 * If gadget was being connected before deactivation, we want
@@ -846,8 +807,6 @@ int usb_gadget_deactivate(struct usb_gadget *gadget)
        }
        gadget->deactivated = true;
 
-unlock:
-       mutex_unlock(&gadget->udc->connect_lock);
 out:
        trace_usb_gadget_deactivate(gadget, ret);
 
@@ -871,7 +830,6 @@ int usb_gadget_activate(struct usb_gadget *gadget)
        if (!gadget->deactivated)
                goto out;
 
-       mutex_lock(&gadget->udc->connect_lock);
        gadget->deactivated = false;
 
        /*
@@ -879,8 +837,7 @@ int usb_gadget_activate(struct usb_gadget *gadget)
         * while it was being deactivated, we call usb_gadget_connect().
         */
        if (gadget->connected)
-               ret = usb_gadget_connect_locked(gadget);
-       mutex_unlock(&gadget->udc->connect_lock);
+               ret = usb_gadget_connect(gadget);
 
 out:
        trace_usb_gadget_activate(gadget, ret);
@@ -1121,13 +1078,12 @@ EXPORT_SYMBOL_GPL(usb_gadget_set_state);
 
 /* ------------------------------------------------------------------------- */
 
-/* Acquire connect_lock before calling this function. */
-static void usb_udc_connect_control_locked(struct usb_udc *udc) __must_hold(&udc->connect_lock)
+static void usb_udc_connect_control(struct usb_udc *udc)
 {
-       if (udc->vbus && udc->started)
-               usb_gadget_connect_locked(udc->gadget);
+       if (udc->vbus)
+               usb_gadget_connect(udc->gadget);
        else
-               usb_gadget_disconnect_locked(udc->gadget);
+               usb_gadget_disconnect(udc->gadget);
 }
 
 /**
@@ -1143,12 +1099,10 @@ void usb_udc_vbus_handler(struct usb_gadget *gadget, bool status)
 {
        struct usb_udc *udc = gadget->udc;
 
-       mutex_lock(&udc->connect_lock);
        if (udc) {
                udc->vbus = status;
-               usb_udc_connect_control_locked(udc);
+               usb_udc_connect_control(udc);
        }
-       mutex_unlock(&udc->connect_lock);
 }
 EXPORT_SYMBOL_GPL(usb_udc_vbus_handler);
 
@@ -1170,7 +1124,7 @@ void usb_gadget_udc_reset(struct usb_gadget *gadget,
 EXPORT_SYMBOL_GPL(usb_gadget_udc_reset);
 
 /**
- * usb_gadget_udc_start_locked - tells usb device controller to start up
+ * usb_gadget_udc_start - tells usb device controller to start up
  * @udc: The UDC to be started
  *
  * This call is issued by the UDC Class driver when it's about
@@ -1181,11 +1135,8 @@ EXPORT_SYMBOL_GPL(usb_gadget_udc_reset);
  * necessary to have it powered on.
  *
  * Returns zero on success, else negative errno.
- *
- * Caller should acquire connect_lock before invoking this function.
  */
-static inline int usb_gadget_udc_start_locked(struct usb_udc *udc)
-       __must_hold(&udc->connect_lock)
+static inline int usb_gadget_udc_start(struct usb_udc *udc)
 {
        int ret;
 
@@ -1202,7 +1153,7 @@ static inline int usb_gadget_udc_start_locked(struct usb_udc *udc)
 }
 
 /**
- * usb_gadget_udc_stop_locked - tells usb device controller we don't need it anymore
+ * usb_gadget_udc_stop - tells usb device controller we don't need it anymore
  * @udc: The UDC to be stopped
  *
  * This call is issued by the UDC Class driver after calling
@@ -1211,11 +1162,8 @@ static inline int usb_gadget_udc_start_locked(struct usb_udc *udc)
  * The details are implementation specific, but it can go as
  * far as powering off UDC completely and disable its data
  * line pullups.
- *
- * Caller should acquire connect lock before invoking this function.
  */
-static inline void usb_gadget_udc_stop_locked(struct usb_udc *udc)
-       __must_hold(&udc->connect_lock)
+static inline void usb_gadget_udc_stop(struct usb_udc *udc)
 {
        if (!udc->started) {
                dev_err(&udc->dev, "UDC had already stopped\n");
@@ -1374,7 +1322,6 @@ int usb_add_gadget(struct usb_gadget *gadget)
 
        udc->gadget = gadget;
        gadget->udc = udc;
-       mutex_init(&udc->connect_lock);
 
        udc->started = false;
 
@@ -1576,15 +1523,11 @@ static int gadget_bind_driver(struct device *dev)
        if (ret)
                goto err_bind;
 
-       mutex_lock(&udc->connect_lock);
-       ret = usb_gadget_udc_start_locked(udc);
-       if (ret) {
-               mutex_unlock(&udc->connect_lock);
+       ret = usb_gadget_udc_start(udc);
+       if (ret)
                goto err_start;
-       }
        usb_gadget_enable_async_callbacks(udc);
-       usb_udc_connect_control_locked(udc);
-       mutex_unlock(&udc->connect_lock);
+       usb_udc_connect_control(udc);
 
        kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
        return 0;
@@ -1615,14 +1558,12 @@ static void gadget_unbind_driver(struct device *dev)
 
        kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
 
-       mutex_lock(&udc->connect_lock);
-       usb_gadget_disconnect_locked(gadget);
+       usb_gadget_disconnect(gadget);
        usb_gadget_disable_async_callbacks(udc);
        if (gadget->irq)
                synchronize_irq(gadget->irq);
        udc->driver->unbind(gadget);
-       usb_gadget_udc_stop_locked(udc);
-       mutex_unlock(&udc->connect_lock);
+       usb_gadget_udc_stop(udc);
 
        mutex_lock(&udc_lock);
        driver->is_bound = false;
@@ -1708,15 +1649,11 @@ static ssize_t soft_connect_store(struct device *dev,
        }
 
        if (sysfs_streq(buf, "connect")) {
-               mutex_lock(&udc->connect_lock);
-               usb_gadget_udc_start_locked(udc);
-               usb_gadget_connect_locked(udc->gadget);
-               mutex_unlock(&udc->connect_lock);
+               usb_gadget_udc_start(udc);
+               usb_gadget_connect(udc->gadget);
        } else if (sysfs_streq(buf, "disconnect")) {
-               mutex_lock(&udc->connect_lock);
-               usb_gadget_disconnect_locked(udc->gadget);
-               usb_gadget_udc_stop_locked(udc);
-               mutex_unlock(&udc->connect_lock);
+               usb_gadget_disconnect(udc->gadget);
+               usb_gadget_udc_stop(udc);
        } else {
                dev_err(dev, "unsupported command '%s'\n", buf);
                ret = -EINVAL;
index 3592f757fe05ddfbce622b7bf91b93cc76b30ce2..7bd2fddde770ae4a895dc2988bc1fda0e8d56a55 100644 (file)
@@ -119,11 +119,13 @@ static int uhci_pci_init(struct usb_hcd *hcd)
 
        uhci->rh_numports = uhci_count_ports(hcd);
 
-       /* Intel controllers report the OverCurrent bit active on.
-        * VIA controllers report it active off, so we'll adjust the
-        * bit value.  (It's not standardized in the UHCI spec.)
+       /*
+        * Intel controllers report the OverCurrent bit active on.  VIA
+        * and ZHAOXIN controllers report it active off, so we'll adjust
+        * the bit value.  (It's not standardized in the UHCI spec.)
         */
-       if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_VIA)
+       if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_VIA ||
+                       to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_ZHAOXIN)
                uhci->oc_low = 1;
 
        /* HP's server management chip requires a longer port reset delay. */
index ddb79f23fb3b7ce0a54b93f388e46db6508aecff..79b3691f373f34e8f4d325b1e9ae57949c23a54d 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/acpi.h>
 #include <linux/reset.h>
+#include <linux/suspend.h>
 
 #include "xhci.h"
 #include "xhci-trace.h"
@@ -387,7 +388,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
 
        if (pdev->vendor == PCI_VENDOR_ID_AMD &&
                pdev->device == PCI_DEVICE_ID_AMD_RENOIR_XHCI)
-               xhci->quirks |= XHCI_BROKEN_D3COLD;
+               xhci->quirks |= XHCI_BROKEN_D3COLD_S2I;
 
        if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
                xhci->quirks |= XHCI_LPM_SUPPORT;
@@ -801,9 +802,16 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
         * Systems with the TI redriver that loses port status change events
         * need to have the registers polled during D3, so avoid D3cold.
         */
-       if (xhci->quirks & (XHCI_COMP_MODE_QUIRK | XHCI_BROKEN_D3COLD))
+       if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
                pci_d3cold_disable(pdev);
 
+#ifdef CONFIG_SUSPEND
+       /* d3cold is broken, but only when s2idle is used */
+       if (pm_suspend_target_state == PM_SUSPEND_TO_IDLE &&
+           xhci->quirks & (XHCI_BROKEN_D3COLD_S2I))
+               pci_d3cold_disable(pdev);
+#endif
+
        if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
                xhci_pme_quirk(hcd);
 
index 1ad12d5a48572b15e3d877df43dd80cf480ccc00..2bc82b3a2f984c33e5d32b23336dce57acdf5a24 100644 (file)
@@ -276,6 +276,26 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
        trace_xhci_inc_enq(ring);
 }
 
+static int xhci_num_trbs_to(struct xhci_segment *start_seg, union xhci_trb *start,
+                           struct xhci_segment *end_seg, union xhci_trb *end,
+                           unsigned int num_segs)
+{
+       union xhci_trb *last_on_seg;
+       int num = 0;
+       int i = 0;
+
+       do {
+               if (start_seg == end_seg && end >= start)
+                       return num + (end - start);
+               last_on_seg = &start_seg->trbs[TRBS_PER_SEGMENT - 1];
+               num += last_on_seg - start;
+               start_seg = start_seg->next;
+               start = start_seg->trbs;
+       } while (i++ <= num_segs);
+
+       return -EINVAL;
+}
+
 /*
  * Check to see if there's room to enqueue num_trbs on the ring and make sure
  * enqueue pointer will not advance into dequeue segment. See rules above.
@@ -2140,6 +2160,7 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
                     u32 trb_comp_code)
 {
        struct xhci_ep_ctx *ep_ctx;
+       int trbs_freed;
 
        ep_ctx = xhci_get_ep_ctx(xhci, ep->vdev->out_ctx, ep->ep_index);
 
@@ -2209,9 +2230,15 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
        }
 
        /* Update ring dequeue pointer */
+       trbs_freed = xhci_num_trbs_to(ep_ring->deq_seg, ep_ring->dequeue,
+                                     td->last_trb_seg, td->last_trb,
+                                     ep_ring->num_segs);
+       if (trbs_freed < 0)
+               xhci_dbg(xhci, "Failed to count freed trbs at TD finish\n");
+       else
+               ep_ring->num_trbs_free += trbs_freed;
        ep_ring->dequeue = td->last_trb;
        ep_ring->deq_seg = td->last_trb_seg;
-       ep_ring->num_trbs_free += td->num_trbs - 1;
        inc_deq(xhci, ep_ring);
 
        return xhci_td_cleanup(xhci, td, ep_ring, td->status);
index 08d721921b7bb22606d82cea5b4736208beb0a9c..6b690ec91ff3ae1044905657dd1f2f0f0f749d80 100644 (file)
@@ -1901,7 +1901,7 @@ struct xhci_hcd {
 #define XHCI_DISABLE_SPARSE    BIT_ULL(38)
 #define XHCI_SG_TRB_CACHE_SIZE_QUIRK   BIT_ULL(39)
 #define XHCI_NO_SOFT_RETRY     BIT_ULL(40)
-#define XHCI_BROKEN_D3COLD     BIT_ULL(41)
+#define XHCI_BROKEN_D3COLD_S2I BIT_ULL(41)
 #define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42)
 #define XHCI_SUSPEND_RESUME_CLKS       BIT_ULL(43)
 #define XHCI_RESET_TO_DEFAULT  BIT_ULL(44)
index 8931df5a85fd9e49de0e8b8f399771405168ed06..c54e9805da536a0ec139ad789017b79131c88561 100644 (file)
@@ -406,22 +406,25 @@ static DEF_SCSI_QCMD(queuecommand)
  ***********************************************************************/
 
 /* Command timeout and abort */
-static int command_abort(struct scsi_cmnd *srb)
+static int command_abort_matching(struct us_data *us, struct scsi_cmnd *srb_match)
 {
-       struct us_data *us = host_to_us(srb->device->host);
-
-       usb_stor_dbg(us, "%s called\n", __func__);
-
        /*
         * us->srb together with the TIMED_OUT, RESETTING, and ABORTING
         * bits are protected by the host lock.
         */
        scsi_lock(us_to_host(us));
 
-       /* Is this command still active? */
-       if (us->srb != srb) {
+       /* is there any active pending command to abort ? */
+       if (!us->srb) {
                scsi_unlock(us_to_host(us));
                usb_stor_dbg(us, "-- nothing to abort\n");
+               return SUCCESS;
+       }
+
+       /* Does the command match the passed srb if any ? */
+       if (srb_match && us->srb != srb_match) {
+               scsi_unlock(us_to_host(us));
+               usb_stor_dbg(us, "-- pending command mismatch\n");
                return FAILED;
        }
 
@@ -444,6 +447,14 @@ static int command_abort(struct scsi_cmnd *srb)
        return SUCCESS;
 }
 
+static int command_abort(struct scsi_cmnd *srb)
+{
+       struct us_data *us = host_to_us(srb->device->host);
+
+       usb_stor_dbg(us, "%s called\n", __func__);
+       return command_abort_matching(us, srb);
+}
+
 /*
  * This invokes the transport reset mechanism to reset the state of the
  * device
@@ -455,6 +466,9 @@ static int device_reset(struct scsi_cmnd *srb)
 
        usb_stor_dbg(us, "%s called\n", __func__);
 
+       /* abort any pending command before reset */
+       command_abort_matching(us, NULL);
+
        /* lock the device pointers and do the reset */
        mutex_lock(&(us->dev_mutex));
        result = us->transport_reset(us);
index 8f3e884222adef512a424e16623ad3cad8565143..66de880b28d01a60d592a490d820aa78f87a9aa0 100644 (file)
@@ -516,6 +516,10 @@ static ssize_t pin_assignment_show(struct device *dev,
 
        mutex_unlock(&dp->lock);
 
+       /* get_current_pin_assignments can return 0 when no matching pin assignments are found */
+       if (len == 0)
+               len++;
+
        buf[len - 1] = '\n';
        return len;
 }
index 8b075ca82ef6de80b4b6f31fa316b675141705c3..603dbd44deba9aaab55ad671526a6bf14befd339 100644 (file)
@@ -886,6 +886,9 @@ static void tps6598x_remove(struct i2c_client *client)
 {
        struct tps6598x *tps = i2c_get_clientdata(client);
 
+       if (!client->irq)
+               cancel_delayed_work_sync(&tps->wq_poll);
+
        tps6598x_disconnect(tps, 0);
        typec_unregister_port(tps->port);
        usb_role_switch_put(tps->role_sw);
@@ -917,7 +920,7 @@ static int __maybe_unused tps6598x_resume(struct device *dev)
                enable_irq(client->irq);
        }
 
-       if (client->irq)
+       if (!client->irq)
                queue_delayed_work(system_power_efficient_wq, &tps->wq_poll,
                                   msecs_to_jiffies(POLL_INTERVAL));
 
index 3d4dd9420c30701453be9323a0e3e46bfbf58755..0d2f805468e190c37b5e79527f864d13a42d311e 100644 (file)
@@ -860,6 +860,11 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data,
                if (ret)
                        goto pin_unwind;
 
+               if (!pfn_valid(phys_pfn)) {
+                       ret = -EINVAL;
+                       goto pin_unwind;
+               }
+
                ret = vfio_add_to_pfn_list(dma, iova, phys_pfn);
                if (ret) {
                        if (put_pfn(phys_pfn, dma->prot) && do_accounting)
index a92af08e786450640b2bb6fa848810dec402fcbb..07427302084955331ae62a0892b9516f089b9daf 100644 (file)
@@ -256,7 +256,7 @@ void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work)
                 * test_and_set_bit() implies a memory barrier.
                 */
                llist_add(&work->node, &dev->worker->work_list);
-               wake_up_process(dev->worker->vtsk->task);
+               vhost_task_wake(dev->worker->vtsk);
        }
 }
 EXPORT_SYMBOL_GPL(vhost_work_queue);
@@ -333,31 +333,19 @@ static void vhost_vq_reset(struct vhost_dev *dev,
        __vhost_vq_meta_reset(vq);
 }
 
-static int vhost_worker(void *data)
+static bool vhost_worker(void *data)
 {
        struct vhost_worker *worker = data;
        struct vhost_work *work, *work_next;
        struct llist_node *node;
 
-       for (;;) {
-               /* mb paired w/ kthread_stop */
-               set_current_state(TASK_INTERRUPTIBLE);
-
-               if (vhost_task_should_stop(worker->vtsk)) {
-                       __set_current_state(TASK_RUNNING);
-                       break;
-               }
-
-               node = llist_del_all(&worker->work_list);
-               if (!node)
-                       schedule();
-
+       node = llist_del_all(&worker->work_list);
+       if (node) {
                node = llist_reverse_order(node);
                /* make sure flag is seen after deletion */
                smp_wmb();
                llist_for_each_entry_safe(work, work_next, node, node) {
                        clear_bit(VHOST_WORK_QUEUED, &work->flags);
-                       __set_current_state(TASK_RUNNING);
                        kcov_remote_start_common(worker->kcov_handle);
                        work->fn(work);
                        kcov_remote_stop();
@@ -365,7 +353,7 @@ static int vhost_worker(void *data)
                }
        }
 
-       return 0;
+       return !!node;
 }
 
 static void vhost_vq_free_iovecs(struct vhost_virtqueue *vq)
index 3ccf46f8ffd017cd4b6eb58305a25d41d8a72da4..07d6e8dc686bb483c9dc16a4e012db15bcc72c6c 100644 (file)
@@ -124,7 +124,7 @@ static u_long get_line_length(int xres_virtual, int bpp)
      *  First part, xxxfb_check_var, must not write anything
      *  to hardware, it should only verify and adjust var.
      *  This means it doesn't alter par but it does use hardware
-     *  data from it to check this var. 
+     *  data from it to check this var.
      */
 
 static int mc68x328fb_check_var(struct fb_var_screeninfo *var,
@@ -182,7 +182,7 @@ static int mc68x328fb_check_var(struct fb_var_screeninfo *var,
 
        /*
         * Now that we checked it we alter var. The reason being is that the video
-        * mode passed in might not work but slight changes to it might make it 
+        * mode passed in might not work but slight changes to it might make it
         * work. This way we let the user know what is acceptable.
         */
        switch (var->bits_per_pixel) {
@@ -257,8 +257,8 @@ static int mc68x328fb_check_var(struct fb_var_screeninfo *var,
 }
 
 /* This routine actually sets the video mode. It's in here where we
- * the hardware state info->par and fix which can be affected by the 
- * change in par. For this driver it doesn't do much. 
+ * the hardware state info->par and fix which can be affected by the
+ * change in par. For this driver it doesn't do much.
  */
 static int mc68x328fb_set_par(struct fb_info *info)
 {
@@ -295,7 +295,7 @@ static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
         *   {hardwarespecific} contains width of RAMDAC
         *   cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
         *   RAMDAC[X] is programmed to (red, green, blue)
-        * 
+        *
         * Pseudocolor:
         *    uses offset = 0 && length = RAMDAC register width.
         *    var->{color}.offset is 0
@@ -384,7 +384,7 @@ static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
 }
 
     /*
-     *  Most drivers don't need their own mmap function 
+     *  Most drivers don't need their own mmap function
      */
 
 static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
index 96e91570cdd3294041c79b25edb62df08331538c..0fdf5f46802c7f508e3025ce292bd1c3a620913c 100644 (file)
@@ -124,7 +124,7 @@ config FB_PROVIDE_GET_FB_UNMAPPED_AREA
        depends on FB
        help
          Allow generic frame-buffer to provide get_fb_unmapped_area
-         function.
+         function to provide shareable character device support on nommu.
 
 menuconfig FB_FOREIGN_ENDIAN
        bool "Framebuffer foreign endianness support"
index 45e64016db3280e82b6aac086a981cb4ebe29c67..08d15e4084130ed2d020194137b62cb058dcf8d2 100644 (file)
@@ -523,7 +523,7 @@ static int arcfb_probe(struct platform_device *dev)
 
        info = framebuffer_alloc(sizeof(struct arcfb_par), &dev->dev);
        if (!info)
-               goto err;
+               goto err_fb_alloc;
 
        info->screen_base = (char __iomem *)videomemory;
        info->fbops = &arcfb_ops;
@@ -535,7 +535,7 @@ static int arcfb_probe(struct platform_device *dev)
 
        if (!dio_addr || !cio_addr || !c2io_addr) {
                printk(KERN_WARNING "no IO addresses supplied\n");
-               goto err1;
+               goto err_addr;
        }
        par->dio_addr = dio_addr;
        par->cio_addr = cio_addr;
@@ -551,12 +551,12 @@ static int arcfb_probe(struct platform_device *dev)
                        printk(KERN_INFO
                                "arcfb: Failed req IRQ %d\n", par->irq);
                        retval = -EBUSY;
-                       goto err1;
+                       goto err_addr;
                }
        }
        retval = register_framebuffer(info);
        if (retval < 0)
-               goto err1;
+               goto err_register_fb;
        platform_set_drvdata(dev, info);
        fb_info(info, "Arc frame buffer device, using %dK of video memory\n",
                videomemorysize >> 10);
@@ -580,14 +580,17 @@ static int arcfb_probe(struct platform_device *dev)
        }
 
        return 0;
-err1:
+
+err_register_fb:
+       free_irq(par->irq, info);
+err_addr:
        framebuffer_release(info);
-err:
+err_fb_alloc:
        vfree(videomemory);
        return retval;
 }
 
-static int arcfb_remove(struct platform_device *dev)
+static void arcfb_remove(struct platform_device *dev)
 {
        struct fb_info *info = platform_get_drvdata(dev);
 
@@ -598,12 +601,11 @@ static int arcfb_remove(struct platform_device *dev)
                vfree((void __force *)info->screen_base);
                framebuffer_release(info);
        }
-       return 0;
 }
 
 static struct platform_driver arcfb_driver = {
        .probe  = arcfb_probe,
-       .remove = arcfb_remove,
+       .remove_new = arcfb_remove,
        .driver = {
                .name   = "arcfb",
        },
index 8187a7c4f9106b05f907da0d75e0394bbd3b54c4..987c5f5f02414be9f9c7e24916e6d7ea27bd4f8a 100644 (file)
@@ -317,7 +317,7 @@ static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
 /**
  *     atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory
  *     @sinfo: the frame buffer to allocate memory for
- *     
+ *
  *     This function is called only from the atmel_lcdfb_probe()
  *     so no locking by fb_info->mm_lock around smem_len setting is needed.
  */
index b02e4e645035c44716740805bc3ffdb666d12c0d..cba2b113b28b0533418e017e8658138c97d21fd7 100644 (file)
@@ -3498,11 +3498,6 @@ static int atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info,
        if (ret)
                goto atyfb_setup_generic_fail;
 #endif
-       if (!(aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_EXT_DISP_EN))
-               par->clk_wr_offset = (inb(R_GENMO) & 0x0CU) >> 2;
-       else
-               par->clk_wr_offset = aty_ld_8(CLOCK_CNTL, par) & 0x03U;
-
        /* according to ATI, we should use clock 3 for acelerated mode */
        par->clk_wr_offset = 3;
 
index 519313b8bb004fa245def79b0e74525a4e2edd42..648d6cac86e8fb1386c459d05852f6f603c00fd7 100644 (file)
@@ -520,13 +520,10 @@ failed:
        return -ENODEV;
 }
 
-int au1100fb_drv_remove(struct platform_device *dev)
+void au1100fb_drv_remove(struct platform_device *dev)
 {
        struct au1100fb_device *fbdev = NULL;
 
-       if (!dev)
-               return -ENODEV;
-
        fbdev = platform_get_drvdata(dev);
 
 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
@@ -543,8 +540,6 @@ int au1100fb_drv_remove(struct platform_device *dev)
                clk_disable_unprepare(fbdev->lcdclk);
                clk_put(fbdev->lcdclk);
        }
-
-       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -593,9 +588,9 @@ static struct platform_driver au1100fb_driver = {
                .name           = "au1100-lcd",
        },
        .probe          = au1100fb_drv_probe,
-        .remove                = au1100fb_drv_remove,
+       .remove_new     = au1100fb_drv_remove,
        .suspend        = au1100fb_drv_suspend,
-        .resume                = au1100fb_drv_resume,
+       .resume         = au1100fb_drv_resume,
 };
 module_platform_driver(au1100fb_driver);
 
index b6b22fa4a8a01360095c3549dc63800f6dd0ddf9..aed88ce45bf091d6990c5242369f959c5b2bb2a0 100644 (file)
@@ -1765,7 +1765,7 @@ failed:
        return ret;
 }
 
-static int au1200fb_drv_remove(struct platform_device *dev)
+static void au1200fb_drv_remove(struct platform_device *dev)
 {
        struct au1200fb_platdata *pd = platform_get_drvdata(dev);
        struct fb_info *fbi;
@@ -1788,8 +1788,6 @@ static int au1200fb_drv_remove(struct platform_device *dev)
        }
 
        free_irq(platform_get_irq(dev, 0), (void *)dev);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -1840,7 +1838,7 @@ static struct platform_driver au1200fb_driver = {
                .pm     = AU1200FB_PMOPS,
        },
        .probe          = au1200fb_drv_probe,
-       .remove         = au1200fb_drv_remove,
+       .remove_new     = au1200fb_drv_remove,
 };
 module_platform_driver(au1200fb_driver);
 
index 55e62dd96f9bef0ee3f6ff7915517feac9a6e6cf..b518cacbf7cd9edb2d8d51d290047d267a76e528 100644 (file)
@@ -1193,7 +1193,7 @@ err:
 
 }
 
-static int broadsheetfb_remove(struct platform_device *dev)
+static void broadsheetfb_remove(struct platform_device *dev)
 {
        struct fb_info *info = platform_get_drvdata(dev);
 
@@ -1209,12 +1209,11 @@ static int broadsheetfb_remove(struct platform_device *dev)
                module_put(par->board->owner);
                framebuffer_release(info);
        }
-       return 0;
 }
 
 static struct platform_driver broadsheetfb_driver = {
        .probe  = broadsheetfb_probe,
-       .remove = broadsheetfb_remove,
+       .remove_new = broadsheetfb_remove,
        .driver = {
                .name   = "broadsheetfb",
        },
index 9cbadcd18b256c4ff0e525f7d09867d377d1028f..025d663dc6fdcae85bc10e8e1813cd5305ca97e5 100644 (file)
@@ -352,7 +352,7 @@ out_err:
        return err;
 }
 
-static int bw2_remove(struct platform_device *op)
+static void bw2_remove(struct platform_device *op)
 {
        struct fb_info *info = dev_get_drvdata(&op->dev);
        struct bw2_par *par = info->par;
@@ -363,8 +363,6 @@ static int bw2_remove(struct platform_device *op)
        of_iounmap(&op->resource[0], info->screen_base, info->fix.smem_len);
 
        framebuffer_release(info);
-
-       return 0;
 }
 
 static const struct of_device_id bw2_match[] = {
@@ -381,7 +379,7 @@ static struct platform_driver bw2_driver = {
                .of_match_table = bw2_match,
        },
        .probe          = bw2_probe,
-       .remove         = bw2_remove,
+       .remove_new     = bw2_remove,
 };
 
 static int __init bw2_init(void)
index a028ede39c12246c6bcda91a2fe23e8ebcf519fb..832a82f45c8096468babc2e0e29d24a081c7f025 100644 (file)
@@ -512,7 +512,7 @@ static int cg14_probe(struct platform_device *op)
        is_8mb = (resource_size(&op->resource[1]) == (8 * 1024 * 1024));
 
        BUILD_BUG_ON(sizeof(par->mmap_map) != sizeof(__cg14_mmap_map));
-               
+
        memcpy(&par->mmap_map, &__cg14_mmap_map, sizeof(par->mmap_map));
 
        for (i = 0; i < CG14_MMAP_ENTRIES; i++) {
index 77dbf94aae5f4fdacf5e340fb89453b6b71dba82..82eeb139c4ebb121a8805857965c9ced6c6b7fd6 100644 (file)
@@ -113,14 +113,14 @@ struct fb_info_control {
        struct fb_info          info;
        struct fb_par_control   par;
        u32                     pseudo_palette[16];
-               
+
        struct cmap_regs        __iomem *cmap_regs;
        unsigned long           cmap_regs_phys;
-       
+
        struct control_regs     __iomem *control_regs;
        unsigned long           control_regs_phys;
        unsigned long           control_regs_size;
-       
+
        __u8                    __iomem *frame_buffer;
        unsigned long           frame_buffer_phys;
        unsigned long           fb_orig_base;
@@ -196,7 +196,7 @@ static void set_control_clock(unsigned char *params)
                while (!req.complete)
                        cuda_poll();
        }
-#endif 
+#endif
 }
 
 /*
@@ -233,19 +233,19 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro
                if (p->par.xoffset != par->xoffset ||
                    p->par.yoffset != par->yoffset)
                        set_screen_start(par->xoffset, par->yoffset, p);
-                       
+
                return;
        }
-       
+
        p->par = *par;
        cmode = p->par.cmode;
        r = &par->regvals;
-       
+
        /* Turn off display */
        out_le32(CNTRL_REG(p,ctrl), 0x400 | par->ctrl);
-       
+
        set_control_clock(r->clock_params);
-       
+
        RADACAL_WRITE(0x20, r->radacal_ctrl);
        RADACAL_WRITE(0x21, p->control_use_bank2 ? 0 : 1);
        RADACAL_WRITE(0x10, 0);
@@ -254,7 +254,7 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro
        rp = &p->control_regs->vswin;
        for (i = 0; i < 16; ++i, ++rp)
                out_le32(&rp->r, r->regs[i]);
-       
+
        out_le32(CNTRL_REG(p,pitch), par->pitch);
        out_le32(CNTRL_REG(p,mode), r->mode);
        out_le32(CNTRL_REG(p,vram_attr), p->vram_attr);
@@ -366,7 +366,7 @@ static int read_control_sense(struct fb_info_control *p)
        sense |= (in_le32(CNTRL_REG(p,mon_sense)) & 0x180) >> 7;
 
        out_le32(CNTRL_REG(p,mon_sense), 077);  /* turn off drivers */
-       
+
        return sense;
 }
 
@@ -558,9 +558,9 @@ static int control_var_to_par(struct fb_var_screeninfo *var,
 static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var)
 {
        struct control_regints *rv;
-       
+
        rv = (struct control_regints *) par->regvals.regs;
-       
+
        memset(var, 0, sizeof(*var));
        var->xres = par->xres;
        var->yres = par->yres;
@@ -568,7 +568,7 @@ static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeni
        var->yres_virtual = par->vyres;
        var->xoffset = par->xoffset;
        var->yoffset = par->yoffset;
-       
+
        switch(par->cmode) {
        default:
        case CMODE_8:
@@ -634,7 +634,7 @@ static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *i
 
        err = control_var_to_par(var, &par, info);
        if (err)
-               return err;     
+               return err;
        control_par_to_var(&par, var);
 
        return 0;
@@ -655,7 +655,7 @@ static int controlfb_set_par (struct fb_info *info)
                                 " control_var_to_par: %d.\n", err);
                return err;
        }
-       
+
        control_set_hardware(p, &par);
 
        info->fix.visual = (p->par.cmode == CMODE_8) ?
@@ -840,7 +840,7 @@ static int __init init_control(struct fb_info_control *p)
        int full, sense, vmode, cmode, vyres;
        struct fb_var_screeninfo var;
        int rc;
-       
+
        printk(KERN_INFO "controlfb: ");
 
        full = p->total_vram == 0x400000;
index f98e8f298bc19a0ae63a8d493ae2e316d8e2e38a..8587c9da067003f74f50d3234a759bf3f218bf12 100644 (file)
@@ -247,6 +247,9 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
 
        cursor.set = 0;
 
+       if (!vc->vc_font.data)
+               return;
+
        c = scr_readw((u16 *) vc->vc_pos);
        attribute = get_attribute(info, c);
        src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
index e808dc86001cc98ca449cdecb63fe891d8579671..28739f1cb5e7a1da84e65b66850984ba4dc4c6be 100644 (file)
@@ -1468,7 +1468,7 @@ __releases(&info->lock)
 }
 
 #if defined(CONFIG_FB_PROVIDE_GET_FB_UNMAPPED_AREA) && !defined(CONFIG_MMU)
-unsigned long get_fb_unmapped_area(struct file *filp,
+static unsigned long get_fb_unmapped_area(struct file *filp,
                                   unsigned long addr, unsigned long len,
                                   unsigned long pgoff, unsigned long flags)
 {
index 23cf8eba785d42c720600e86e18746b212f470ae..f7e019dded0fb92d51fe9872714da056fd5edb85 100644 (file)
@@ -257,6 +257,11 @@ static const struct fb_videomode modedb[] = {
        { NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, 0,
                FB_VMODE_DOUBLE },
 
+       /* 1920x1080 @ 60 Hz, 67.3 kHz hsync */
+       { NULL, 60, 1920, 1080, 6734, 148, 88, 36, 4, 44, 5, 0,
+               FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               FB_VMODE_NONINTERLACED },
+
        /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */
        { NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3,
                FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
index 05837a3b985c7f0f668bd18d0d5f7e174dbb619b..c5b7673ddc6caf04f4e46ae0d2dc38f37c01fdb8 100644 (file)
@@ -6,7 +6,7 @@
  *
  *  This driver is based on tgafb.c
  *
- *     Copyright (C) 1997 Geert Uytterhoeven 
+ *     Copyright (C) 1997 Geert Uytterhoeven
  *     Copyright (C) 1995  Jay Estabrook
  *
  *  This file is subject to the terms and conditions of the GNU General Public
@@ -28,7 +28,7 @@
 #include <asm/io.h>
 #include <asm/jazz.h>
 
-/* 
+/*
  * Various defines for the G364
  */
 #define G364_MEM_BASE   0xe4400000
@@ -125,7 +125,7 @@ static const struct fb_ops g364fb_ops = {
  *
  *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
  */
-static int g364fb_pan_display(struct fb_var_screeninfo *var, 
+static int g364fb_pan_display(struct fb_var_screeninfo *var,
                              struct fb_info *info)
 {
        if (var->xoffset ||
index 20bdab738ab7a71d435cf19f7fd862cc5252d5d5..0af58018441d30aa0dc893be291848c6b1b07019 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * linux/drivers/video/hgafb.c -- Hercules graphics adaptor frame buffer device
- * 
+ *
  *      Created 25 Nov 1999 by Ferenc Bakonyi (fero@drama.obuda.kando.hu)
  *      Based on skeletonfb.c by Geert Uytterhoeven and
  *               mdacon.c by Andrew Apted
@@ -8,14 +8,14 @@
  * History:
  *
  * - Revision 0.1.8 (23 Oct 2002): Ported to new framebuffer api.
- * 
- * - Revision 0.1.7 (23 Jan 2001): fix crash resulting from MDA only cards 
+ *
+ * - Revision 0.1.7 (23 Jan 2001): fix crash resulting from MDA only cards
  *                                being detected as Hercules.   (Paul G.)
  * - Revision 0.1.6 (17 Aug 2000): new style structs
  *                                 documentation
  * - Revision 0.1.5 (13 Mar 2000): spinlocks instead of saveflags();cli();etc
  *                                 minor fixes
- * - Revision 0.1.4 (24 Jan 2000): fixed a bug in hga_card_detect() for 
+ * - Revision 0.1.4 (24 Jan 2000): fixed a bug in hga_card_detect() for
  *                                  HGA-only systems
  * - Revision 0.1.3 (22 Jan 2000): modified for the new fb_info structure
  *                                 screen is cleared after rmmod
@@ -143,7 +143,7 @@ static bool nologo = 0;
 
 static void write_hga_b(unsigned int val, unsigned char reg)
 {
-       outb_p(reg, HGA_INDEX_PORT); 
+       outb_p(reg, HGA_INDEX_PORT);
        outb_p(val, HGA_VALUE_PORT);
 }
 
@@ -155,7 +155,7 @@ static void write_hga_w(unsigned int val, unsigned char reg)
 
 static int test_hga_b(unsigned char val, unsigned char reg)
 {
-       outb_p(reg, HGA_INDEX_PORT); 
+       outb_p(reg, HGA_INDEX_PORT);
        outb  (val, HGA_VALUE_PORT);
        udelay(20); val = (inb_p(HGA_VALUE_PORT) == val);
        return val;
@@ -244,7 +244,7 @@ static void hga_show_logo(struct fb_info *info)
        void __iomem *dest = hga_vram;
        char *logo = linux_logo_bw;
        int x, y;
-       
+
        for (y = 134; y < 134 + 80 ; y++) * this needs some cleanup *
                for (x = 0; x < 10 ; x++)
                        writeb(~*(logo++),(dest + HGA_ROWADDR(y) + x + 40));
@@ -255,7 +255,7 @@ static void hga_pan(unsigned int xoffset, unsigned int yoffset)
 {
        unsigned int base;
        unsigned long flags;
-       
+
        base = (yoffset / 8) * 90 + xoffset;
        spin_lock_irqsave(&hga_reg_lock, flags);
        write_hga_w(base, 0x0c);        /* start address */
@@ -310,7 +310,7 @@ static int hga_card_detect(void)
        /* Ok, there is definitely a card registering at the correct
         * memory location, so now we do an I/O port test.
         */
-       
+
        if (!test_hga_b(0x66, 0x0f))        /* cursor low register */
                goto error;
 
@@ -321,7 +321,7 @@ static int hga_card_detect(void)
         * bit of the status register is changing.  This test lasts for
         * approximately 1/10th of a second.
         */
-       
+
        p_save = q_save = inb_p(HGA_STATUS_PORT) & HGA_STATUS_VSYNC;
 
        for (count=0; count < 50000 && p_save == q_save; count++) {
@@ -329,7 +329,7 @@ static int hga_card_detect(void)
                udelay(2);
        }
 
-       if (p_save == q_save) 
+       if (p_save == q_save)
                goto error;
 
        switch (inb_p(HGA_STATUS_PORT) & 0x70) {
@@ -415,7 +415,7 @@ static int hgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  *     @info:pointer to fb_info object containing info for current hga board
  *
  *     This function looks only at xoffset, yoffset and the %FB_VMODE_YWRAP
- *     flag in @var. If input parameters are correct it calls hga_pan() to 
+ *     flag in @var. If input parameters are correct it calls hga_pan() to
  *     program the hardware. @info->var is updated to the new values.
  *     A zero is returned on success and %-EINVAL for failure.
  */
@@ -442,9 +442,9 @@ static int hgafb_pan_display(struct fb_var_screeninfo *var,
  *     hgafb_blank - (un)blank the screen
  *     @blank_mode:blanking method to use
  *     @info:unused
- *     
- *     Blank the screen if blank_mode != 0, else unblank. 
- *     Implements VESA suspend and powerdown modes on hardware that supports 
+ *
+ *     Blank the screen if blank_mode != 0, else unblank.
+ *     Implements VESA suspend and powerdown modes on hardware that supports
  *     disabling hsync/vsync:
  *             @blank_mode == 2 means suspend vsync,
  *             @blank_mode == 3 means suspend hsync,
@@ -539,15 +539,15 @@ static const struct fb_ops hgafb_ops = {
        .fb_copyarea    = hgafb_copyarea,
        .fb_imageblit   = hgafb_imageblit,
 };
-               
+
 /* ------------------------------------------------------------------------- *
  *
  * Functions in fb_info
- * 
+ *
  * ------------------------------------------------------------------------- */
 
 /* ------------------------------------------------------------------------- */
-    
+
        /*
         *  Initialization
         */
index cdd44e5deafe4d9114a2a5f174ed2cd06474730f..77fbff47b1a8ed11c1dcd717a7745cad664b466a 100644 (file)
@@ -92,7 +92,7 @@ static int hpfb_setcolreg(unsigned regno, unsigned red, unsigned green,
 
        if (regno >= info->cmap.len)
                return 1;
-       
+
        while (in_be16(fb_regs + 0x6002) & 0x4) udelay(1);
 
        out_be16(fb_regs + 0x60ba, 0xff);
@@ -143,7 +143,7 @@ static void topcat_blit(int x0, int y0, int x1, int y1, int w, int h, int rr)
        out_8(fb_regs + WMOVE, fb_bitmask);
 }
 
-static void hpfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 
+static void hpfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
        topcat_blit(area->sx, area->sy, area->dx, area->dy, area->width, area->height, RR_COPY);
 }
@@ -315,7 +315,7 @@ unmap_screen_base:
        return ret;
 }
 
-/* 
+/*
  * Check that the secondary ID indicates that we have some hope of working with this
  * framebuffer.  The catseye boards are pretty much like topcats and we can muddle through.
  */
@@ -323,7 +323,7 @@ unmap_screen_base:
 #define topcat_sid_ok(x)  (((x) == DIO_ID2_LRCATSEYE) || ((x) == DIO_ID2_HRCCATSEYE)    \
                           || ((x) == DIO_ID2_HRMCATSEYE) || ((x) == DIO_ID2_TOPCAT))
 
-/* 
+/*
  * Initialise the framebuffer
  */
 static int hpfb_dio_probe(struct dio_dev *d, const struct dio_device_id *ent)
index b4b3670667ab8ce42dce3d58cc2d65be02d72eaa..2082b5c92e8f3b9f72deff934b6fc4b8a958e8fc 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "i810_regs.h"
 #include "i810.h"
+#include "i810_main.h"
 
 struct mode_registers std_modes[] = {
        /* 640x480 @ 60Hz */
@@ -276,7 +277,7 @@ void i810fb_fill_var_timings(struct fb_var_screeninfo *var)
        var->upper_margin = total - (yres + var->lower_margin + var->vsync_len);
 }
 
-u32 i810_get_watermark(struct fb_var_screeninfo *var,
+u32 i810_get_watermark(const struct fb_var_screeninfo *var,
                       struct i810fb_par *par)
 {
        struct mode_registers *params = &par->regs;
index bea45647184e1539d13015ed06680725752386cb..ee7d01ad14068687b968a42f1558ed730664e47b 100644 (file)
@@ -1347,7 +1347,7 @@ static const struct fb_ops imsttfb_ops = {
        .fb_ioctl       = imsttfb_ioctl,
 };
 
-static void init_imstt(struct fb_info *info)
+static int init_imstt(struct fb_info *info)
 {
        struct imstt_par *par = info->par;
        __u32 i, tmp, *ip, *end;
@@ -1420,7 +1420,7 @@ static void init_imstt(struct fb_info *info)
            || !(compute_imstt_regvals(par, info->var.xres, info->var.yres))) {
                printk("imsttfb: %ux%ux%u not supported\n", info->var.xres, info->var.yres, info->var.bits_per_pixel);
                framebuffer_release(info);
-               return;
+               return -ENODEV;
        }
 
        sprintf(info->fix.id, "IMS TT (%s)", par->ramdac == IBM ? "IBM" : "TVP");
@@ -1452,16 +1452,21 @@ static void init_imstt(struct fb_info *info)
                      FBINFO_HWACCEL_FILLRECT |
                      FBINFO_HWACCEL_YPAN;
 
-       fb_alloc_cmap(&info->cmap, 0, 0);
+       if (fb_alloc_cmap(&info->cmap, 0, 0)) {
+               framebuffer_release(info);
+               return -ENODEV;
+       }
 
        if (register_framebuffer(info) < 0) {
+               fb_dealloc_cmap(&info->cmap);
                framebuffer_release(info);
-               return;
+               return -ENODEV;
        }
 
        tmp = (read_reg_le32(par->dc_regs, SSTATUS) & 0x0f00) >> 8;
        fb_info(info, "%s frame buffer; %uMB vram; chip version %u\n",
                info->fix.id, info->fix.smem_len >> 20, tmp);
+       return 0;
 }
 
 static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -1529,10 +1534,12 @@ static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (!par->cmap_regs)
                goto error;
        info->pseudo_palette = par->palette;
-       init_imstt(info);
+       ret = init_imstt(info);
+       if (ret)
+               goto error;
 
        pci_set_drvdata(pdev, info);
-       return 0;
+       return ret;
 
 error:
        if (par->dc_regs)
index 312e35c9aa6c5dec351cd3357d7a9b0bbd1959ec..44ff860a3f3783210d0b54f1444e0aa4e0f8dd05 100644 (file)
@@ -339,7 +339,7 @@ static int civic_setpalette(unsigned int regno, unsigned int red,
 {
        unsigned long flags;
        int clut_status;
-       
+
        local_irq_save(flags);
 
        /* Set the register address */
@@ -439,7 +439,7 @@ static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green,
         * (according to the entries in the `var' structure).
         * Return non-zero for invalid regno.
         */
-       
+
        if (regno >= fb_info->cmap.len)
                return 1;
 
@@ -548,7 +548,7 @@ static int __init macfb_init(void)
                return -ENODEV;
        macfb_setup(option);
 
-       if (!MACH_IS_MAC) 
+       if (!MACH_IS_MAC)
                return -ENODEV;
 
        if (mac_bi_data.id == MAC_MODEL_Q630 ||
@@ -644,7 +644,7 @@ static int __init macfb_init(void)
                err = -EINVAL;
                goto fail_unmap;
        }
-       
+
        /*
         * We take a wild guess that if the video physical address is
         * in nubus slot space, that the nubus card is driving video.
@@ -774,7 +774,7 @@ static int __init macfb_init(void)
                        civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
                        break;
 
-               
+
                /*
                 * Assorted weirdos
                 * We think this may be like the LC II
index 727a10a59811b38d701f12159ce5201ee8d18bea..b15a8ad92ba704e234e7e16874897dffb2427cf7 100644 (file)
@@ -1291,7 +1291,7 @@ static struct i2c_driver maven_driver={
        .driver = {
                .name   = "maven",
        },
-       .probe_new      = maven_probe,
+       .probe          = maven_probe,
        .remove         = maven_remove,
        .id_table       = maven_id,
 };
index ae1a42bcb0ead38c25788c0f4ef767ea64cb57b0..4e6b05232ae2238159734e8d956a832ddd101442 100644 (file)
@@ -138,7 +138,7 @@ int __init maxinefb_init(void)
                *(volatile unsigned char *)fboff = 0x0;
 
        maxinefb_fix.smem_start = fb_start;
-       
+
        /* erase hardware cursor */
        for (i = 0; i < 512; i++) {
                maxinefb_ims332_write_register(IMS332_REG_CURSOR_RAM + i,
index 1eaa35c278359836ebd4860af036b42fce2d010b..477789cff8e08d5e620a0754feb1f1dba6008370 100644 (file)
@@ -491,7 +491,8 @@ static int tpo_td043_probe(struct spi_device *spi)
 
        ddata->vcc_reg = devm_regulator_get(&spi->dev, "vcc");
        if (IS_ERR(ddata->vcc_reg)) {
-               r = dev_err_probe(&spi->dev, r, "failed to get LCD VCC regulator\n");
+               r = dev_err_probe(&spi->dev, PTR_ERR(ddata->vcc_reg),
+                                 "failed to get LCD VCC regulator\n");
                goto err_regulator;
        }
 
index 3e44f95163182e4f9dd05c9399606569c6613261..0876962c52ebc5f54271c498c2867d4be024b02a 100644 (file)
@@ -65,7 +65,7 @@ static const struct fb_ops p9100_ops = {
 #define P9100_FB_OFF 0x0UL
 
 /* 3 bits: 2=8bpp 3=16bpp 5=32bpp 7=24bpp */
-#define SYS_CONFIG_PIXELSIZE_SHIFT 26 
+#define SYS_CONFIG_PIXELSIZE_SHIFT 26
 
 #define SCREENPAINT_TIMECTL1_ENABLE_VIDEO 0x20 /* 0 = off, 1 = on */
 
@@ -110,7 +110,7 @@ struct p9100_regs {
        u32 vram_xxx[25];
 
        /* Registers for IBM RGB528 Palette */
-       u32 ramdac_cmap_wridx; 
+       u32 ramdac_cmap_wridx;
        u32 ramdac_palette_data;
        u32 ramdac_pixel_mask;
        u32 ramdac_palette_rdaddr;
index 82f019f0a0d6cca7d398ca418f837535dc83a530..f8283fcd5edb781cb66587b181d3737d31695a77 100644 (file)
@@ -52,17 +52,17 @@ struct fb_info_platinum {
                __u8 red, green, blue;
        }                               palette[256];
        u32                             pseudo_palette[16];
-       
+
        volatile struct cmap_regs       __iomem *cmap_regs;
        unsigned long                   cmap_regs_phys;
-       
+
        volatile struct platinum_regs   __iomem *platinum_regs;
        unsigned long                   platinum_regs_phys;
-       
+
        __u8                            __iomem *frame_buffer;
        volatile __u8                   __iomem *base_frame_buffer;
        unsigned long                   frame_buffer_phys;
-       
+
        unsigned long                   total_vram;
        int                             clktype;
        int                             dactype;
@@ -133,7 +133,7 @@ static int platinumfb_set_par (struct fb_info *info)
        platinum_set_hardware(pinfo);
 
        init = platinum_reg_init[pinfo->vmode-1];
-       
+
        if ((pinfo->vmode == VMODE_832_624_75) && (pinfo->cmode > CMODE_8))
                offset = 0x10;
 
@@ -214,7 +214,7 @@ static int platinumfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                        break;
                }
        }
-       
+
        return 0;
 }
 
@@ -269,7 +269,7 @@ static void platinum_set_hardware(struct fb_info_platinum *pinfo)
        struct platinum_regvals         *init;
        int                             i;
        int                             vmode, cmode;
-       
+
        vmode = pinfo->vmode;
        cmode = pinfo->cmode;
 
@@ -436,7 +436,7 @@ static int read_platinum_sense(struct fb_info_platinum *info)
  * This routine takes a user-supplied var, and picks the best vmode/cmode from it.
  * It also updates the var structure to the actual mode data obtained
  */
-static int platinum_var_to_par(struct fb_var_screeninfo *var, 
+static int platinum_var_to_par(struct fb_var_screeninfo *var,
                               struct fb_info_platinum *pinfo,
                               int check_only)
 {
@@ -478,12 +478,12 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var,
        pinfo->yoffset = 0;
        pinfo->vxres = pinfo->xres;
        pinfo->vyres = pinfo->yres;
-       
+
        return 0;
 }
 
 
-/* 
+/*
  * Parse user specified options (`video=platinumfb:')
  */
 static int __init platinumfb_setup(char *options)
@@ -624,7 +624,7 @@ static int platinumfb_probe(struct platform_device* odev)
                break;
        }
        dev_set_drvdata(&odev->dev, info);
-       
+
        rc = platinum_init_fb(info);
        if (rc != 0) {
                iounmap(pinfo->frame_buffer);
@@ -640,9 +640,9 @@ static void platinumfb_remove(struct platform_device* odev)
 {
        struct fb_info          *info = dev_get_drvdata(&odev->dev);
        struct fb_info_platinum *pinfo = info->par;
-       
+
         unregister_framebuffer (info);
-       
+
        /* Unmap frame buffer and registers */
        iounmap(pinfo->frame_buffer);
        iounmap(pinfo->platinum_regs);
@@ -656,7 +656,7 @@ static void platinumfb_remove(struct platform_device* odev)
        framebuffer_release(info);
 }
 
-static struct of_device_id platinumfb_match[] = 
+static struct of_device_id platinumfb_match[] =
 {
        {
        .name           = "platinum",
@@ -664,7 +664,7 @@ static struct of_device_id platinumfb_match[] =
        {},
 };
 
-static struct platform_driver platinum_driver = 
+static struct platform_driver platinum_driver =
 {
        .driver = {
                .name = "platinumfb",
index b1b8ccdbac4a7da1e1a0d7e78270c1bf891b834a..a2408bf00ca0f51724645dd3b0c7f603d1ded146 100644 (file)
  *     - Driver appears to be working for Brutus 320x200x8bpp mode.  Other
  *       resolutions are working, but only the 8bpp mode is supported.
  *       Changes need to be made to the palette encode and decode routines
- *       to support 4 and 16 bpp modes.  
+ *       to support 4 and 16 bpp modes.
  *       Driver is not designed to be a module.  The FrameBuffer is statically
- *       allocated since dynamic allocation of a 300k buffer cannot be 
- *       guaranteed. 
+ *       allocated since dynamic allocation of a 300k buffer cannot be
+ *       guaranteed.
  *
  * 1999/06/17:
  *     - FrameBuffer memory is now allocated at run-time when the
- *       driver is initialized.    
+ *       driver is initialized.
  *
  * 2000/04/10: Nicolas Pitre <nico@fluxnic.net>
  *     - Big cleanup for dynamic selection of machine type at run time.
@@ -74,8 +74,8 @@
  *
  * 2000/08/07: Tak-Shing Chan <tchan.rd@idthk.com>
  *            Jeff Sutherland <jsutherland@accelent.com>
- *     - Resolved an issue caused by a change made to the Assabet's PLD 
- *       earlier this year which broke the framebuffer driver for newer 
+ *     - Resolved an issue caused by a change made to the Assabet's PLD
+ *       earlier this year which broke the framebuffer driver for newer
  *       Phase 4 Assabets.  Some other parameters were changed to optimize
  *       for the Sharp display.
  *
  * 2000/11/23: Eric Peng <ericpeng@coventive.com>
  *     - Freebird add
  *
- * 2001/02/07: Jamey Hicks <jamey.hicks@compaq.com> 
+ * 2001/02/07: Jamey Hicks <jamey.hicks@compaq.com>
  *            Cliff Brake <cbrake@accelent.com>
  *     - Added PM callback
  *
@@ -500,7 +500,7 @@ sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  *     the shortest recovery time
  *  Suspend
  *     This refers to a level of power management in which substantial power
- *     reduction is achieved by the display.  The display can have a longer 
+ *     reduction is achieved by the display.  The display can have a longer
  *     recovery time from this state than from the Stand-by state
  *  Off
  *     This indicates that the display is consuming the lowest level of power
@@ -522,9 +522,9 @@ sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  */
 /*
  * sa1100fb_blank():
- *     Blank the display by setting all palette values to zero.  Note, the 
+ *     Blank the display by setting all palette values to zero.  Note, the
  *     12 and 16 bpp modes don't really use the palette, so this will not
- *      blank the display in all modes.  
+ *      blank the display in all modes.
  */
 static int sa1100fb_blank(int blank, struct fb_info *info)
 {
@@ -603,8 +603,8 @@ static inline unsigned int get_pcd(struct sa1100fb_info *fbi,
 
 /*
  * sa1100fb_activate_var():
- *     Configures LCD Controller based on entries in var parameter.  Settings are      
- *     only written to the controller if changes were made.  
+ *     Configures LCD Controller based on entries in var parameter.  Settings are
+ *     only written to the controller if changes were made.
  */
 static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi)
 {
@@ -747,7 +747,7 @@ static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
         *
         * SA1110 spec update nr. 25 says we can and should
         * clear LDD15 to 12 for 4 or 8bpp modes with active
-        * panels.  
+        * panels.
         */
        if ((fbi->reg_lccr0 & LCCR0_CMS) == LCCR0_Color &&
            (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) != 0) {
@@ -1020,9 +1020,9 @@ static int sa1100fb_resume(struct platform_device *dev)
 
 /*
  * sa1100fb_map_video_memory():
- *      Allocates the DRAM memory for the frame buffer.  This buffer is  
- *     remapped into a non-cached, non-buffered, memory region to  
- *      allow palette and pixel writes to occur without flushing the 
+ *      Allocates the DRAM memory for the frame buffer.  This buffer is
+ *     remapped into a non-cached, non-buffered, memory region to
+ *      allow palette and pixel writes to occur without flushing the
  *      cache.  Once this area is remapped, all virtual memory
  *      access to the video memory should occur at the new region.
  */
index 046b9990d27cd92c1a26b16bf9f6c05713a65dda..132d1a205011836eb43db7dcd380e03f24f17caf 100644 (file)
@@ -844,7 +844,7 @@ static const struct i2c_device_id ssd1307fb_i2c_id[] = {
 MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id);
 
 static struct i2c_driver ssd1307fb_driver = {
-       .probe_new = ssd1307fb_probe,
+       .probe = ssd1307fb_probe,
        .remove = ssd1307fb_remove,
        .id_table = ssd1307fb_i2c_id,
        .driver = {
index ef8a4c5fc6875c55e180eea152e84e72c55c39d0..686a234f3899e5635b23da77375b2b6a5b8155b1 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * linux/drivers/video/stifb.c - 
- * Low level Frame buffer driver for HP workstations with 
+ * linux/drivers/video/stifb.c -
+ * Low level Frame buffer driver for HP workstations with
  * STI (standard text interface) video firmware.
  *
  * Copyright (C) 2001-2006 Helge Deller <deller@gmx.de>
  * Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
- * 
+ *
  * Based on:
  * - linux/drivers/video/artistfb.c -- Artist frame buffer driver
  *     Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
@@ -14,7 +14,7 @@
  * - HP Xhp cfb-based X11 window driver for XFree86
  *     (c)Copyright 1992 Hewlett-Packard Co.
  *
- * 
+ *
  *  The following graphics display devices (NGLE family) are supported by this driver:
  *
  *  HPA4070A   known as "HCRX", a 1280x1024 color device with 8 planes
@@ -30,7 +30,7 @@
  *             supports 1280x1024 color displays with 8 planes.
  *  HP710G     same as HP710C, 1280x1024 grayscale only
  *  HP710L     same as HP710C, 1024x768 color only
- *  HP712      internal graphics support on HP9000s712 SPU, supports 640x480, 
+ *  HP712      internal graphics support on HP9000s712 SPU, supports 640x480,
  *             1024x768 or 1280x1024 color displays on 8 planes (Artist)
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -92,7 +92,7 @@ typedef struct {
        __s32   misc_video_end;
 } video_setup_t;
 
-typedef struct {                  
+typedef struct {
        __s16   sizeof_ngle_data;
        __s16   x_size_visible;     /* visible screen dim in pixels  */
        __s16   y_size_visible;
@@ -177,10 +177,10 @@ static int __initdata stifb_bpp_pref[MAX_STI_ROMS];
 #endif /* DEBUG_STIFB_REGS */
 
 
-#define ENABLE 1       /* for enabling/disabling screen */     
+#define ENABLE 1       /* for enabling/disabling screen */
 #define DISABLE 0
 
-#define NGLE_LOCK(fb_info)     do { } while (0) 
+#define NGLE_LOCK(fb_info)     do { } while (0)
 #define NGLE_UNLOCK(fb_info)   do { } while (0)
 
 static void
@@ -198,9 +198,9 @@ SETUP_HW(struct stifb_info *fb)
 
 static void
 SETUP_FB(struct stifb_info *fb)
-{      
+{
        unsigned int reg10_value = 0;
-       
+
        SETUP_HW(fb);
        switch (fb->id)
        {
@@ -210,15 +210,15 @@ SETUP_FB(struct stifb_info *fb)
                        reg10_value = 0x13601000;
                        break;
                case S9000_ID_A1439A:
-                       if (fb->info.var.bits_per_pixel == 32)                                          
+                       if (fb->info.var.bits_per_pixel == 32)
                                reg10_value = 0xBBA0A000;
-                       else 
+                       else
                                reg10_value = 0x13601000;
                        break;
                case S9000_ID_HCRX:
                        if (fb->info.var.bits_per_pixel == 32)
                                reg10_value = 0xBBA0A000;
-                       else                                    
+                       else
                                reg10_value = 0x13602000;
                        break;
                case S9000_ID_TIMBER:
@@ -243,7 +243,7 @@ START_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb)
 }
 
 static void
-WRITE_IMAGE_COLOR(struct stifb_info *fb, int index, int color) 
+WRITE_IMAGE_COLOR(struct stifb_info *fb, int index, int color)
 {
        SETUP_HW(fb);
        WRITE_WORD(((0x100+index)<<2), fb, REG_3);
@@ -251,30 +251,30 @@ WRITE_IMAGE_COLOR(struct stifb_info *fb, int index, int color)
 }
 
 static void
-FINISH_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb) 
-{              
+FINISH_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb)
+{
        WRITE_WORD(0x400, fb, REG_2);
        if (fb->info.var.bits_per_pixel == 32) {
                WRITE_WORD(0x83000100, fb, REG_1);
        } else {
                if (fb->id == S9000_ID_ARTIST || fb->id == CRT_ID_VISUALIZE_EG)
                        WRITE_WORD(0x80000100, fb, REG_26);
-               else                                                    
+               else
                        WRITE_WORD(0x80000100, fb, REG_1);
        }
        SETUP_FB(fb);
 }
 
 static void
-SETUP_RAMDAC(struct stifb_info *fb) 
+SETUP_RAMDAC(struct stifb_info *fb)
 {
        SETUP_HW(fb);
        WRITE_WORD(0x04000000, fb, 0x1020);
        WRITE_WORD(0xff000000, fb, 0x1028);
 }
 
-static void 
-CRX24_SETUP_RAMDAC(struct stifb_info *fb) 
+static void
+CRX24_SETUP_RAMDAC(struct stifb_info *fb)
 {
        SETUP_HW(fb);
        WRITE_WORD(0x04000000, fb, 0x1000);
@@ -286,14 +286,14 @@ CRX24_SETUP_RAMDAC(struct stifb_info *fb)
 }
 
 #if 0
-static void 
+static void
 HCRX_SETUP_RAMDAC(struct stifb_info *fb)
 {
        WRITE_WORD(0xffffffff, fb, REG_32);
 }
 #endif
 
-static void 
+static void
 CRX24_SET_OVLY_MASK(struct stifb_info *fb)
 {
        SETUP_HW(fb);
@@ -314,7 +314,7 @@ ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
         WRITE_WORD(value,      fb, 0x1038);
 }
 
-static void 
+static void
 CRX24_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
 {
        unsigned int value = enable ? 0x10000000 : 0x30000000;
@@ -325,11 +325,11 @@ CRX24_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
 }
 
 static void
-ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) 
+ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
 {
        u32 DregsMiscVideo = REG_21;
        u32 DregsMiscCtl = REG_27;
-       
+
        SETUP_HW(fb);
        if (enable) {
          WRITE_WORD(READ_WORD(fb, DregsMiscVideo) | 0x0A000000, fb, DregsMiscVideo);
@@ -344,7 +344,7 @@ ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
        (READ_BYTE(fb, REG_16b3) - 1)
 
 #define HYPER_CONFIG_PLANES_24 0x00000100
-       
+
 #define IS_24_DEVICE(fb) \
        (fb->deviceSpecificConfig & HYPER_CONFIG_PLANES_24)
 
@@ -470,15 +470,15 @@ SETUP_ATTR_ACCESS(struct stifb_info *fb, unsigned BufferNumber)
 }
 
 static void
-SET_ATTR_SIZE(struct stifb_info *fb, int width, int height) 
+SET_ATTR_SIZE(struct stifb_info *fb, int width, int height)
 {
-       /* REG_6 seems to have special values when run on a 
+       /* REG_6 seems to have special values when run on a
           RDI precisionbook parisc laptop (INTERNAL_EG_DX1024 or
           INTERNAL_EG_X1024).  The values are:
                0x2f0: internal (LCD) & external display enabled
                0x2a0: external display only
                0x000: zero on standard artist graphic cards
-       */ 
+       */
        WRITE_WORD(0x00000000, fb, REG_6);
        WRITE_WORD((width<<16) | height, fb, REG_9);
        WRITE_WORD(0x05000000, fb, REG_6);
@@ -486,7 +486,7 @@ SET_ATTR_SIZE(struct stifb_info *fb, int width, int height)
 }
 
 static void
-FINISH_ATTR_ACCESS(struct stifb_info *fb) 
+FINISH_ATTR_ACCESS(struct stifb_info *fb)
 {
        SETUP_HW(fb);
        WRITE_WORD(0x00000000, fb, REG_12);
@@ -499,7 +499,7 @@ elkSetupPlanes(struct stifb_info *fb)
        SETUP_FB(fb);
 }
 
-static void 
+static void
 ngleSetupAttrPlanes(struct stifb_info *fb, int BufferNumber)
 {
        SETUP_ATTR_ACCESS(fb, BufferNumber);
@@ -519,7 +519,7 @@ rattlerSetupPlanes(struct stifb_info *fb)
         * read mask register for overlay planes, not image planes).
         */
        CRX24_SETUP_RAMDAC(fb);
-    
+
        /* change fb->id temporarily to fool SETUP_FB() */
        saved_id = fb->id;
        fb->id = CRX24_OVERLAY_PLANES;
@@ -565,7 +565,7 @@ setNgleLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length)
        lutBltCtl.all           = 0x80000000;
        lutBltCtl.fields.length = length;
 
-       switch (fb->id) 
+       switch (fb->id)
        {
        case S9000_ID_A1439A:           /* CRX24 */
                if (fb->var.bits_per_pixel == 8) {
@@ -576,12 +576,12 @@ setNgleLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length)
                        lutBltCtl.fields.lutOffset = 0 * 256;
                }
                break;
-               
+
        case S9000_ID_ARTIST:
                lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;
                lutBltCtl.fields.lutOffset = 0 * 256;
                break;
-               
+
        default:
                lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;
                lutBltCtl.fields.lutOffset = 0;
@@ -596,7 +596,7 @@ setNgleLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length)
 #endif
 
 static NgleLutBltCtl
-setHyperLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length) 
+setHyperLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length)
 {
        NgleLutBltCtl lutBltCtl;
 
@@ -633,7 +633,7 @@ static void hyperUndoITE(struct stifb_info *fb)
 
        /* Hardware setup for full-depth write to "magic" location */
        GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7);
-       NGLE_QUICK_SET_DST_BM_ACCESS(fb, 
+       NGLE_QUICK_SET_DST_BM_ACCESS(fb,
                BA(IndexedDcd, Otc04, Ots08, AddrLong,
                BAJustPoint(0), BINovly, BAIndexBase(0)));
        NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,
@@ -653,13 +653,13 @@ static void hyperUndoITE(struct stifb_info *fb)
        NGLE_UNLOCK(fb);
 }
 
-static void 
+static void
 ngleDepth8_ClearImagePlanes(struct stifb_info *fb)
 {
        /* FIXME! */
 }
 
-static void 
+static void
 ngleDepth24_ClearImagePlanes(struct stifb_info *fb)
 {
        /* FIXME! */
@@ -675,7 +675,7 @@ ngleResetAttrPlanes(struct stifb_info *fb, unsigned int ctlPlaneReg)
        NGLE_LOCK(fb);
 
        GET_FIFO_SLOTS(fb, nFreeFifoSlots, 4);
-       NGLE_QUICK_SET_DST_BM_ACCESS(fb, 
+       NGLE_QUICK_SET_DST_BM_ACCESS(fb,
                                     BA(IndexedDcd, Otc32, OtsIndirect,
                                        AddrLong, BAJustPoint(0),
                                        BINattr, BAIndexBase(0)));
@@ -713,22 +713,22 @@ ngleResetAttrPlanes(struct stifb_info *fb, unsigned int ctlPlaneReg)
        /**** Finally, set the Control Plane Register back to zero: ****/
        GET_FIFO_SLOTS(fb, nFreeFifoSlots, 1);
        NGLE_QUICK_SET_CTL_PLN_REG(fb, 0);
-       
+
        NGLE_UNLOCK(fb);
 }
-    
+
 static void
 ngleClearOverlayPlanes(struct stifb_info *fb, int mask, int data)
 {
        int nFreeFifoSlots = 0;
        u32 packed_dst;
        u32 packed_len;
-    
+
        NGLE_LOCK(fb);
 
        /* Hardware setup */
        GET_FIFO_SLOTS(fb, nFreeFifoSlots, 8);
-       NGLE_QUICK_SET_DST_BM_ACCESS(fb, 
+       NGLE_QUICK_SET_DST_BM_ACCESS(fb,
                                     BA(IndexedDcd, Otc04, Ots08, AddrLong,
                                        BAJustPoint(0), BINovly, BAIndexBase(0)));
 
@@ -736,23 +736,23 @@ ngleClearOverlayPlanes(struct stifb_info *fb, int mask, int data)
 
         NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, data);
         NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, mask);
-    
+
         packed_dst = 0;
         packed_len = (fb->info.var.xres << 16) | fb->info.var.yres;
         NGLE_SET_DSTXY(fb, packed_dst);
-    
-        /* Write zeroes to overlay planes */                  
+
+       /* Write zeroes to overlay planes */
        NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,
                                       IBOvals(RopSrc, MaskAddrOffset(0),
                                               BitmapExtent08, StaticReg(0),
                                               DataDynamic, MaskOtc, BGx(0), FGx(0)));
-                      
+
         SET_LENXY_START_RECFILL(fb, packed_len);
 
        NGLE_UNLOCK(fb);
 }
 
-static void 
+static void
 hyperResetPlanes(struct stifb_info *fb, int enable)
 {
        unsigned int controlPlaneReg;
@@ -783,7 +783,7 @@ hyperResetPlanes(struct stifb_info *fb, int enable)
                ngleClearOverlayPlanes(fb, 0xff, 255);
 
                /**************************************************
-                ** Also need to counteract ITE settings 
+                ** Also need to counteract ITE settings
                 **************************************************/
                hyperUndoITE(fb);
                break;
@@ -803,13 +803,13 @@ hyperResetPlanes(struct stifb_info *fb, int enable)
                ngleResetAttrPlanes(fb, controlPlaneReg);
                break;
        }
-       
+
        NGLE_UNLOCK(fb);
 }
 
 /* Return pointer to in-memory structure holding ELK device-dependent ROM values. */
 
-static void 
+static void
 ngleGetDeviceRomData(struct stifb_info *fb)
 {
 #if 0
@@ -821,7 +821,7 @@ XXX: FIXME: !!!
        char    *pCard8;
        int     i;
        char    *mapOrigin = NULL;
-    
+
        int romTableIdx;
 
        pPackedDevRomData = fb->ngle_rom;
@@ -888,7 +888,7 @@ SETUP_HCRX(struct stifb_info *fb)
 
        /* Initialize Hyperbowl registers */
        GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7);
-       
+
        if (IS_24_DEVICE(fb)) {
                hyperbowl = (fb->info.var.bits_per_pixel == 32) ?
                        HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE :
@@ -897,9 +897,9 @@ SETUP_HCRX(struct stifb_info *fb)
                /* First write to Hyperbowl must happen twice (bug) */
                WRITE_WORD(hyperbowl, fb, REG_40);
                WRITE_WORD(hyperbowl, fb, REG_40);
-               
+
                WRITE_WORD(HYPERBOWL_MODE2_8_24, fb, REG_39);
-               
+
                WRITE_WORD(0x014c0148, fb, REG_42); /* Set lut 0 to be the direct color */
                WRITE_WORD(0x404c4048, fb, REG_43);
                WRITE_WORD(0x034c0348, fb, REG_44);
@@ -990,7 +990,7 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
                                0,      /* Offset w/i LUT */
                                256);   /* Load entire LUT */
                NGLE_BINC_SET_SRCADDR(fb,
-                               NGLE_LONG_FB_ADDRESS(0, 0x100, 0)); 
+                               NGLE_LONG_FB_ADDRESS(0, 0x100, 0));
                                /* 0x100 is same as used in WRITE_IMAGE_COLOR() */
                START_COLORMAPLOAD(fb, lutBltCtl.all);
                SETUP_FB(fb);
@@ -1028,7 +1028,7 @@ stifb_blank(int blank_mode, struct fb_info *info)
                ENABLE_DISABLE_DISPLAY(fb, enable);
                break;
        }
-       
+
        SETUP_FB(fb);
        return 0;
 }
@@ -1114,15 +1114,15 @@ stifb_init_display(struct stifb_info *fb)
 
        /* HCRX specific initialization */
        SETUP_HCRX(fb);
-       
+
        /*
        if (id == S9000_ID_HCRX)
                hyperInitSprite(fb);
        else
                ngleInitSprite(fb);
        */
-       
-       /* Initialize the image planes. */ 
+
+       /* Initialize the image planes. */
         switch (id) {
         case S9000_ID_HCRX:
            hyperResetPlanes(fb, ENABLE);
@@ -1194,7 +1194,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
        fb = kzalloc(sizeof(*fb), GFP_ATOMIC);
        if (!fb)
                return -ENOMEM;
-       
+
        info = &fb->info;
 
        /* set struct to a known state */
@@ -1235,7 +1235,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
                        dev_name, fb->id);
                goto out_err0;
        }
-       
+
        /* default to 8 bpp on most graphic chips */
        bpp = 8;
        xres = sti_onscreen_x(fb->sti);
@@ -1256,7 +1256,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
                fb->id = S9000_ID_A1659A;
                break;
        case S9000_ID_TIMBER:   /* HP9000/710 Any (may be a grayscale device) */
-               if (strstr(dev_name, "GRAYSCALE") || 
+               if (strstr(dev_name, "GRAYSCALE") ||
                    strstr(dev_name, "Grayscale") ||
                    strstr(dev_name, "grayscale"))
                        var->grayscale = 1;
@@ -1295,16 +1295,16 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
        case CRT_ID_VISUALIZE_EG:
        case S9000_ID_ARTIST:   /* Artist */
                break;
-       default: 
+       default:
 #ifdef FALLBACK_TO_1BPP
-               printk(KERN_WARNING 
+               printk(KERN_WARNING
                        "stifb: Unsupported graphics card (id=0x%08x) "
                                "- now trying 1bpp mode instead\n",
                        fb->id);
                bpp = 1;        /* default to 1 bpp */
                break;
 #else
-               printk(KERN_WARNING 
+               printk(KERN_WARNING
                        "stifb: Unsupported graphics card (id=0x%08x) "
                                "- skipping.\n",
                        fb->id);
@@ -1320,11 +1320,11 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
        fix->line_length = (fb->sti->glob_cfg->total_x * bpp) / 8;
        if (!fix->line_length)
                fix->line_length = 2048; /* default */
-       
+
        /* limit fbsize to max visible screen size */
        if (fix->smem_len > yres*fix->line_length)
                fix->smem_len = ALIGN(yres*fix->line_length, 4*1024*1024);
-       
+
        fix->accel = FB_ACCEL_NONE;
 
        switch (bpp) {
@@ -1350,7 +1350,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
            default:
                break;
        }
-       
+
        var->xres = var->xres_virtual = xres;
        var->yres = var->yres_virtual = yres;
        var->bits_per_pixel = bpp;
@@ -1379,7 +1379,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
                                fix->smem_start, fix->smem_start+fix->smem_len);
                goto out_err2;
        }
-               
+
        if (!request_mem_region(fix->mmio_start, fix->mmio_len, "stifb mmio")) {
                printk(KERN_ERR "stifb: cannot reserve sti mmio region 0x%04lx-0x%04lx\n",
                                fix->mmio_start, fix->mmio_start+fix->mmio_len);
@@ -1393,11 +1393,11 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
 
        fb_info(&fb->info, "%s %dx%d-%d frame buffer device, %s, id: %04x, mmio: 0x%04lx\n",
                fix->id,
-               var->xres, 
+               var->xres,
                var->yres,
                var->bits_per_pixel,
                dev_name,
-               fb->id, 
+               fb->id,
                fix->mmio_start);
 
        return 0;
@@ -1413,6 +1413,7 @@ out_err1:
        iounmap(info->screen_base);
 out_err0:
        kfree(fb);
+       sti->info = NULL;
        return -ENXIO;
 }
 
@@ -1426,7 +1427,7 @@ static int __init stifb_init(void)
        struct sti_struct *sti;
        struct sti_struct *def_sti;
        int i;
-       
+
 #ifndef MODULE
        char *option = NULL;
 
@@ -1438,7 +1439,7 @@ static int __init stifb_init(void)
                printk(KERN_INFO "stifb: disabled by \"stifb=off\" kernel parameter\n");
                return -ENXIO;
        }
-       
+
        def_sti = sti_get_rom(0);
        if (def_sti) {
                for (i = 1; i <= MAX_STI_ROMS; i++) {
@@ -1472,7 +1473,7 @@ stifb_cleanup(void)
 {
        struct sti_struct *sti;
        int i;
-       
+
        for (i = 1; i <= MAX_STI_ROMS; i++) {
                sti = sti_get_rom(i);
                if (!sti)
@@ -1495,10 +1496,10 @@ int __init
 stifb_setup(char *options)
 {
        int i;
-       
+
        if (!options || !*options)
                return 1;
-       
+
        if (strncmp(options, "off", 3) == 0) {
                stifb_disabled = 1;
                options += 3;
index 216d49c9d47e5c57f11e93c5c01a56b371cb39b1..dabc30a09f969876654280ddc31db0355c41de3b 100644 (file)
@@ -27,6 +27,8 @@
 #include <video/udlfb.h>
 #include "edid.h"
 
+#define OUT_EP_NUM     1       /* The endpoint number we will use */
+
 static const struct fb_fix_screeninfo dlfb_fix = {
        .id =           "udlfb",
        .type =         FB_TYPE_PACKED_PIXELS,
@@ -1541,24 +1543,16 @@ static const struct device_attribute fb_device_attrs[] = {
 static int dlfb_select_std_channel(struct dlfb_data *dlfb)
 {
        int ret;
-       void *buf;
        static const u8 set_def_chn[] = {
                                0x57, 0xCD, 0xDC, 0xA7,
                                0x1C, 0x88, 0x5E, 0x15,
                                0x60, 0xFE, 0xC6, 0x97,
                                0x16, 0x3D, 0x47, 0xF2  };
 
-       buf = kmemdup(set_def_chn, sizeof(set_def_chn), GFP_KERNEL);
-
-       if (!buf)
-               return -ENOMEM;
-
-       ret = usb_control_msg(dlfb->udev, usb_sndctrlpipe(dlfb->udev, 0),
-                       NR_USB_REQUEST_CHANNEL,
+       ret = usb_control_msg_send(dlfb->udev, 0, NR_USB_REQUEST_CHANNEL,
                        (USB_DIR_OUT | USB_TYPE_VENDOR), 0, 0,
-                       buf, sizeof(set_def_chn), USB_CTRL_SET_TIMEOUT);
-
-       kfree(buf);
+                       &set_def_chn, sizeof(set_def_chn), USB_CTRL_SET_TIMEOUT,
+                       GFP_KERNEL);
 
        return ret;
 }
@@ -1652,7 +1646,7 @@ static int dlfb_usb_probe(struct usb_interface *intf,
        struct fb_info *info;
        int retval;
        struct usb_device *usbdev = interface_to_usbdev(intf);
-       struct usb_endpoint_descriptor *out;
+       static u8 out_ep[] = {OUT_EP_NUM + USB_DIR_OUT, 0};
 
        /* usb initialization */
        dlfb = kzalloc(sizeof(*dlfb), GFP_KERNEL);
@@ -1666,9 +1660,9 @@ static int dlfb_usb_probe(struct usb_interface *intf,
        dlfb->udev = usb_get_dev(usbdev);
        usb_set_intfdata(intf, dlfb);
 
-       retval = usb_find_common_endpoints(intf->cur_altsetting, NULL, &out, NULL, NULL);
-       if (retval) {
-               dev_err(&intf->dev, "Device should have at lease 1 bulk endpoint!\n");
+       if (!usb_check_bulk_endpoints(intf, out_ep)) {
+               dev_err(&intf->dev, "Invalid DisplayLink device!\n");
+               retval = -EINVAL;
                goto error;
        }
 
@@ -1927,7 +1921,8 @@ retry:
                }
 
                /* urb->transfer_buffer_length set to actual before submit */
-               usb_fill_bulk_urb(urb, dlfb->udev, usb_sndbulkpipe(dlfb->udev, 1),
+               usb_fill_bulk_urb(urb, dlfb->udev,
+                       usb_sndbulkpipe(dlfb->udev, OUT_EP_NUM),
                        buf, size, dlfb_urb_completion, unode);
                urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
index 1007023a5e889b4b57f8f12474af2d27f0bbbe27..b166b7cfe0e56fcf24cfeaf2205c860044087278 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  valkyriefb.c -- frame buffer device for the PowerMac 'valkyrie' display
  *
- *  Created 8 August 1998 by 
+ *  Created 8 August 1998 by
  *  Martin Costabel <costabel@wanadoo.fr> and Kevin Schoedel
  *
  *  Vmode-switching changes and vmode 15/17 modifications created 29 August
@@ -77,13 +77,13 @@ struct fb_info_valkyrie {
        struct fb_par_valkyrie  par;
        struct cmap_regs        __iomem *cmap_regs;
        unsigned long           cmap_regs_phys;
-       
+
        struct valkyrie_regs    __iomem *valkyrie_regs;
        unsigned long           valkyrie_regs_phys;
-       
+
        __u8                    __iomem *frame_buffer;
        unsigned long           frame_buffer_phys;
-       
+
        int                     sense;
        unsigned long           total_vram;
 
@@ -244,7 +244,7 @@ static inline int valkyrie_vram_reqd(int video_mode, int color_mode)
 {
        int pitch;
        struct valkyrie_regvals *init = valkyrie_reg_init[video_mode-1];
-       
+
        if ((pitch = init->pitch[color_mode]) == 0)
                pitch = 2 * init->pitch[0];
        return init->vres * pitch;
@@ -467,7 +467,7 @@ static int valkyrie_var_to_par(struct fb_var_screeninfo *var,
                printk(KERN_ERR "valkyriefb: vmode %d not valid.\n", vmode);
                return -EINVAL;
        }
-       
+
        if (cmode != CMODE_8 && cmode != CMODE_16) {
                printk(KERN_ERR "valkyriefb: cmode %d not valid.\n", cmode);
                return -EINVAL;
@@ -516,7 +516,7 @@ static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valk
        fix->ywrapstep = 0;
        fix->ypanstep = 0;
        fix->xpanstep = 0;
-       
+
 }
 
 /* Fix must already be inited above */
index a94573997d1593c59e88598d13406f2cca390f8d..6f1990969361caccbd9c4b01e569b3bf7289d1b9 100644 (file)
@@ -111,7 +111,7 @@ static u_long get_line_length(int xres_virtual, int bpp)
      *  First part, xxxfb_check_var, must not write anything
      *  to hardware, it should only verify and adjust var.
      *  This means it doesn't alter par but it does use hardware
-     *  data from it to check this var. 
+     *  data from it to check this var.
      */
 
 static int vfb_check_var(struct fb_var_screeninfo *var,
@@ -169,7 +169,7 @@ static int vfb_check_var(struct fb_var_screeninfo *var,
 
        /*
         * Now that we checked it we alter var. The reason being is that the video
-        * mode passed in might not work but slight changes to it might make it 
+        * mode passed in might not work but slight changes to it might make it
         * work. This way we let the user know what is acceptable.
         */
        switch (var->bits_per_pixel) {
@@ -235,8 +235,8 @@ static int vfb_check_var(struct fb_var_screeninfo *var,
 }
 
 /* This routine actually sets the video mode. It's in here where we
- * the hardware state info->par and fix which can be affected by the 
- * change in par. For this driver it doesn't do much. 
+ * the hardware state info->par and fix which can be affected by the
+ * change in par. For this driver it doesn't do much.
  */
 static int vfb_set_par(struct fb_info *info)
 {
@@ -379,7 +379,7 @@ static int vfb_pan_display(struct fb_var_screeninfo *var,
 }
 
     /*
-     *  Most drivers don't need their own mmap function 
+     *  Most drivers don't need their own mmap function
      */
 
 static int vfb_mmap(struct fb_info *info,
index e8c7fa68d3cc34086468b4aa907b910ab271f11a..d7fbc3c146e1c2b98aa3146942416222b19355b3 100644 (file)
@@ -93,7 +93,7 @@ static int sgi_w1_probe(struct platform_device *pdev)
 
        pdata = dev_get_platdata(&pdev->dev);
        if (pdata) {
-               strlcpy(sdev->dev_id, pdata->dev_id, sizeof(sdev->dev_id));
+               strscpy(sdev->dev_id, pdata->dev_id, sizeof(sdev->dev_id));
                sdev->bus_master.dev_id = sdev->dev_id;
        }
 
index 687753889c34ead10a3e54fbfe1ffb79e3de314c..32b8a757744ee30002cbd659a04c049778aea980 100644 (file)
@@ -71,8 +71,8 @@ config W1_SLAVE_DS2805
        help
          Say Y here if you want to use a 1-wire
          is a 112-byte user-programmable EEPROM is
-          organized as 7 pages of 16 bytes each with 64bit
-          unique number. Requires OverDrive Speed to talk to.
+         organized as 7 pages of 16 bytes each with 64bit
+         unique number. Requires OverDrive Speed to talk to.
 
 config W1_SLAVE_DS2430
        tristate "256b EEPROM family support (DS2430)"
index ca64f99c8f3d7b61515a24d455f9be51003c70b7..e008c27b3db9efaaba4e6965cc7c3ff032afe3cc 100644 (file)
@@ -66,8 +66,6 @@ static int w1_ds2438_get_page(struct w1_slave *sl, int pageno, u8 *buf)
        size_t count;
 
        while (retries--) {
-               crc = 0;
-
                if (w1_reset_select_slave(sl))
                        continue;
                w1_buf[0] = W1_DS2438_RECALL_MEMORY;
index 067692626cf072acfa533975f242331626e6573f..c85e80c7e13078afb9beb3fbae23356954644cee 100644 (file)
@@ -284,7 +284,7 @@ static int read_powermode(struct w1_slave *sl);
  * trigger_bulk_read() - function to trigger a bulk read on the bus
  * @dev_master: the device master of the bus
  *
- * Send a SKIP ROM follow by a CONVERT T commmand on the bus.
+ * Send a SKIP ROM follow by a CONVERT T command on the bus.
  * It also set the status flag in each slave &struct w1_therm_family_data
  * to signal that a conversion is in progress.
  *
@@ -454,7 +454,7 @@ static const struct hwmon_channel_info w1_temp = {
        .config = w1_temp_config,
 };
 
-static const struct hwmon_channel_info *w1_info[] = {
+static const struct hwmon_channel_info * const w1_info[] = {
        &w1_temp,
        NULL
 };
@@ -1159,29 +1159,26 @@ static int convert_t(struct w1_slave *sl, struct therm_info *info)
 
                        w1_write_8(dev_master, W1_CONVERT_TEMP);
 
-                       if (strong_pullup) { /*some device need pullup */
+                       if (SLAVE_FEATURES(sl) & W1_THERM_POLL_COMPLETION) {
+                               ret = w1_poll_completion(dev_master, W1_POLL_CONVERT_TEMP);
+                               if (ret) {
+                                       dev_dbg(&sl->dev, "%s: Timeout\n", __func__);
+                                       goto mt_unlock;
+                               }
+                               mutex_unlock(&dev_master->bus_mutex);
+                       } else if (!strong_pullup) { /*no device need pullup */
                                sleep_rem = msleep_interruptible(t_conv);
                                if (sleep_rem != 0) {
                                        ret = -EINTR;
                                        goto mt_unlock;
                                }
                                mutex_unlock(&dev_master->bus_mutex);
-                       } else { /*no device need pullup */
-                               if (SLAVE_FEATURES(sl) & W1_THERM_POLL_COMPLETION) {
-                                       ret = w1_poll_completion(dev_master, W1_POLL_CONVERT_TEMP);
-                                       if (ret) {
-                                               dev_dbg(&sl->dev, "%s: Timeout\n", __func__);
-                                               goto mt_unlock;
-                                       }
-                                       mutex_unlock(&dev_master->bus_mutex);
-                               } else {
-                                       /* Fixed delay */
-                                       mutex_unlock(&dev_master->bus_mutex);
-                                       sleep_rem = msleep_interruptible(t_conv);
-                                       if (sleep_rem != 0) {
-                                               ret = -EINTR;
-                                               goto dec_refcnt;
-                                       }
+                       } else { /*some device need pullup */
+                               mutex_unlock(&dev_master->bus_mutex);
+                               sleep_rem = msleep_interruptible(t_conv);
+                               if (sleep_rem != 0) {
+                                       ret = -EINTR;
+                                       goto dec_refcnt;
                                }
                        }
                        ret = read_scratchpad(sl, info);
@@ -1515,7 +1512,7 @@ static int trigger_bulk_read(struct w1_master *dev_master)
                if (bulk_read_support(sl)) {
                        int t_cur = conversion_time(sl);
 
-                       t_conv = t_cur > t_conv ? t_cur : t_conv;
+                       t_conv = max(t_cur, t_conv);
                        strong_pullup = strong_pullup ||
                                        (w1_strong_pullup == 2 ||
                                        (!SLAVE_POWERMODE(sl) &&
index 9d199fed96287602868b2f925257250f1a3a6574..5353cbd75126c120f4f202038be16c3e27fdef63 100644 (file)
@@ -32,7 +32,7 @@ static int w1_timeout = 10;
 module_param_named(timeout, w1_timeout, int, 0);
 MODULE_PARM_DESC(timeout, "time in seconds between automatic slave searches");
 
-static int w1_timeout_us = 0;
+static int w1_timeout_us;
 module_param_named(timeout_us, w1_timeout_us, int, 0);
 MODULE_PARM_DESC(timeout_us,
                 "time in microseconds between automatic slave searches");
@@ -58,11 +58,6 @@ MODULE_PARM_DESC(slave_ttl,
 DEFINE_MUTEX(w1_mlock);
 LIST_HEAD(w1_masters);
 
-static int w1_master_match(struct device *dev, struct device_driver *drv)
-{
-       return 1;
-}
-
 static int w1_master_probe(struct device *dev)
 {
        return -ENODEV;
@@ -174,7 +169,6 @@ static int w1_uevent(const struct device *dev, struct kobj_uevent_env *env);
 
 static struct bus_type w1_bus_type = {
        .name = "w1",
-       .match = w1_master_match,
        .uevent = w1_uevent,
 };
 
@@ -301,17 +295,13 @@ static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct devic
 
 static ssize_t w1_master_attribute_show_timeout(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       ssize_t count;
-       count = sprintf(buf, "%d\n", w1_timeout);
-       return count;
+       return sprintf(buf, "%d\n", w1_timeout);
 }
 
 static ssize_t w1_master_attribute_show_timeout_us(struct device *dev,
        struct device_attribute *attr, char *buf)
 {
-       ssize_t count;
-       count = sprintf(buf, "%d\n", w1_timeout_us);
-       return count;
+       return sprintf(buf, "%d\n", w1_timeout_us);
 }
 
 static ssize_t w1_master_attribute_store_max_slave_count(struct device *dev,
@@ -501,7 +491,7 @@ static ssize_t w1_master_attribute_store_remove(struct device *dev,
        struct w1_master *md = dev_to_w1_master(dev);
        struct w1_reg_num rn;
        struct w1_slave *sl;
-       ssize_t result = count;
+       ssize_t result;
 
        if (w1_atoreg_num(dev, buf, count, &rn))
                return -EINVAL;
@@ -702,6 +692,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
                dev_err(&sl->dev,
                        "Device registration [%s] failed. err=%d\n",
                        dev_name(&sl->dev), err);
+               of_node_put(sl->dev.of_node);
                put_device(&sl->dev);
                return err;
        }
@@ -830,49 +821,47 @@ int w1_slave_detach(struct w1_slave *sl)
 
 struct w1_master *w1_search_master_id(u32 id)
 {
-       struct w1_master *dev;
-       int found = 0;
+       struct w1_master *dev = NULL, *iter;
 
        mutex_lock(&w1_mlock);
-       list_for_each_entry(dev, &w1_masters, w1_master_entry) {
-               if (dev->id == id) {
-                       found = 1;
-                       atomic_inc(&dev->refcnt);
+       list_for_each_entry(iter, &w1_masters, w1_master_entry) {
+               if (iter->id == id) {
+                       dev = iter;
+                       atomic_inc(&iter->refcnt);
                        break;
                }
        }
        mutex_unlock(&w1_mlock);
 
-       return (found)?dev:NULL;
+       return dev;
 }
 
 struct w1_slave *w1_search_slave(struct w1_reg_num *id)
 {
        struct w1_master *dev;
-       struct w1_slave *sl = NULL;
-       int found = 0;
+       struct w1_slave *sl = NULL, *iter;
 
        mutex_lock(&w1_mlock);
        list_for_each_entry(dev, &w1_masters, w1_master_entry) {
                mutex_lock(&dev->list_mutex);
-               list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
-                       if (sl->reg_num.family == id->family &&
-                                       sl->reg_num.id == id->id &&
-                                       sl->reg_num.crc == id->crc) {
-                               found = 1;
+               list_for_each_entry(iter, &dev->slist, w1_slave_entry) {
+                       if (iter->reg_num.family == id->family &&
+                           iter->reg_num.id == id->id &&
+                           iter->reg_num.crc == id->crc) {
+                               sl = iter;
                                atomic_inc(&dev->refcnt);
-                               atomic_inc(&sl->refcnt);
+                               atomic_inc(&iter->refcnt);
                                break;
                        }
                }
                mutex_unlock(&dev->list_mutex);
 
-               if (found)
+               if (sl)
                        break;
        }
        mutex_unlock(&w1_mlock);
 
-       return (found)?sl:NULL;
+       return sl;
 }
 
 void w1_reconnect_slaves(struct w1_family *f, int attach)
@@ -1263,10 +1252,10 @@ err_out_exit_init:
 
 static void __exit w1_fini(void)
 {
-       struct w1_master *dev;
+       struct w1_master *dev, *n;
 
        /* Set netlink removal messages and some cleanup */
-       list_for_each_entry(dev, &w1_masters, w1_master_entry)
+       list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry)
                __w1_remove_master_device(dev);
 
        w1_fini_netlink();
index 1f5219e12cc36a5094390ae3a1a7c30211bd42fd..7beaf2c41fbbbe6bc6f3822953bab275f2db26a4 100644 (file)
@@ -325,8 +325,10 @@ static struct sock_mapping *pvcalls_new_active_socket(
        void *page;
 
        map = kzalloc(sizeof(*map), GFP_KERNEL);
-       if (map == NULL)
+       if (map == NULL) {
+               sock_release(sock);
                return NULL;
+       }
 
        map->fedata = fedata;
        map->sock = sock;
@@ -418,10 +420,8 @@ static int pvcalls_back_connect(struct xenbus_device *dev,
                                        req->u.connect.ref,
                                        req->u.connect.evtchn,
                                        sock);
-       if (!map) {
+       if (!map)
                ret = -EFAULT;
-               sock_release(sock);
-       }
 
 out:
        rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
@@ -561,7 +561,6 @@ static void __pvcalls_back_accept(struct work_struct *work)
                                        sock);
        if (!map) {
                ret = -EFAULT;
-               sock_release(sock);
                goto out_error;
        }
 
index cc07a0cd317265f15788348c633085c020ce1c13..18d034ec79539f0469f98edee982a62501f78490 100644 (file)
@@ -368,14 +368,7 @@ config NFS_V4_2_SSC_HELPER
 source "net/sunrpc/Kconfig"
 source "fs/ceph/Kconfig"
 
-source "fs/cifs/Kconfig"
-source "fs/ksmbd/Kconfig"
-
-config SMBFS_COMMON
-       tristate
-       default y if CIFS=y || SMB_SERVER=y
-       default m if CIFS=m || SMB_SERVER=m
-
+source "fs/smb/Kconfig"
 source "fs/coda/Kconfig"
 source "fs/afs/Kconfig"
 source "fs/9p/Kconfig"
index 834f1c3dba4642330c38afe14eb38d78727168fa..5bfdbf0d70373e015af5fe037dde7c0e5e8291e9 100644 (file)
@@ -95,9 +95,7 @@ obj-$(CONFIG_LOCKD)           += lockd/
 obj-$(CONFIG_NLS)              += nls/
 obj-y                          += unicode/
 obj-$(CONFIG_SYSV_FS)          += sysv/
-obj-$(CONFIG_SMBFS_COMMON)     += smbfs_common/
-obj-$(CONFIG_CIFS)             += cifs/
-obj-$(CONFIG_SMB_SERVER)       += ksmbd/
+obj-$(CONFIG_SMBFS)            += smb/
 obj-$(CONFIG_HPFS_FS)          += hpfs/
 obj-$(CONFIG_NTFS_FS)          += ntfs/
 obj-$(CONFIG_NTFS3_FS)         += ntfs3/
index e54f0884802a0cb2ac3592a71d348e80e5e01e62..79336fa853db363c5543d2b880a9290a99ce41ff 100644 (file)
@@ -45,7 +45,8 @@ static int check_extent_in_eb(struct btrfs_backref_walk_ctx *ctx,
        int root_count;
        bool cached;
 
-       if (!btrfs_file_extent_compression(eb, fi) &&
+       if (!ctx->ignore_extent_item_pos &&
+           !btrfs_file_extent_compression(eb, fi) &&
            !btrfs_file_extent_encryption(eb, fi) &&
            !btrfs_file_extent_other_encoding(eb, fi)) {
                u64 data_offset;
@@ -552,7 +553,7 @@ static int add_all_parents(struct btrfs_backref_walk_ctx *ctx,
                                count++;
                        else
                                goto next;
-                       if (!ctx->ignore_extent_item_pos) {
+                       if (!ctx->skip_inode_ref_list) {
                                ret = check_extent_in_eb(ctx, &key, eb, fi, &eie);
                                if (ret == BTRFS_ITERATE_EXTENT_INODES_STOP ||
                                    ret < 0)
@@ -564,7 +565,7 @@ static int add_all_parents(struct btrfs_backref_walk_ctx *ctx,
                                                  eie, (void **)&old, GFP_NOFS);
                        if (ret < 0)
                                break;
-                       if (!ret && !ctx->ignore_extent_item_pos) {
+                       if (!ret && !ctx->skip_inode_ref_list) {
                                while (old->next)
                                        old = old->next;
                                old->next = eie;
@@ -1606,7 +1607,7 @@ again:
                                goto out;
                }
                if (ref->count && ref->parent) {
-                       if (!ctx->ignore_extent_item_pos && !ref->inode_list &&
+                       if (!ctx->skip_inode_ref_list && !ref->inode_list &&
                            ref->level == 0) {
                                struct btrfs_tree_parent_check check = { 0 };
                                struct extent_buffer *eb;
@@ -1647,7 +1648,7 @@ again:
                                                  (void **)&eie, GFP_NOFS);
                        if (ret < 0)
                                goto out;
-                       if (!ret && !ctx->ignore_extent_item_pos) {
+                       if (!ret && !ctx->skip_inode_ref_list) {
                                /*
                                 * We've recorded that parent, so we must extend
                                 * its inode list here.
@@ -1743,7 +1744,7 @@ int btrfs_find_all_leafs(struct btrfs_backref_walk_ctx *ctx)
 static int btrfs_find_all_roots_safe(struct btrfs_backref_walk_ctx *ctx)
 {
        const u64 orig_bytenr = ctx->bytenr;
-       const bool orig_ignore_extent_item_pos = ctx->ignore_extent_item_pos;
+       const bool orig_skip_inode_ref_list = ctx->skip_inode_ref_list;
        bool roots_ulist_allocated = false;
        struct ulist_iterator uiter;
        int ret = 0;
@@ -1764,7 +1765,7 @@ static int btrfs_find_all_roots_safe(struct btrfs_backref_walk_ctx *ctx)
                roots_ulist_allocated = true;
        }
 
-       ctx->ignore_extent_item_pos = true;
+       ctx->skip_inode_ref_list = true;
 
        ULIST_ITER_INIT(&uiter);
        while (1) {
@@ -1789,7 +1790,7 @@ static int btrfs_find_all_roots_safe(struct btrfs_backref_walk_ctx *ctx)
        ulist_free(ctx->refs);
        ctx->refs = NULL;
        ctx->bytenr = orig_bytenr;
-       ctx->ignore_extent_item_pos = orig_ignore_extent_item_pos;
+       ctx->skip_inode_ref_list = orig_skip_inode_ref_list;
 
        return ret;
 }
@@ -1912,7 +1913,7 @@ int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
                goto out_trans;
        }
 
-       walk_ctx.ignore_extent_item_pos = true;
+       walk_ctx.skip_inode_ref_list = true;
        walk_ctx.trans = trans;
        walk_ctx.fs_info = fs_info;
        walk_ctx.refs = &ctx->refs;
index ef6bbea3f45621f1f0b87e5c3331c200c7a9b388..1616e3e3f1e4193c7fc531737e65da47698fc049 100644 (file)
@@ -60,6 +60,12 @@ struct btrfs_backref_walk_ctx {
         * @extent_item_pos is ignored.
         */
        bool ignore_extent_item_pos;
+       /*
+        * If true and bytenr corresponds to a data extent, then the inode list
+        * (each member describing inode number, file offset and root) is not
+        * added to each reference added to the @refs ulist.
+        */
+       bool skip_inode_ref_list;
        /* A valid transaction handle or NULL. */
        struct btrfs_trans_handle *trans;
        /*
index 5379c4714905e6695a21db9338a28236b8e5a56c..b3ad0f51e6162eea34550605d13d54031904b851 100644 (file)
@@ -330,7 +330,7 @@ static void btrfs_end_bio_work(struct work_struct *work)
        if (bbio->inode && !(bbio->bio.bi_opf & REQ_META))
                btrfs_check_read_bio(bbio, bbio->bio.bi_private);
        else
-               bbio->end_io(bbio);
+               btrfs_orig_bbio_end_io(bbio);
 }
 
 static void btrfs_simple_end_io(struct bio *bio)
@@ -811,10 +811,6 @@ void btrfs_submit_repair_write(struct btrfs_bio *bbio, int mirror_num, bool dev_
                goto fail;
 
        if (dev_replace) {
-               if (btrfs_op(&bbio->bio) == BTRFS_MAP_WRITE && btrfs_is_zoned(fs_info)) {
-                       bbio->bio.bi_opf &= ~REQ_OP_WRITE;
-                       bbio->bio.bi_opf |= REQ_OP_ZONE_APPEND;
-               }
                ASSERT(smap.dev == fs_info->dev_replace.srcdev);
                smap.dev = fs_info->dev_replace.tgtdev;
        }
index 957ad1c31c4f86a2b9211b4656f3b468e926efa3..590b0356026505cc0bdb547d1b56820e747af427 100644 (file)
@@ -2818,10 +2818,20 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache,
        }
 
        ret = inc_block_group_ro(cache, 0);
-       if (!do_chunk_alloc || ret == -ETXTBSY)
-               goto unlock_out;
        if (!ret)
                goto out;
+       if (ret == -ETXTBSY)
+               goto unlock_out;
+
+       /*
+        * Skip chunk alloction if the bg is SYSTEM, this is to avoid system
+        * chunk allocation storm to exhaust the system chunk array.  Otherwise
+        * we still want to try our best to mark the block group read-only.
+        */
+       if (!do_chunk_alloc && ret == -ENOSPC &&
+           (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM))
+               goto unlock_out;
+
        alloc_flags = btrfs_get_alloc_profile(fs_info, cache->space_info->flags);
        ret = btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE);
        if (ret < 0)
index 3ab707e26fa271a9645d5a66822dc04ef946d278..ac18c43fadadcade858daa32b93d0ae532218cb8 100644 (file)
@@ -124,7 +124,8 @@ static u64 block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
        } else {
                num_bytes = 0;
        }
-       if (block_rsv->qgroup_rsv_reserved >= block_rsv->qgroup_rsv_size) {
+       if (qgroup_to_release_ret &&
+           block_rsv->qgroup_rsv_reserved >= block_rsv->qgroup_rsv_size) {
                qgroup_to_release = block_rsv->qgroup_rsv_reserved -
                                    block_rsv->qgroup_rsv_size;
                block_rsv->qgroup_rsv_reserved = block_rsv->qgroup_rsv_size;
index 3c983c70028afa26429ba83e518f9ca8af32ac71..2ff2961b118302ebf91d4b0049b37c8b76b6b652 100644 (file)
@@ -2627,6 +2627,10 @@ static bool check_sibling_keys(struct extent_buffer *left,
        }
 
        if (btrfs_comp_cpu_keys(&left_last, &right_first) >= 0) {
+               btrfs_crit(left->fs_info, "left extent buffer:");
+               btrfs_print_tree(left, false);
+               btrfs_crit(left->fs_info, "right extent buffer:");
+               btrfs_print_tree(right, false);
                btrfs_crit(left->fs_info,
 "bad key order, sibling blocks, left last (%llu %u %llu) right first (%llu %u %llu)",
                           left_last.objectid, left_last.type,
@@ -3215,6 +3219,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
 
        if (check_sibling_keys(left, right)) {
                ret = -EUCLEAN;
+               btrfs_abort_transaction(trans, ret);
                btrfs_tree_unlock(right);
                free_extent_buffer(right);
                return ret;
@@ -3433,6 +3438,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
 
        if (check_sibling_keys(left, right)) {
                ret = -EUCLEAN;
+               btrfs_abort_transaction(trans, ret);
                goto out;
        }
        return __push_leaf_left(trans, path, min_data_size, empty, left,
@@ -4478,10 +4484,12 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path)
 {
        struct btrfs_key key;
+       struct btrfs_key orig_key;
        struct btrfs_disk_key found_key;
        int ret;
 
        btrfs_item_key_to_cpu(path->nodes[0], &key, 0);
+       orig_key = key;
 
        if (key.offset > 0) {
                key.offset--;
@@ -4498,8 +4506,36 @@ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path)
 
        btrfs_release_path(path);
        ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
-       if (ret < 0)
+       if (ret <= 0)
                return ret;
+
+       /*
+        * Previous key not found. Even if we were at slot 0 of the leaf we had
+        * before releasing the path and calling btrfs_search_slot(), we now may
+        * be in a slot pointing to the same original key - this can happen if
+        * after we released the path, one of more items were moved from a
+        * sibling leaf into the front of the leaf we had due to an insertion
+        * (see push_leaf_right()).
+        * If we hit this case and our slot is > 0 and just decrement the slot
+        * so that the caller does not process the same key again, which may or
+        * may not break the caller, depending on its logic.
+        */
+       if (path->slots[0] < btrfs_header_nritems(path->nodes[0])) {
+               btrfs_item_key(path->nodes[0], &found_key, path->slots[0]);
+               ret = comp_keys(&found_key, &orig_key);
+               if (ret == 0) {
+                       if (path->slots[0] > 0) {
+                               path->slots[0]--;
+                               return 0;
+                       }
+                       /*
+                        * At slot 0, same key as before, it means orig_key is
+                        * the lowest, leftmost, key in the tree. We're done.
+                        */
+                       return 1;
+               }
+       }
+
        btrfs_item_key(path->nodes[0], &found_key, 0);
        ret = comp_keys(&found_key, &key);
        /*
index 59ea049fe7ee0de22a15c6c9795fdf077b8369eb..2b1b227505f3a8a4ba056ecd306ea18d5a72bd0b 100644 (file)
@@ -96,7 +96,7 @@ static void csum_tree_block(struct extent_buffer *buf, u8 *result)
        crypto_shash_update(shash, kaddr + BTRFS_CSUM_SIZE,
                            first_page_part - BTRFS_CSUM_SIZE);
 
-       for (i = 1; i < num_pages; i++) {
+       for (i = 1; i < num_pages && INLINE_EXTENT_BUFFER_PAGES > 1; i++) {
                kaddr = page_address(buf->pages[i]);
                crypto_shash_update(shash, kaddr, PAGE_SIZE);
        }
@@ -3121,23 +3121,34 @@ int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info)
 {
        int ret;
        const bool cache_opt = btrfs_test_opt(fs_info, SPACE_CACHE);
-       bool clear_free_space_tree = false;
+       bool rebuild_free_space_tree = false;
 
        if (btrfs_test_opt(fs_info, CLEAR_CACHE) &&
            btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
-               clear_free_space_tree = true;
+               rebuild_free_space_tree = true;
        } else if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) &&
                   !btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID)) {
                btrfs_warn(fs_info, "free space tree is invalid");
-               clear_free_space_tree = true;
+               rebuild_free_space_tree = true;
        }
 
-       if (clear_free_space_tree) {
-               btrfs_info(fs_info, "clearing free space tree");
-               ret = btrfs_clear_free_space_tree(fs_info);
+       if (rebuild_free_space_tree) {
+               btrfs_info(fs_info, "rebuilding free space tree");
+               ret = btrfs_rebuild_free_space_tree(fs_info);
                if (ret) {
                        btrfs_warn(fs_info,
-                                  "failed to clear free space tree: %d", ret);
+                                  "failed to rebuild free space tree: %d", ret);
+                       goto out;
+               }
+       }
+
+       if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) &&
+           !btrfs_test_opt(fs_info, FREE_SPACE_TREE)) {
+               btrfs_info(fs_info, "disabling free space tree");
+               ret = btrfs_delete_free_space_tree(fs_info);
+               if (ret) {
+                       btrfs_warn(fs_info,
+                                  "failed to disable free space tree: %d", ret);
                        goto out;
                }
        }
@@ -4925,7 +4936,11 @@ static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root)
                 */
                inode = igrab(&btrfs_inode->vfs_inode);
                if (inode) {
+                       unsigned int nofs_flag;
+
+                       nofs_flag = memalloc_nofs_save();
                        invalidate_inode_pages2(inode->i_mapping);
+                       memalloc_nofs_restore(nofs_flag);
                        iput(inode);
                }
                spin_lock(&root->delalloc_lock);
@@ -5031,7 +5046,12 @@ static void btrfs_cleanup_bg_io(struct btrfs_block_group *cache)
 
        inode = cache->io_ctl.inode;
        if (inode) {
+               unsigned int nofs_flag;
+
+               nofs_flag = memalloc_nofs_save();
                invalidate_inode_pages2(inode->i_mapping);
+               memalloc_nofs_restore(nofs_flag);
+
                BTRFS_I(inode)->generation = 0;
                cache->io_ctl.inode = NULL;
                iput(inode);
index 018c711a0bc8d2124475982aa9abdb7093d44d6e..d1cd0a692f8efb8fe4f475874536d12235c04527 100644 (file)
@@ -52,13 +52,13 @@ void btrfs_inode_safe_disk_i_size_write(struct btrfs_inode *inode, u64 new_i_siz
        u64 start, end, i_size;
        int ret;
 
+       spin_lock(&inode->lock);
        i_size = new_i_size ?: i_size_read(&inode->vfs_inode);
        if (btrfs_fs_incompat(fs_info, NO_HOLES)) {
                inode->disk_i_size = i_size;
-               return;
+               goto out_unlock;
        }
 
-       spin_lock(&inode->lock);
        ret = find_contiguous_extent_bit(&inode->file_extent_tree, 0, &start,
                                         &end, EXTENT_DIRTY);
        if (!ret && start == 0)
@@ -66,6 +66,7 @@ void btrfs_inode_safe_disk_i_size_write(struct btrfs_inode *inode, u64 new_i_siz
        else
                i_size = 0;
        inode->disk_i_size = i_size;
+out_unlock:
        spin_unlock(&inode->lock);
 }
 
@@ -791,7 +792,9 @@ blk_status_t btrfs_csum_one_bio(struct btrfs_bio *bbio)
                                sums = kvzalloc(btrfs_ordered_sum_size(fs_info,
                                                      bytes_left), GFP_KERNEL);
                                memalloc_nofs_restore(nofs_flag);
-                               BUG_ON(!sums); /* -ENOMEM */
+                               if (!sums)
+                                       return BLK_STS_RESOURCE;
+
                                sums->len = bytes_left;
                                ordered = btrfs_lookup_ordered_extent(inode,
                                                                offset);
index d84cef89cdff522ab64931da108498d00637ea53..cf98a3c0548029ae041ba8032190f71bfbc22823 100644 (file)
@@ -870,15 +870,16 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
                        }
                        spin_lock(&ctl->tree_lock);
                        ret = link_free_space(ctl, e);
-                       ctl->total_bitmaps++;
-                       recalculate_thresholds(ctl);
-                       spin_unlock(&ctl->tree_lock);
                        if (ret) {
+                               spin_unlock(&ctl->tree_lock);
                                btrfs_err(fs_info,
                                        "Duplicate entries in free space cache, dumping");
                                kmem_cache_free(btrfs_free_space_cachep, e);
                                goto free_cache;
                        }
+                       ctl->total_bitmaps++;
+                       recalculate_thresholds(ctl);
+                       spin_unlock(&ctl->tree_lock);
                        list_add_tail(&e->list, &bitmaps);
                }
 
index 4d155a48ec59d333bc97eac224398e5d1a7ac388..b21da1446f2aac2733508bf8e8ee65c3bd9fbfab 100644 (file)
@@ -1252,7 +1252,7 @@ out:
        return ret;
 }
 
-int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
+int btrfs_delete_free_space_tree(struct btrfs_fs_info *fs_info)
 {
        struct btrfs_trans_handle *trans;
        struct btrfs_root *tree_root = fs_info->tree_root;
@@ -1298,6 +1298,54 @@ abort:
        return ret;
 }
 
+int btrfs_rebuild_free_space_tree(struct btrfs_fs_info *fs_info)
+{
+       struct btrfs_trans_handle *trans;
+       struct btrfs_key key = {
+               .objectid = BTRFS_FREE_SPACE_TREE_OBJECTID,
+               .type = BTRFS_ROOT_ITEM_KEY,
+               .offset = 0,
+       };
+       struct btrfs_root *free_space_root = btrfs_global_root(fs_info, &key);
+       struct rb_node *node;
+       int ret;
+
+       trans = btrfs_start_transaction(free_space_root, 1);
+       if (IS_ERR(trans))
+               return PTR_ERR(trans);
+
+       set_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags);
+       set_bit(BTRFS_FS_FREE_SPACE_TREE_UNTRUSTED, &fs_info->flags);
+
+       ret = clear_free_space_tree(trans, free_space_root);
+       if (ret)
+               goto abort;
+
+       node = rb_first_cached(&fs_info->block_group_cache_tree);
+       while (node) {
+               struct btrfs_block_group *block_group;
+
+               block_group = rb_entry(node, struct btrfs_block_group,
+                                      cache_node);
+               ret = populate_free_space_tree(trans, block_group);
+               if (ret)
+                       goto abort;
+               node = rb_next(node);
+       }
+
+       btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE);
+       btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID);
+       clear_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags);
+
+       ret = btrfs_commit_transaction(trans);
+       clear_bit(BTRFS_FS_FREE_SPACE_TREE_UNTRUSTED, &fs_info->flags);
+       return ret;
+abort:
+       btrfs_abort_transaction(trans, ret);
+       btrfs_end_transaction(trans);
+       return ret;
+}
+
 static int __add_block_group_free_space(struct btrfs_trans_handle *trans,
                                        struct btrfs_block_group *block_group,
                                        struct btrfs_path *path)
index dc2463e4cfe3c9a78a73d83f7aa05b2953531ccf..6d5551d0ced810cc02ac85390be192f8fab826dd 100644 (file)
@@ -18,7 +18,8 @@ struct btrfs_caching_control;
 
 void set_free_space_tree_thresholds(struct btrfs_block_group *block_group);
 int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info);
-int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info);
+int btrfs_delete_free_space_tree(struct btrfs_fs_info *fs_info);
+int btrfs_rebuild_free_space_tree(struct btrfs_fs_info *fs_info);
 int load_free_space_tree(struct btrfs_caching_control *caching_ctl);
 int add_block_group_free_space(struct btrfs_trans_handle *trans,
                               struct btrfs_block_group *block_group);
index 57d070025c7a89bcdc46fa84d20e2efa5f8eb534..19c707bc8801a993463e3805f84db32c9d93e33d 100644 (file)
@@ -3108,6 +3108,9 @@ int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
                btrfs_rewrite_logical_zoned(ordered_extent);
                btrfs_zone_finish_endio(fs_info, ordered_extent->disk_bytenr,
                                        ordered_extent->disk_num_bytes);
+       } else if (btrfs_is_data_reloc_root(inode->root)) {
+               btrfs_zone_finish_endio(fs_info, ordered_extent->disk_bytenr,
+                                       ordered_extent->disk_num_bytes);
        }
 
        if (test_bit(BTRFS_ORDERED_TRUNCATED, &ordered_extent->flags)) {
index 25833b4eeaf574ea28c44f2be2dae38627b19ee8..2fa36f694daa53acd3a33e12c09e8df8210e5624 100644 (file)
@@ -454,7 +454,9 @@ void btrfs_exclop_balance(struct btrfs_fs_info *fs_info,
        case BTRFS_EXCLOP_BALANCE_PAUSED:
                spin_lock(&fs_info->super_lock);
                ASSERT(fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE ||
-                      fs_info->exclusive_operation == BTRFS_EXCLOP_DEV_ADD);
+                      fs_info->exclusive_operation == BTRFS_EXCLOP_DEV_ADD ||
+                      fs_info->exclusive_operation == BTRFS_EXCLOP_NONE ||
+                      fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE_PAUSED);
                fs_info->exclusive_operation = BTRFS_EXCLOP_BALANCE_PAUSED;
                spin_unlock(&fs_info->super_lock);
                break;
index b93c962133048174bd5c9e867f971da8da994c3a..497b9dbd8a13381abe179ff54423473a2cc32473 100644 (file)
@@ -151,10 +151,10 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
                        pr_cont("shared data backref parent %llu count %u\n",
                               offset, btrfs_shared_data_ref_count(eb, sref));
                        /*
-                        * offset is supposed to be a tree block which
-                        * must be aligned to nodesize.
+                        * Offset is supposed to be a tree block which must be
+                        * aligned to sectorsize.
                         */
-                       if (!IS_ALIGNED(offset, eb->fs_info->nodesize))
+                       if (!IS_ALIGNED(offset, eb->fs_info->sectorsize))
                                pr_info(
                        "\t\t\t(parent %llu not aligned to sectorsize %u)\n",
                                     offset, eb->fs_info->sectorsize);
index 09b1988d179107c4bfe71556a6290cb157e81b18..59a06499c647ebb5ce35046763f35b9ac9626a5e 100644 (file)
@@ -3422,7 +3422,7 @@ int add_data_references(struct reloc_control *rc,
        btrfs_release_path(path);
 
        ctx.bytenr = extent_key->objectid;
-       ctx.ignore_extent_item_pos = true;
+       ctx.skip_inode_ref_list = true;
        ctx.fs_info = rc->extent_root->fs_info;
 
        ret = btrfs_find_all_leafs(&ctx);
index 836725a19661c1741e42971399fc941a4a7f9d82..7c666517d3d33a4e2bdaac5c4eeaf88e11ac1ab8 100644 (file)
@@ -1137,6 +1137,35 @@ static void scrub_write_endio(struct btrfs_bio *bbio)
                wake_up(&stripe->io_wait);
 }
 
+static void scrub_submit_write_bio(struct scrub_ctx *sctx,
+                                  struct scrub_stripe *stripe,
+                                  struct btrfs_bio *bbio, bool dev_replace)
+{
+       struct btrfs_fs_info *fs_info = sctx->fs_info;
+       u32 bio_len = bbio->bio.bi_iter.bi_size;
+       u32 bio_off = (bbio->bio.bi_iter.bi_sector << SECTOR_SHIFT) -
+                     stripe->logical;
+
+       fill_writer_pointer_gap(sctx, stripe->physical + bio_off);
+       atomic_inc(&stripe->pending_io);
+       btrfs_submit_repair_write(bbio, stripe->mirror_num, dev_replace);
+       if (!btrfs_is_zoned(fs_info))
+               return;
+       /*
+        * For zoned writeback, queue depth must be 1, thus we must wait for
+        * the write to finish before the next write.
+        */
+       wait_scrub_stripe_io(stripe);
+
+       /*
+        * And also need to update the write pointer if write finished
+        * successfully.
+        */
+       if (!test_bit(bio_off >> fs_info->sectorsize_bits,
+                     &stripe->write_error_bitmap))
+               sctx->write_pointer += bio_len;
+}
+
 /*
  * Submit the write bio(s) for the sectors specified by @write_bitmap.
  *
@@ -1155,7 +1184,6 @@ static void scrub_write_sectors(struct scrub_ctx *sctx, struct scrub_stripe *str
 {
        struct btrfs_fs_info *fs_info = stripe->bg->fs_info;
        struct btrfs_bio *bbio = NULL;
-       const bool zoned = btrfs_is_zoned(fs_info);
        int sector_nr;
 
        for_each_set_bit(sector_nr, &write_bitmap, stripe->nr_sectors) {
@@ -1168,13 +1196,7 @@ static void scrub_write_sectors(struct scrub_ctx *sctx, struct scrub_stripe *str
 
                /* Cannot merge with previous sector, submit the current one. */
                if (bbio && sector_nr && !test_bit(sector_nr - 1, &write_bitmap)) {
-                       fill_writer_pointer_gap(sctx, stripe->physical +
-                                       (sector_nr << fs_info->sectorsize_bits));
-                       atomic_inc(&stripe->pending_io);
-                       btrfs_submit_repair_write(bbio, stripe->mirror_num, dev_replace);
-                       /* For zoned writeback, queue depth must be 1. */
-                       if (zoned)
-                               wait_scrub_stripe_io(stripe);
+                       scrub_submit_write_bio(sctx, stripe, bbio, dev_replace);
                        bbio = NULL;
                }
                if (!bbio) {
@@ -1187,14 +1209,8 @@ static void scrub_write_sectors(struct scrub_ctx *sctx, struct scrub_stripe *str
                ret = bio_add_page(&bbio->bio, page, fs_info->sectorsize, pgoff);
                ASSERT(ret == fs_info->sectorsize);
        }
-       if (bbio) {
-               fill_writer_pointer_gap(sctx, bbio->bio.bi_iter.bi_sector <<
-                                       SECTOR_SHIFT);
-               atomic_inc(&stripe->pending_io);
-               btrfs_submit_repair_write(bbio, stripe->mirror_num, dev_replace);
-               if (zoned)
-                       wait_scrub_stripe_io(stripe);
-       }
+       if (bbio)
+               scrub_submit_write_bio(sctx, stripe, bbio, dev_replace);
 }
 
 /*
@@ -2518,13 +2534,20 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
 
                if (ret == 0) {
                        ro_set = 1;
-               } else if (ret == -ENOSPC && !sctx->is_dev_replace) {
+               } else if (ret == -ENOSPC && !sctx->is_dev_replace &&
+                          !(cache->flags & BTRFS_BLOCK_GROUP_RAID56_MASK)) {
                        /*
                         * btrfs_inc_block_group_ro return -ENOSPC when it
                         * failed in creating new chunk for metadata.
                         * It is not a problem for scrub, because
                         * metadata are always cowed, and our scrub paused
                         * commit_transactions.
+                        *
+                        * For RAID56 chunks, we have to mark them read-only
+                        * for scrub, as later we would use our own cache
+                        * out of RAID56 realm.
+                        * Thus we want the RAID56 bg to be marked RO to
+                        * prevent RMW from screwing up out cache.
                         */
                        ro_set = 0;
                } else if (ret == -ETXTBSY) {
index 6cb97efee9765ca1f4324be1fd9c8f2471e710a0..ec18e22106023bcb6b7b141f50972dc387debfd3 100644 (file)
@@ -826,7 +826,11 @@ out:
            !btrfs_test_opt(info, CLEAR_CACHE)) {
                btrfs_err(info, "cannot disable free space tree");
                ret = -EINVAL;
-
+       }
+       if (btrfs_fs_compat_ro(info, BLOCK_GROUP_TREE) &&
+            !btrfs_test_opt(info, FREE_SPACE_TREE)) {
+               btrfs_err(info, "cannot disable free space tree with block-group-tree feature");
+               ret = -EINVAL;
        }
        if (!ret)
                ret = btrfs_check_mountopts_zoned(info);
index 9b212e8c70cc585de76be3366bda9b33e15299ca..d2755d5e338b531eacad051becd98318c1b29059 100644 (file)
@@ -6158,7 +6158,7 @@ static int log_delayed_deletions_incremental(struct btrfs_trans_handle *trans,
 {
        struct btrfs_root *log = inode->root->log_root;
        const struct btrfs_delayed_item *curr;
-       u64 last_range_start;
+       u64 last_range_start = 0;
        u64 last_range_end = 0;
        struct btrfs_key key;
 
index 03f52e4a20aa9b695c7bb498e1e4a9e16b25488b..841e799dece51b2ebd990bd54b306da4be317dc8 100644 (file)
@@ -395,6 +395,7 @@ void btrfs_free_device(struct btrfs_device *device)
 {
        WARN_ON(!list_empty(&device->post_commit_list));
        rcu_string_free(device->name);
+       extent_io_tree_release(&device->alloc_state);
        btrfs_destroy_dev_zone_info(device);
        kfree(device);
 }
index a9b32ba6b2ce41b492c1a2546f89ceb213367ed9..39828af4a4e8ccc49611635688c9d8674ab430b1 100644 (file)
@@ -122,10 +122,9 @@ static int sb_write_pointer(struct block_device *bdev, struct blk_zone *zones,
                int i;
 
                for (i = 0; i < BTRFS_NR_SB_LOG_ZONES; i++) {
-                       u64 bytenr;
-
-                       bytenr = ((zones[i].start + zones[i].len)
-                                  << SECTOR_SHIFT) - BTRFS_SUPER_INFO_SIZE;
+                       u64 zone_end = (zones[i].start + zones[i].capacity) << SECTOR_SHIFT;
+                       u64 bytenr = ALIGN_DOWN(zone_end, BTRFS_SUPER_INFO_SIZE) -
+                                               BTRFS_SUPER_INFO_SIZE;
 
                        page[i] = read_cache_page_gfp(mapping,
                                        bytenr >> PAGE_SHIFT, GFP_NOFS);
@@ -1168,12 +1167,12 @@ int btrfs_ensure_empty_zones(struct btrfs_device *device, u64 start, u64 size)
                return -ERANGE;
 
        /* All the zones are conventional */
-       if (find_next_bit(zinfo->seq_zones, begin, end) == end)
+       if (find_next_bit(zinfo->seq_zones, end, begin) == end)
                return 0;
 
        /* All the zones are sequential and empty */
-       if (find_next_zero_bit(zinfo->seq_zones, begin, end) == end &&
-           find_next_zero_bit(zinfo->empty_zones, begin, end) == end)
+       if (find_next_zero_bit(zinfo->seq_zones, end, begin) == end &&
+           find_next_zero_bit(zinfo->empty_zones, end, begin) == end)
                return 0;
 
        for (pos = start; pos < start + size; pos += zinfo->zone_size) {
@@ -1610,11 +1609,11 @@ void btrfs_redirty_list_add(struct btrfs_transaction *trans,
            !list_empty(&eb->release_list))
                return;
 
+       memzero_extent_buffer(eb, 0, eb->len);
+       set_bit(EXTENT_BUFFER_NO_CHECK, &eb->bflags);
        set_extent_buffer_dirty(eb);
        set_extent_bits_nowait(&trans->dirty_pages, eb->start,
                               eb->start + eb->len - 1, EXTENT_DIRTY);
-       memzero_extent_buffer(eb, 0, eb->len);
-       set_bit(EXTENT_BUFFER_NO_CHECK, &eb->bflags);
 
        spin_lock(&trans->releasing_ebs_lock);
        list_add_tail(&eb->release_list, &trans->releasing_ebs);
index 29cf00220b09c41f553b31f573fc35b2cdd5c99f..4c0f22acf53d294a1c80e93f5c9ee8ad55bb8e3d 100644 (file)
@@ -3942,7 +3942,7 @@ static int reconnect_caps_cb(struct inode *inode, int mds, void *arg)
        struct dentry *dentry;
        struct ceph_cap *cap;
        char *path;
-       int pathlen = 0, err = 0;
+       int pathlen = 0, err;
        u64 pathbase;
        u64 snap_follows;
 
@@ -3965,6 +3965,7 @@ static int reconnect_caps_cb(struct inode *inode, int mds, void *arg)
        cap = __get_cap_for_mds(ci, mds);
        if (!cap) {
                spin_unlock(&ci->i_ceph_lock);
+               err = 0;
                goto out_err;
        }
        dout(" adding %p ino %llx.%llx cap %p %lld %s\n",
index 87007203f130e14abf51cdf54a5c3d388ba9ab97..0b236ebd989fcae8853e1af3bbaf2c9f00d4f0e4 100644 (file)
@@ -1111,6 +1111,19 @@ skip_inode:
                                continue;
                        adjust_snap_realm_parent(mdsc, child, realm->ino);
                }
+       } else {
+               /*
+                * In the non-split case both 'num_split_inos' and
+                * 'num_split_realms' should be 0, making this a no-op.
+                * However the MDS happens to populate 'split_realms' list
+                * in one of the UPDATE op cases by mistake.
+                *
+                * Skip both lists just in case to ensure that 'p' is
+                * positioned at the start of realm info, as expected by
+                * ceph_update_snap_trace().
+                */
+               p += sizeof(u64) * num_split_inos;
+               p += sizeof(u64) * num_split_realms;
        }
 
        /*
index ece7badf701bc2f917796aa565b478b21c5ce104..88740c51b94202528243a6a0ed74335e09eee41e 100644 (file)
@@ -371,7 +371,9 @@ static int zap_process(struct task_struct *start, int exit_code)
                if (t != current && !(t->flags & PF_POSTCOREDUMP)) {
                        sigaddset(&t->pending.signal, SIGKILL);
                        signal_wake_up(t, 1);
-                       nr++;
+                       /* The vhost_worker does not particpate in coredumps */
+                       if ((t->flags & (PF_USER_WORKER | PF_IO_WORKER)) != PF_USER_WORKER)
+                               nr++;
                }
        }
 
index 704fb59577e097d9c69727be960be8d3bfff828b..f259d92c97207b4143c5e4b5c32fbd76c94e8a90 100644 (file)
@@ -121,6 +121,7 @@ config EROFS_FS_PCPU_KTHREAD
 config EROFS_FS_PCPU_KTHREAD_HIPRI
        bool "EROFS high priority per-CPU kthread workers"
        depends on EROFS_FS_ZIP && EROFS_FS_PCPU_KTHREAD
+       default y
        help
          This permits EROFS to configure per-CPU kthread workers to run
          at higher priority.
index 99bbc597a3e923710905a66147accf906762c109..a3a98fc3e481ac42a12b4165a98d5fad9c20355b 100644 (file)
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
 obj-$(CONFIG_EROFS_FS) += erofs.o
-erofs-objs := super.o inode.o data.o namei.o dir.o utils.o pcpubuf.o sysfs.o
+erofs-objs := super.o inode.o data.o namei.o dir.o utils.o sysfs.o
 erofs-$(CONFIG_EROFS_FS_XATTR) += xattr.o
-erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o
+erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o pcpubuf.o
 erofs-$(CONFIG_EROFS_FS_ZIP_LZMA) += decompressor_lzma.o
 erofs-$(CONFIG_EROFS_FS_ONDEMAND) += fscache.o
index af0431a40647905738e2d2533d02d644f2a49c8d..1e39c03357d1ec0ecf039f7e28ccb432e24618d2 100644 (file)
@@ -472,12 +472,6 @@ static inline void *erofs_vm_map_ram(struct page **pages, unsigned int count)
        return NULL;
 }
 
-void *erofs_get_pcpubuf(unsigned int requiredpages);
-void erofs_put_pcpubuf(void *ptr);
-int erofs_pcpubuf_growsize(unsigned int nrpages);
-void __init erofs_pcpubuf_init(void);
-void erofs_pcpubuf_exit(void);
-
 int erofs_register_sysfs(struct super_block *sb);
 void erofs_unregister_sysfs(struct super_block *sb);
 int __init erofs_init_sysfs(void);
@@ -512,6 +506,11 @@ int z_erofs_load_lz4_config(struct super_block *sb,
                            struct z_erofs_lz4_cfgs *lz4, int len);
 int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map,
                            int flags);
+void *erofs_get_pcpubuf(unsigned int requiredpages);
+void erofs_put_pcpubuf(void *ptr);
+int erofs_pcpubuf_growsize(unsigned int nrpages);
+void __init erofs_pcpubuf_init(void);
+void erofs_pcpubuf_exit(void);
 #else
 static inline void erofs_shrinker_register(struct super_block *sb) {}
 static inline void erofs_shrinker_unregister(struct super_block *sb) {}
@@ -529,6 +528,8 @@ static inline int z_erofs_load_lz4_config(struct super_block *sb,
        }
        return 0;
 }
+static inline void erofs_pcpubuf_init(void) {}
+static inline void erofs_pcpubuf_exit(void) {}
 #endif /* !CONFIG_EROFS_FS_ZIP */
 
 #ifdef CONFIG_EROFS_FS_ZIP_LZMA
index cd80499351e05c1e3900a71f468b51eaa8d009ad..bbfe7ce170d217f30ec4a838c65df1b6c16fd463 100644 (file)
@@ -675,7 +675,7 @@ int erofs_xattr_prefixes_init(struct super_block *sb)
        if (!pfs)
                return -ENOMEM;
 
-       if (erofs_sb_has_fragments(sbi))
+       if (sbi->packed_inode)
                buf.inode = sbi->packed_inode;
        else
                erofs_init_metabuf(&buf, sb);
index 45f21db2303a9d72b606c92d5783cb724b5d5705..160b3da43aecdf6e88e6510630909f42fd5f056b 100644 (file)
@@ -369,8 +369,6 @@ static struct kthread_worker *erofs_init_percpu_worker(int cpu)
                return worker;
        if (IS_ENABLED(CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI))
                sched_set_fifo_low(worker->task);
-       else
-               sched_set_normal(worker->task, 0);
        return worker;
 }
 
index 0942694881838ea28d14d53ba0f7d29839e8a3e5..c1edde817be88f65f4c64263803f994d5d1a1347 100644 (file)
@@ -305,6 +305,38 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
        return desc;
 }
 
+static ext4_fsblk_t ext4_valid_block_bitmap_padding(struct super_block *sb,
+                                                   ext4_group_t block_group,
+                                                   struct buffer_head *bh)
+{
+       ext4_grpblk_t next_zero_bit;
+       unsigned long bitmap_size = sb->s_blocksize * 8;
+       unsigned int offset = num_clusters_in_group(sb, block_group);
+
+       if (bitmap_size <= offset)
+               return 0;
+
+       next_zero_bit = ext4_find_next_zero_bit(bh->b_data, bitmap_size, offset);
+
+       return (next_zero_bit < bitmap_size ? next_zero_bit : 0);
+}
+
+struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
+                                           ext4_group_t group)
+{
+        struct ext4_group_info **grp_info;
+        long indexv, indexh;
+
+        if (unlikely(group >= EXT4_SB(sb)->s_groups_count)) {
+                ext4_error(sb, "invalid group %u", group);
+                return NULL;
+        }
+        indexv = group >> (EXT4_DESC_PER_BLOCK_BITS(sb));
+        indexh = group & ((EXT4_DESC_PER_BLOCK(sb)) - 1);
+        grp_info = sbi_array_rcu_deref(EXT4_SB(sb), s_group_info, indexv);
+        return grp_info[indexh];
+}
+
 /*
  * Return the block number which was discovered to be invalid, or 0 if
  * the block bitmap is valid.
@@ -379,7 +411,7 @@ static int ext4_validate_block_bitmap(struct super_block *sb,
 
        if (buffer_verified(bh))
                return 0;
-       if (EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
+       if (!grp || EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
                return -EFSCORRUPTED;
 
        ext4_lock_group(sb, block_group);
@@ -402,6 +434,15 @@ static int ext4_validate_block_bitmap(struct super_block *sb,
                                        EXT4_GROUP_INFO_BBITMAP_CORRUPT);
                return -EFSCORRUPTED;
        }
+       blk = ext4_valid_block_bitmap_padding(sb, block_group, bh);
+       if (unlikely(blk != 0)) {
+               ext4_unlock_group(sb, block_group);
+               ext4_error(sb, "bg %u: block %llu: padding at end of block bitmap is not set",
+                          block_group, blk);
+               ext4_mark_group_bitmap_corrupted(sb, block_group,
+                                                EXT4_GROUP_INFO_BBITMAP_CORRUPT);
+               return -EFSCORRUPTED;
+       }
        set_buffer_verified(bh);
 verified:
        ext4_unlock_group(sb, block_group);
index 18cb2680dc39603d833f7472b64fb75216bbcf42..8104a21b001ae3b9ea3e20f27e36642c73b30248 100644 (file)
@@ -918,11 +918,13 @@ do {                                                                             \
  *                       where the second inode has larger inode number
  *                       than the first
  *  I_DATA_SEM_QUOTA  - Used for quota inodes only
+ *  I_DATA_SEM_EA     - Used for ea_inodes only
  */
 enum {
        I_DATA_SEM_NORMAL = 0,
        I_DATA_SEM_OTHER,
        I_DATA_SEM_QUOTA,
+       I_DATA_SEM_EA
 };
 
 
@@ -1684,6 +1686,30 @@ static inline struct ext4_inode_info *EXT4_I(struct inode *inode)
        return container_of(inode, struct ext4_inode_info, vfs_inode);
 }
 
+static inline int ext4_writepages_down_read(struct super_block *sb)
+{
+       percpu_down_read(&EXT4_SB(sb)->s_writepages_rwsem);
+       return memalloc_nofs_save();
+}
+
+static inline void ext4_writepages_up_read(struct super_block *sb, int ctx)
+{
+       memalloc_nofs_restore(ctx);
+       percpu_up_read(&EXT4_SB(sb)->s_writepages_rwsem);
+}
+
+static inline int ext4_writepages_down_write(struct super_block *sb)
+{
+       percpu_down_write(&EXT4_SB(sb)->s_writepages_rwsem);
+       return memalloc_nofs_save();
+}
+
+static inline void ext4_writepages_up_write(struct super_block *sb, int ctx)
+{
+       memalloc_nofs_restore(ctx);
+       percpu_up_write(&EXT4_SB(sb)->s_writepages_rwsem);
+}
+
 static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
 {
        return ino == EXT4_ROOT_INO ||
@@ -2625,6 +2651,8 @@ extern void ext4_check_blocks_bitmap(struct super_block *);
 extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
                                                    ext4_group_t block_group,
                                                    struct buffer_head ** bh);
+extern struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
+                                                  ext4_group_t group);
 extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
 
 extern struct buffer_head *ext4_read_block_bitmap_nowait(struct super_block *sb,
@@ -2875,7 +2903,8 @@ typedef enum {
        EXT4_IGET_NORMAL =      0,
        EXT4_IGET_SPECIAL =     0x0001, /* OK to iget a system inode */
        EXT4_IGET_HANDLE =      0x0002, /* Inode # is from a handle */
-       EXT4_IGET_BAD =         0x0004  /* Allow to iget a bad inode */
+       EXT4_IGET_BAD =         0x0004, /* Allow to iget a bad inode */
+       EXT4_IGET_EA_INODE =    0x0008  /* Inode should contain an EA value */
 } ext4_iget_flags;
 
 extern struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
@@ -3232,19 +3261,6 @@ static inline void ext4_isize_set(struct ext4_inode *raw_inode, loff_t i_size)
        raw_inode->i_size_high = cpu_to_le32(i_size >> 32);
 }
 
-static inline
-struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
-                                           ext4_group_t group)
-{
-        struct ext4_group_info **grp_info;
-        long indexv, indexh;
-        BUG_ON(group >= EXT4_SB(sb)->s_groups_count);
-        indexv = group >> (EXT4_DESC_PER_BLOCK_BITS(sb));
-        indexh = group & ((EXT4_DESC_PER_BLOCK(sb)) - 1);
-        grp_info = sbi_array_rcu_deref(EXT4_SB(sb), s_group_info, indexv);
-        return grp_info[indexh];
-}
-
 /*
  * Reading s_groups_count requires using smp_rmb() afterwards.  See
  * the locking protocol documented in the comments of ext4_group_add()
index 7bc221038c6c1041c91d9cc8d31368d813fee9bc..595abb9e7d74bb66073e00318ec54dbe4f9b7755 100644 (file)
@@ -267,14 +267,12 @@ static void __es_find_extent_range(struct inode *inode,
 
        /* see if the extent has been cached */
        es->es_lblk = es->es_len = es->es_pblk = 0;
-       if (tree->cache_es) {
-               es1 = tree->cache_es;
-               if (in_range(lblk, es1->es_lblk, es1->es_len)) {
-                       es_debug("%u cached by [%u/%u) %llu %x\n",
-                                lblk, es1->es_lblk, es1->es_len,
-                                ext4_es_pblock(es1), ext4_es_status(es1));
-                       goto out;
-               }
+       es1 = READ_ONCE(tree->cache_es);
+       if (es1 && in_range(lblk, es1->es_lblk, es1->es_len)) {
+               es_debug("%u cached by [%u/%u) %llu %x\n",
+                        lblk, es1->es_lblk, es1->es_len,
+                        ext4_es_pblock(es1), ext4_es_status(es1));
+               goto out;
        }
 
        es1 = __es_tree_search(&tree->root, lblk);
@@ -293,7 +291,7 @@ out:
        }
 
        if (es1 && matching_fn(es1)) {
-               tree->cache_es = es1;
+               WRITE_ONCE(tree->cache_es, es1);
                es->es_lblk = es1->es_lblk;
                es->es_len = es1->es_len;
                es->es_pblk = es1->es_pblk;
@@ -931,14 +929,12 @@ int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk,
 
        /* find extent in cache firstly */
        es->es_lblk = es->es_len = es->es_pblk = 0;
-       if (tree->cache_es) {
-               es1 = tree->cache_es;
-               if (in_range(lblk, es1->es_lblk, es1->es_len)) {
-                       es_debug("%u cached by [%u/%u)\n",
-                                lblk, es1->es_lblk, es1->es_len);
-                       found = 1;
-                       goto out;
-               }
+       es1 = READ_ONCE(tree->cache_es);
+       if (es1 && in_range(lblk, es1->es_lblk, es1->es_len)) {
+               es_debug("%u cached by [%u/%u)\n",
+                        lblk, es1->es_lblk, es1->es_len);
+               found = 1;
+               goto out;
        }
 
        node = tree->root.rb_node;
index f65fdb27ce141a6f8e0c07a1574a14a1fb75a65c..2a143209aa0cb2c2191c078688f474d65e71ee1e 100644 (file)
@@ -108,6 +108,13 @@ static int ext4_fsync_journal(struct inode *inode, bool datasync,
        journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
        tid_t commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid;
 
+       /*
+        * Fastcommit does not really support fsync on directories or other
+        * special files. Force a full commit.
+        */
+       if (!S_ISREG(inode->i_mode))
+               return ext4_force_commit(inode->i_sb);
+
        if (journal->j_flags & JBD2_BARRIER &&
            !jbd2_trans_will_send_data_barrier(journal, commit_tid))
                *needs_barrier = true;
index 147b5241dd94fe844ceb2637a8bc68dba428187f..46c3423ddfa17e5363d451d7351de4d8aba14bc7 100644 (file)
@@ -277,7 +277,11 @@ static int __ext4fs_dirhash(const struct inode *dir, const char *name, int len,
        }
        default:
                hinfo->hash = 0;
-               return -1;
+               hinfo->minor_hash = 0;
+               ext4_warning(dir->i_sb,
+                            "invalid/unsupported hash tree version %u",
+                            hinfo->hash_version);
+               return -EINVAL;
        }
        hash = hash & ~1;
        if (hash == (EXT4_HTREE_EOF_32BIT << 1))
index 787ab89c2c265ffbf0aa294afbce2734914795e1..754f961cd9fdfbccb3b1280b40a56bcb3b066454 100644 (file)
@@ -91,7 +91,7 @@ static int ext4_validate_inode_bitmap(struct super_block *sb,
 
        if (buffer_verified(bh))
                return 0;
-       if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp))
+       if (!grp || EXT4_MB_GRP_IBITMAP_CORRUPT(grp))
                return -EFSCORRUPTED;
 
        ext4_lock_group(sb, block_group);
@@ -293,7 +293,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
        }
        if (!(sbi->s_mount_state & EXT4_FC_REPLAY)) {
                grp = ext4_get_group_info(sb, block_group);
-               if (unlikely(EXT4_MB_GRP_IBITMAP_CORRUPT(grp))) {
+               if (!grp || unlikely(EXT4_MB_GRP_IBITMAP_CORRUPT(grp))) {
                        fatal = -EFSCORRUPTED;
                        goto error_return;
                }
@@ -1046,7 +1046,7 @@ got_group:
                         * Skip groups with already-known suspicious inode
                         * tables
                         */
-                       if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp))
+                       if (!grp || EXT4_MB_GRP_IBITMAP_CORRUPT(grp))
                                goto next_group;
                }
 
@@ -1183,6 +1183,10 @@ got:
 
                if (!(sbi->s_mount_state & EXT4_FC_REPLAY)) {
                        grp = ext4_get_group_info(sb, group);
+                       if (!grp) {
+                               err = -EFSCORRUPTED;
+                               goto out;
+                       }
                        down_read(&grp->alloc_sem); /*
                                                     * protect vs itable
                                                     * lazyinit
@@ -1526,7 +1530,7 @@ int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
        }
 
        gdp = ext4_get_group_desc(sb, group, &group_desc_bh);
-       if (!gdp)
+       if (!gdp || !grp)
                goto out;
 
        /*
index 859bc4e2c9b0af3a98e0b33dd4a0eac94e0a9585..5854bd5a33526807dc6194e7043ad16fe4d389f9 100644 (file)
@@ -34,6 +34,7 @@ static int get_max_inline_xattr_value_size(struct inode *inode,
        struct ext4_xattr_ibody_header *header;
        struct ext4_xattr_entry *entry;
        struct ext4_inode *raw_inode;
+       void *end;
        int free, min_offs;
 
        if (!EXT4_INODE_HAS_XATTR_SPACE(inode))
@@ -57,14 +58,23 @@ static int get_max_inline_xattr_value_size(struct inode *inode,
        raw_inode = ext4_raw_inode(iloc);
        header = IHDR(inode, raw_inode);
        entry = IFIRST(header);
+       end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
 
        /* Compute min_offs. */
-       for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
+       while (!IS_LAST_ENTRY(entry)) {
+               void *next = EXT4_XATTR_NEXT(entry);
+
+               if (next >= end) {
+                       EXT4_ERROR_INODE(inode,
+                                        "corrupt xattr in inline inode");
+                       return 0;
+               }
                if (!entry->e_value_inum && entry->e_value_size) {
                        size_t offs = le16_to_cpu(entry->e_value_offs);
                        if (offs < min_offs)
                                min_offs = offs;
                }
+               entry = next;
        }
        free = min_offs -
                ((void *)entry - (void *)IFIRST(header)) - sizeof(__u32);
@@ -350,7 +360,7 @@ static int ext4_update_inline_data(handle_t *handle, struct inode *inode,
 
        error = ext4_xattr_ibody_get(inode, i.name_index, i.name,
                                     value, len);
-       if (error == -ENODATA)
+       if (error < 0)
                goto out;
 
        BUFFER_TRACE(is.iloc.bh, "get_write_access");
@@ -1175,6 +1185,7 @@ static int ext4_finish_convert_inline_dir(handle_t *handle,
                ext4_initialize_dirent_tail(dir_block,
                                            inode->i_sb->s_blocksize);
        set_buffer_uptodate(dir_block);
+       unlock_buffer(dir_block);
        err = ext4_handle_dirty_dirblock(handle, inode, dir_block);
        if (err)
                return err;
@@ -1249,6 +1260,7 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,
        if (!S_ISDIR(inode->i_mode)) {
                memcpy(data_bh->b_data, buf, inline_size);
                set_buffer_uptodate(data_bh);
+               unlock_buffer(data_bh);
                error = ext4_handle_dirty_metadata(handle,
                                                   inode, data_bh);
        } else {
@@ -1256,7 +1268,6 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,
                                                       buf, inline_size);
        }
 
-       unlock_buffer(data_bh);
 out_restore:
        if (error)
                ext4_restore_inline_data(handle, inode, iloc, buf, inline_size);
index 0d5ba922e411f88f05a3e698bd62bfd988e514cd..02de439bf1f04ee7b9ab25bc2caf4c4e1fce610a 100644 (file)
@@ -2783,11 +2783,12 @@ static int ext4_writepages(struct address_space *mapping,
                .can_map = 1,
        };
        int ret;
+       int alloc_ctx;
 
        if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
                return -EIO;
 
-       percpu_down_read(&EXT4_SB(sb)->s_writepages_rwsem);
+       alloc_ctx = ext4_writepages_down_read(sb);
        ret = ext4_do_writepages(&mpd);
        /*
         * For data=journal writeback we could have come across pages marked
@@ -2796,7 +2797,7 @@ static int ext4_writepages(struct address_space *mapping,
         */
        if (!ret && mpd.journalled_more_data)
                ret = ext4_do_writepages(&mpd);
-       percpu_up_read(&EXT4_SB(sb)->s_writepages_rwsem);
+       ext4_writepages_up_read(sb, alloc_ctx);
 
        return ret;
 }
@@ -2824,17 +2825,18 @@ static int ext4_dax_writepages(struct address_space *mapping,
        long nr_to_write = wbc->nr_to_write;
        struct inode *inode = mapping->host;
        struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
+       int alloc_ctx;
 
        if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
                return -EIO;
 
-       percpu_down_read(&sbi->s_writepages_rwsem);
+       alloc_ctx = ext4_writepages_down_read(inode->i_sb);
        trace_ext4_writepages(inode, wbc);
 
        ret = dax_writeback_mapping_range(mapping, sbi->s_daxdev, wbc);
        trace_ext4_writepages_result(inode, wbc, ret,
                                     nr_to_write - wbc->nr_to_write);
-       percpu_up_read(&sbi->s_writepages_rwsem);
+       ext4_writepages_up_read(inode->i_sb, alloc_ctx);
        return ret;
 }
 
@@ -3375,7 +3377,7 @@ static int ext4_iomap_overwrite_begin(struct inode *inode, loff_t offset,
         */
        flags &= ~IOMAP_WRITE;
        ret = ext4_iomap_begin(inode, offset, length, flags, iomap, srcmap);
-       WARN_ON_ONCE(iomap->type != IOMAP_MAPPED);
+       WARN_ON_ONCE(!ret && iomap->type != IOMAP_MAPPED);
        return ret;
 }
 
@@ -4639,6 +4641,24 @@ static inline void ext4_inode_set_iversion_queried(struct inode *inode, u64 val)
                inode_set_iversion_queried(inode, val);
 }
 
+static const char *check_igot_inode(struct inode *inode, ext4_iget_flags flags)
+
+{
+       if (flags & EXT4_IGET_EA_INODE) {
+               if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL))
+                       return "missing EA_INODE flag";
+               if (ext4_test_inode_state(inode, EXT4_STATE_XATTR) ||
+                   EXT4_I(inode)->i_file_acl)
+                       return "ea_inode with extended attributes";
+       } else {
+               if ((EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL))
+                       return "unexpected EA_INODE flag";
+       }
+       if (is_bad_inode(inode) && !(flags & EXT4_IGET_BAD))
+               return "unexpected bad inode w/o EXT4_IGET_BAD";
+       return NULL;
+}
+
 struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
                          ext4_iget_flags flags, const char *function,
                          unsigned int line)
@@ -4648,6 +4668,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
        struct ext4_inode_info *ei;
        struct ext4_super_block *es = EXT4_SB(sb)->s_es;
        struct inode *inode;
+       const char *err_str;
        journal_t *journal = EXT4_SB(sb)->s_journal;
        long ret;
        loff_t size;
@@ -4675,8 +4696,14 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
        inode = iget_locked(sb, ino);
        if (!inode)
                return ERR_PTR(-ENOMEM);
-       if (!(inode->i_state & I_NEW))
+       if (!(inode->i_state & I_NEW)) {
+               if ((err_str = check_igot_inode(inode, flags)) != NULL) {
+                       ext4_error_inode(inode, function, line, 0, err_str);
+                       iput(inode);
+                       return ERR_PTR(-EFSCORRUPTED);
+               }
                return inode;
+       }
 
        ei = EXT4_I(inode);
        iloc.bh = NULL;
@@ -4942,10 +4969,9 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
        if (IS_CASEFOLDED(inode) && !ext4_has_feature_casefold(inode->i_sb))
                ext4_error_inode(inode, function, line, 0,
                                 "casefold flag without casefold feature");
-       if (is_bad_inode(inode) && !(flags & EXT4_IGET_BAD)) {
-               ext4_error_inode(inode, function, line, 0,
-                                "bad inode without EXT4_IGET_BAD flag");
-               ret = -EUCLEAN;
+       if ((err_str = check_igot_inode(inode, flags)) != NULL) {
+               ext4_error_inode(inode, function, line, 0, err_str);
+               ret = -EFSCORRUPTED;
                goto bad_inode;
        }
 
@@ -5928,7 +5954,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
        journal_t *journal;
        handle_t *handle;
        int err;
-       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+       int alloc_ctx;
 
        /*
         * We have to be very careful here: changing a data block's
@@ -5966,7 +5992,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
                }
        }
 
-       percpu_down_write(&sbi->s_writepages_rwsem);
+       alloc_ctx = ext4_writepages_down_write(inode->i_sb);
        jbd2_journal_lock_updates(journal);
 
        /*
@@ -5983,7 +6009,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
                err = jbd2_journal_flush(journal, 0);
                if (err < 0) {
                        jbd2_journal_unlock_updates(journal);
-                       percpu_up_write(&sbi->s_writepages_rwsem);
+                       ext4_writepages_up_write(inode->i_sb, alloc_ctx);
                        return err;
                }
                ext4_clear_inode_flag(inode, EXT4_INODE_JOURNAL_DATA);
@@ -5991,7 +6017,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
        ext4_set_aops(inode);
 
        jbd2_journal_unlock_updates(journal);
-       percpu_up_write(&sbi->s_writepages_rwsem);
+       ext4_writepages_up_write(inode->i_sb, alloc_ctx);
 
        if (val)
                filemap_invalidate_unlock(inode->i_mapping);
index 78259bddbc4d614daf5b044149386b965b52bbf4..20f67a260df5043b00511088dc2a8bb937293fb6 100644 (file)
@@ -745,6 +745,8 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file,
        MB_CHECK_ASSERT(e4b->bd_info->bb_fragments == fragments);
 
        grp = ext4_get_group_info(sb, e4b->bd_group);
+       if (!grp)
+               return NULL;
        list_for_each(cur, &grp->bb_prealloc_list) {
                ext4_group_t groupnr;
                struct ext4_prealloc_space *pa;
@@ -1060,9 +1062,9 @@ mb_set_largest_free_order(struct super_block *sb, struct ext4_group_info *grp)
 
 static noinline_for_stack
 void ext4_mb_generate_buddy(struct super_block *sb,
-                               void *buddy, void *bitmap, ext4_group_t group)
+                           void *buddy, void *bitmap, ext4_group_t group,
+                           struct ext4_group_info *grp)
 {
-       struct ext4_group_info *grp = ext4_get_group_info(sb, group);
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        ext4_grpblk_t max = EXT4_CLUSTERS_PER_GROUP(sb);
        ext4_grpblk_t i = 0;
@@ -1181,6 +1183,8 @@ static int ext4_mb_init_cache(struct page *page, char *incore, gfp_t gfp)
                        break;
 
                grinfo = ext4_get_group_info(sb, group);
+               if (!grinfo)
+                       continue;
                /*
                 * If page is uptodate then we came here after online resize
                 * which added some new uninitialized group info structs, so
@@ -1246,6 +1250,10 @@ static int ext4_mb_init_cache(struct page *page, char *incore, gfp_t gfp)
                                group, page->index, i * blocksize);
                        trace_ext4_mb_buddy_bitmap_load(sb, group);
                        grinfo = ext4_get_group_info(sb, group);
+                       if (!grinfo) {
+                               err = -EFSCORRUPTED;
+                               goto out;
+                       }
                        grinfo->bb_fragments = 0;
                        memset(grinfo->bb_counters, 0,
                               sizeof(*grinfo->bb_counters) *
@@ -1256,7 +1264,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore, gfp_t gfp)
                        ext4_lock_group(sb, group);
                        /* init the buddy */
                        memset(data, 0xff, blocksize);
-                       ext4_mb_generate_buddy(sb, data, incore, group);
+                       ext4_mb_generate_buddy(sb, data, incore, group, grinfo);
                        ext4_unlock_group(sb, group);
                        incore = NULL;
                } else {
@@ -1370,6 +1378,9 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group, gfp_t gfp)
        might_sleep();
        mb_debug(sb, "init group %u\n", group);
        this_grp = ext4_get_group_info(sb, group);
+       if (!this_grp)
+               return -EFSCORRUPTED;
+
        /*
         * This ensures that we don't reinit the buddy cache
         * page which map to the group from which we are already
@@ -1444,6 +1455,8 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
 
        blocks_per_page = PAGE_SIZE / sb->s_blocksize;
        grp = ext4_get_group_info(sb, group);
+       if (!grp)
+               return -EFSCORRUPTED;
 
        e4b->bd_blkbits = sb->s_blocksize_bits;
        e4b->bd_info = grp;
@@ -2049,7 +2062,7 @@ static void ext4_mb_check_limits(struct ext4_allocation_context *ac,
        if (bex->fe_len < gex->fe_len)
                return;
 
-       if (finish_group)
+       if (finish_group || ac->ac_found > sbi->s_mb_min_to_scan)
                ext4_mb_use_best_found(ac, e4b);
 }
 
@@ -2061,6 +2074,20 @@ static void ext4_mb_check_limits(struct ext4_allocation_context *ac,
  * in the context. Later, the best found extent will be used, if
  * mballoc can't find good enough extent.
  *
+ * The algorithm used is roughly as follows:
+ *
+ * * If free extent found is exactly as big as goal, then
+ *   stop the scan and use it immediately
+ *
+ * * If free extent found is smaller than goal, then keep retrying
+ *   upto a max of sbi->s_mb_max_to_scan times (default 200). After
+ *   that stop scanning and use whatever we have.
+ *
+ * * If free extent found is bigger than goal, then keep retrying
+ *   upto a max of sbi->s_mb_min_to_scan times (default 10) before
+ *   stopping the scan and using the extent.
+ *
+ *
  * FIXME: real allocation policy is to be designed yet!
  */
 static void ext4_mb_measure_extent(struct ext4_allocation_context *ac,
@@ -2159,6 +2186,8 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
        struct ext4_group_info *grp = ext4_get_group_info(ac->ac_sb, group);
        struct ext4_free_extent ex;
 
+       if (!grp)
+               return -EFSCORRUPTED;
        if (!(ac->ac_flags & (EXT4_MB_HINT_TRY_GOAL | EXT4_MB_HINT_GOAL_ONLY)))
                return 0;
        if (grp->bb_free == 0)
@@ -2385,7 +2414,7 @@ static bool ext4_mb_good_group(struct ext4_allocation_context *ac,
 
        BUG_ON(cr < 0 || cr >= 4);
 
-       if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(grp)))
+       if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(grp) || !grp))
                return false;
 
        free = grp->bb_free;
@@ -2454,6 +2483,8 @@ static int ext4_mb_good_group_nolock(struct ext4_allocation_context *ac,
        ext4_grpblk_t free;
        int ret = 0;
 
+       if (!grp)
+               return -EFSCORRUPTED;
        if (sbi->s_mb_stats)
                atomic64_inc(&sbi->s_bal_cX_groups_considered[ac->ac_criteria]);
        if (should_lock) {
@@ -2534,7 +2565,7 @@ ext4_group_t ext4_mb_prefetch(struct super_block *sb, ext4_group_t group,
                 * prefetch once, so we avoid getblk() call, which can
                 * be expensive.
                 */
-               if (!EXT4_MB_GRP_TEST_AND_SET_READ(grp) &&
+               if (gdp && grp && !EXT4_MB_GRP_TEST_AND_SET_READ(grp) &&
                    EXT4_MB_GRP_NEED_INIT(grp) &&
                    ext4_free_group_clusters(sb, gdp) > 0 &&
                    !(ext4_has_group_desc_csum(sb) &&
@@ -2578,7 +2609,7 @@ void ext4_mb_prefetch_fini(struct super_block *sb, ext4_group_t group,
                gdp = ext4_get_group_desc(sb, group, NULL);
                grp = ext4_get_group_info(sb, group);
 
-               if (EXT4_MB_GRP_NEED_INIT(grp) &&
+               if (grp && gdp && EXT4_MB_GRP_NEED_INIT(grp) &&
                    ext4_free_group_clusters(sb, gdp) > 0 &&
                    !(ext4_has_group_desc_csum(sb) &&
                      (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)))) {
@@ -2837,6 +2868,8 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
                sizeof(struct ext4_group_info);
 
        grinfo = ext4_get_group_info(sb, group);
+       if (!grinfo)
+               return 0;
        /* Load the group info in memory only if not already loaded. */
        if (unlikely(EXT4_MB_GRP_NEED_INIT(grinfo))) {
                err = ext4_mb_load_buddy(sb, group, &e4b);
@@ -2847,7 +2880,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
                buddy_loaded = 1;
        }
 
-       memcpy(&sg, ext4_get_group_info(sb, group), i);
+       memcpy(&sg, grinfo, i);
 
        if (buddy_loaded)
                ext4_mb_unload_buddy(&e4b);
@@ -3208,8 +3241,12 @@ static int ext4_mb_init_backend(struct super_block *sb)
 
 err_freebuddy:
        cachep = get_groupinfo_cache(sb->s_blocksize_bits);
-       while (i-- > 0)
-               kmem_cache_free(cachep, ext4_get_group_info(sb, i));
+       while (i-- > 0) {
+               struct ext4_group_info *grp = ext4_get_group_info(sb, i);
+
+               if (grp)
+                       kmem_cache_free(cachep, grp);
+       }
        i = sbi->s_group_info_size;
        rcu_read_lock();
        group_info = rcu_dereference(sbi->s_group_info);
@@ -3522,6 +3559,8 @@ int ext4_mb_release(struct super_block *sb)
                for (i = 0; i < ngroups; i++) {
                        cond_resched();
                        grinfo = ext4_get_group_info(sb, i);
+                       if (!grinfo)
+                               continue;
                        mb_group_bb_bitmap_free(grinfo);
                        ext4_lock_group(sb, i);
                        count = ext4_mb_cleanup_pa(grinfo);
@@ -4606,6 +4645,8 @@ static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap,
        struct ext4_free_data *entry;
 
        grp = ext4_get_group_info(sb, group);
+       if (!grp)
+               return;
        n = rb_first(&(grp->bb_free_root));
 
        while (n) {
@@ -4633,6 +4674,9 @@ void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
        int preallocated = 0;
        int len;
 
+       if (!grp)
+               return;
+
        /* all form of preallocation discards first load group,
         * so the only competing code is preallocation use.
         * we don't need any locking here
@@ -4869,6 +4913,8 @@ adjust_bex:
 
        ei = EXT4_I(ac->ac_inode);
        grp = ext4_get_group_info(sb, ac->ac_b_ex.fe_group);
+       if (!grp)
+               return;
 
        pa->pa_node_lock.inode_lock = &ei->i_prealloc_lock;
        pa->pa_inode = ac->ac_inode;
@@ -4918,6 +4964,8 @@ ext4_mb_new_group_pa(struct ext4_allocation_context *ac)
        atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
 
        grp = ext4_get_group_info(sb, ac->ac_b_ex.fe_group);
+       if (!grp)
+               return;
        lg = ac->ac_lg;
        BUG_ON(lg == NULL);
 
@@ -5013,7 +5061,11 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b,
        trace_ext4_mb_release_group_pa(sb, pa);
        BUG_ON(pa->pa_deleted == 0);
        ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
-       BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
+       if (unlikely(group != e4b->bd_group && pa->pa_len != 0)) {
+               ext4_warning(sb, "bad group: expected %u, group %u, pa_start %llu",
+                            e4b->bd_group, group, pa->pa_pstart);
+               return 0;
+       }
        mb_free_blocks(pa->pa_inode, e4b, bit, pa->pa_len);
        atomic_add(pa->pa_len, &EXT4_SB(sb)->s_mb_discarded);
        trace_ext4_mballoc_discard(sb, NULL, group, bit, pa->pa_len);
@@ -5043,6 +5095,8 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
        int err;
        int free = 0;
 
+       if (!grp)
+               return 0;
        mb_debug(sb, "discard preallocation for group %u\n", group);
        if (list_empty(&grp->bb_prealloc_list))
                goto out_dbg;
@@ -5297,6 +5351,9 @@ static inline void ext4_mb_show_pa(struct super_block *sb)
                struct ext4_prealloc_space *pa;
                ext4_grpblk_t start;
                struct list_head *cur;
+
+               if (!grp)
+                       continue;
                ext4_lock_group(sb, i);
                list_for_each(cur, &grp->bb_prealloc_list) {
                        pa = list_entry(cur, struct ext4_prealloc_space,
@@ -6064,6 +6121,7 @@ static void ext4_mb_clear_bb(handle_t *handle, struct inode *inode,
        struct buffer_head *bitmap_bh = NULL;
        struct super_block *sb = inode->i_sb;
        struct ext4_group_desc *gdp;
+       struct ext4_group_info *grp;
        unsigned int overflow;
        ext4_grpblk_t bit;
        struct buffer_head *gd_bh;
@@ -6089,8 +6147,8 @@ do_more:
        overflow = 0;
        ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
 
-       if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(
-                       ext4_get_group_info(sb, block_group))))
+       grp = ext4_get_group_info(sb, block_group);
+       if (unlikely(!grp || EXT4_MB_GRP_BBITMAP_CORRUPT(grp)))
                return;
 
        /*
@@ -6692,6 +6750,8 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
 
        for (group = first_group; group <= last_group; group++) {
                grp = ext4_get_group_info(sb, group);
+               if (!grp)
+                       continue;
                /* We only do this if the grp has never been initialized */
                if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
                        ret = ext4_mb_init_group(sb, group, GFP_NOFS);
index a19a9661646ebfa87cf0813bd29dd7eda2f668f7..d98ac2af8199f1ecc5f9d10036a02c90f5ff7855 100644 (file)
@@ -408,7 +408,6 @@ static int free_ext_block(handle_t *handle, struct inode *inode)
 
 int ext4_ext_migrate(struct inode *inode)
 {
-       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        handle_t *handle;
        int retval = 0, i;
        __le32 *i_data;
@@ -418,6 +417,7 @@ int ext4_ext_migrate(struct inode *inode)
        unsigned long max_entries;
        __u32 goal, tmp_csum_seed;
        uid_t owner[2];
+       int alloc_ctx;
 
        /*
         * If the filesystem does not support extents, or the inode
@@ -434,7 +434,7 @@ int ext4_ext_migrate(struct inode *inode)
                 */
                return retval;
 
-       percpu_down_write(&sbi->s_writepages_rwsem);
+       alloc_ctx = ext4_writepages_down_write(inode->i_sb);
 
        /*
         * Worst case we can touch the allocation bitmaps and a block
@@ -586,7 +586,7 @@ out_tmp_inode:
        unlock_new_inode(tmp_inode);
        iput(tmp_inode);
 out_unlock:
-       percpu_up_write(&sbi->s_writepages_rwsem);
+       ext4_writepages_up_write(inode->i_sb, alloc_ctx);
        return retval;
 }
 
@@ -605,6 +605,7 @@ int ext4_ind_migrate(struct inode *inode)
        ext4_fsblk_t                    blk;
        handle_t                        *handle;
        int                             ret, ret2 = 0;
+       int                             alloc_ctx;
 
        if (!ext4_has_feature_extents(inode->i_sb) ||
            (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
@@ -621,7 +622,7 @@ int ext4_ind_migrate(struct inode *inode)
        if (test_opt(inode->i_sb, DELALLOC))
                ext4_alloc_da_blocks(inode);
 
-       percpu_down_write(&sbi->s_writepages_rwsem);
+       alloc_ctx = ext4_writepages_down_write(inode->i_sb);
 
        handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1);
        if (IS_ERR(handle)) {
@@ -665,6 +666,6 @@ errout:
        ext4_journal_stop(handle);
        up_write(&EXT4_I(inode)->i_data_sem);
 out_unlock:
-       percpu_up_write(&sbi->s_writepages_rwsem);
+       ext4_writepages_up_write(inode->i_sb, alloc_ctx);
        return ret;
 }
index 4022bc713421555741ab6b28c4027db6a77efc60..0aaf38ffcb6ec6600ae91b5bd41e2b6fe3fc501a 100644 (file)
@@ -39,28 +39,36 @@ static void ext4_mmp_csum_set(struct super_block *sb, struct mmp_struct *mmp)
  * Write the MMP block using REQ_SYNC to try to get the block on-disk
  * faster.
  */
-static int write_mmp_block(struct super_block *sb, struct buffer_head *bh)
+static int write_mmp_block_thawed(struct super_block *sb,
+                                 struct buffer_head *bh)
 {
        struct mmp_struct *mmp = (struct mmp_struct *)(bh->b_data);
 
-       /*
-        * We protect against freezing so that we don't create dirty buffers
-        * on frozen filesystem.
-        */
-       sb_start_write(sb);
        ext4_mmp_csum_set(sb, mmp);
        lock_buffer(bh);
        bh->b_end_io = end_buffer_write_sync;
        get_bh(bh);
        submit_bh(REQ_OP_WRITE | REQ_SYNC | REQ_META | REQ_PRIO, bh);
        wait_on_buffer(bh);
-       sb_end_write(sb);
        if (unlikely(!buffer_uptodate(bh)))
                return -EIO;
-
        return 0;
 }
 
+static int write_mmp_block(struct super_block *sb, struct buffer_head *bh)
+{
+       int err;
+
+       /*
+        * We protect against freezing so that we don't create dirty buffers
+        * on frozen filesystem.
+        */
+       sb_start_write(sb);
+       err = write_mmp_block_thawed(sb, bh);
+       sb_end_write(sb);
+       return err;
+}
+
 /*
  * Read the MMP block. It _must_ be read from disk and hence we clear the
  * uptodate flag on the buffer.
@@ -344,7 +352,11 @@ skip:
        seq = mmp_new_seq();
        mmp->mmp_seq = cpu_to_le32(seq);
 
-       retval = write_mmp_block(sb, bh);
+       /*
+        * On mount / remount we are protected against fs freezing (by s_umount
+        * semaphore) and grabbing freeze protection upsets lockdep
+        */
+       retval = write_mmp_block_thawed(sb, bh);
        if (retval)
                goto failed;
 
index a5010b5b8a8c11b5909c137b649fe5d04849d832..45b579805c95428238b792de8182bc2e7e52a18c 100644 (file)
@@ -674,7 +674,7 @@ static struct stats dx_show_leaf(struct inode *dir,
                                len = de->name_len;
                                if (!IS_ENCRYPTED(dir)) {
                                        /* Directory is not encrypted */
-                                       ext4fs_dirhash(dir, de->name,
+                                       (void) ext4fs_dirhash(dir, de->name,
                                                de->name_len, &h);
                                        printk("%*.s:(U)%x.%u ", len,
                                               name, h.hash,
@@ -709,8 +709,9 @@ static struct stats dx_show_leaf(struct inode *dir,
                                        if (IS_CASEFOLDED(dir))
                                                h.hash = EXT4_DIRENT_HASH(de);
                                        else
-                                               ext4fs_dirhash(dir, de->name,
-                                                      de->name_len, &h);
+                                               (void) ext4fs_dirhash(dir,
+                                                       de->name,
+                                                       de->name_len, &h);
                                        printk("%*.s:(E)%x.%u ", len, name,
                                               h.hash, (unsigned) ((char *) de
                                                                   - base));
@@ -720,7 +721,8 @@ static struct stats dx_show_leaf(struct inode *dir,
 #else
                                int len = de->name_len;
                                char *name = de->name;
-                               ext4fs_dirhash(dir, de->name, de->name_len, &h);
+                               (void) ext4fs_dirhash(dir, de->name,
+                                                     de->name_len, &h);
                                printk("%*.s:%x.%u ", len, name, h.hash,
                                       (unsigned) ((char *) de - base));
 #endif
@@ -849,8 +851,14 @@ dx_probe(struct ext4_filename *fname, struct inode *dir,
        hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed;
        /* hash is already computed for encrypted casefolded directory */
        if (fname && fname_name(fname) &&
-                               !(IS_ENCRYPTED(dir) && IS_CASEFOLDED(dir)))
-               ext4fs_dirhash(dir, fname_name(fname), fname_len(fname), hinfo);
+           !(IS_ENCRYPTED(dir) && IS_CASEFOLDED(dir))) {
+               int ret = ext4fs_dirhash(dir, fname_name(fname),
+                                        fname_len(fname), hinfo);
+               if (ret < 0) {
+                       ret_err = ERR_PTR(ret);
+                       goto fail;
+               }
+       }
        hash = hinfo->hash;
 
        if (root->info.unused_flags & 1) {
@@ -1111,7 +1119,12 @@ static int htree_dirblock_to_tree(struct file *dir_file,
                                hinfo->minor_hash = 0;
                        }
                } else {
-                       ext4fs_dirhash(dir, de->name, de->name_len, hinfo);
+                       err = ext4fs_dirhash(dir, de->name,
+                                            de->name_len, hinfo);
+                       if (err < 0) {
+                               count = err;
+                               goto errout;
+                       }
                }
                if ((hinfo->hash < start_hash) ||
                    ((hinfo->hash == start_hash) &&
@@ -1313,8 +1326,12 @@ static int dx_make_map(struct inode *dir, struct buffer_head *bh,
                if (de->name_len && de->inode) {
                        if (ext4_hash_in_dirent(dir))
                                h.hash = EXT4_DIRENT_HASH(de);
-                       else
-                               ext4fs_dirhash(dir, de->name, de->name_len, &h);
+                       else {
+                               int err = ext4fs_dirhash(dir, de->name,
+                                                    de->name_len, &h);
+                               if (err < 0)
+                                       return err;
+                       }
                        map_tail--;
                        map_tail->hash = h.hash;
                        map_tail->offs = ((char *) de - base)>>2;
@@ -1452,10 +1469,9 @@ int ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,
        hinfo->hash_version = DX_HASH_SIPHASH;
        hinfo->seed = NULL;
        if (cf_name->name)
-               ext4fs_dirhash(dir, cf_name->name, cf_name->len, hinfo);
+               return ext4fs_dirhash(dir, cf_name->name, cf_name->len, hinfo);
        else
-               ext4fs_dirhash(dir, iname->name, iname->len, hinfo);
-       return 0;
+               return ext4fs_dirhash(dir, iname->name, iname->len, hinfo);
 }
 #endif
 
@@ -2298,10 +2314,15 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
        fname->hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
 
        /* casefolded encrypted hashes are computed on fname setup */
-       if (!ext4_hash_in_dirent(dir))
-               ext4fs_dirhash(dir, fname_name(fname),
-                               fname_len(fname), &fname->hinfo);
-
+       if (!ext4_hash_in_dirent(dir)) {
+               int err = ext4fs_dirhash(dir, fname_name(fname),
+                                        fname_len(fname), &fname->hinfo);
+               if (err < 0) {
+                       brelse(bh2);
+                       brelse(bh);
+                       return err;
+               }
+       }
        memset(frames, 0, sizeof(frames));
        frame = frames;
        frame->entries = entries;
index d39f386e9baf6ad0daad9d5a5c4f69c5172e78aa..56a5d1c469fc9cf31b36e25c7e874dfdd25b25f8 100644 (file)
@@ -1048,6 +1048,8 @@ void ext4_mark_group_bitmap_corrupted(struct super_block *sb,
        struct ext4_group_desc *gdp = ext4_get_group_desc(sb, group, NULL);
        int ret;
 
+       if (!grp || !gdp)
+               return;
        if (flags & EXT4_GROUP_INFO_BBITMAP_CORRUPT) {
                ret = ext4_test_and_set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT,
                                            &grp->bb_state);
@@ -3238,11 +3240,9 @@ static __le16 ext4_group_desc_csum(struct super_block *sb, __u32 block_group,
        crc = crc16(crc, (__u8 *)gdp, offset);
        offset += sizeof(gdp->bg_checksum); /* skip checksum */
        /* for checksum of struct ext4_group_desc do the rest...*/
-       if (ext4_has_feature_64bit(sb) &&
-           offset < le16_to_cpu(sbi->s_es->s_desc_size))
+       if (ext4_has_feature_64bit(sb) && offset < sbi->s_desc_size)
                crc = crc16(crc, (__u8 *)gdp + offset,
-                           le16_to_cpu(sbi->s_es->s_desc_size) -
-                               offset);
+                           sbi->s_desc_size - offset);
 
 out:
        return cpu_to_le16(crc);
@@ -5684,8 +5684,9 @@ static int ext4_fill_super(struct super_block *sb, struct fs_context *fc)
                descr = "out journal";
 
        if (___ratelimit(&ext4_mount_msg_ratelimit, "EXT4-fs mount"))
-               ext4_msg(sb, KERN_INFO, "mounted filesystem %pU with%s. "
-                        "Quota mode: %s.", &sb->s_uuid, descr,
+               ext4_msg(sb, KERN_INFO, "mounted filesystem %pU %s with%s. "
+                        "Quota mode: %s.", &sb->s_uuid,
+                        sb_rdonly(sb) ? "ro" : "r/w", descr,
                         ext4_quota_mode(sb));
 
        /* Update the s_overhead_clusters if necessary */
@@ -6387,6 +6388,7 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
        struct ext4_mount_options old_opts;
        ext4_group_t g;
        int err = 0;
+       int enable_rw = 0;
 #ifdef CONFIG_QUOTA
        int enable_quota = 0;
        int i, j;
@@ -6573,7 +6575,7 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
                        if (err)
                                goto restore_opts;
 
-                       sb->s_flags &= ~SB_RDONLY;
+                       enable_rw = 1;
                        if (ext4_has_feature_mmp(sb)) {
                                err = ext4_multi_mount_protect(sb,
                                                le64_to_cpu(es->s_mmp_block));
@@ -6586,18 +6588,6 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
                }
        }
 
-       /*
-        * Reinitialize lazy itable initialization thread based on
-        * current settings
-        */
-       if (sb_rdonly(sb) || !test_opt(sb, INIT_INODE_TABLE))
-               ext4_unregister_li_request(sb);
-       else {
-               ext4_group_t first_not_zeroed;
-               first_not_zeroed = ext4_has_uninit_itable(sb);
-               ext4_register_li_request(sb, first_not_zeroed);
-       }
-
        /*
         * Handle creation of system zone data early because it can fail.
         * Releasing of existing data is done when we are sure remount will
@@ -6616,9 +6606,6 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
        }
 
 #ifdef CONFIG_QUOTA
-       /* Release old quota file names */
-       for (i = 0; i < EXT4_MAXQUOTAS; i++)
-               kfree(old_opts.s_qf_names[i]);
        if (enable_quota) {
                if (sb_any_quota_suspended(sb))
                        dquot_resume(sb, -1);
@@ -6628,16 +6615,41 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
                                goto restore_opts;
                }
        }
+       /* Release old quota file names */
+       for (i = 0; i < EXT4_MAXQUOTAS; i++)
+               kfree(old_opts.s_qf_names[i]);
 #endif
        if (!test_opt(sb, BLOCK_VALIDITY) && sbi->s_system_blks)
                ext4_release_system_zone(sb);
 
+       if (enable_rw)
+               sb->s_flags &= ~SB_RDONLY;
+
+       /*
+        * Reinitialize lazy itable initialization thread based on
+        * current settings
+        */
+       if (sb_rdonly(sb) || !test_opt(sb, INIT_INODE_TABLE))
+               ext4_unregister_li_request(sb);
+       else {
+               ext4_group_t first_not_zeroed;
+               first_not_zeroed = ext4_has_uninit_itable(sb);
+               ext4_register_li_request(sb, first_not_zeroed);
+       }
+
        if (!ext4_has_feature_mmp(sb) || sb_rdonly(sb))
                ext4_stop_mmpd(sbi);
 
        return 0;
 
 restore_opts:
+       /*
+        * If there was a failing r/w to ro transition, we may need to
+        * re-enable quota
+        */
+       if ((sb->s_flags & SB_RDONLY) && !(old_sb_flags & SB_RDONLY) &&
+           sb_any_quota_suspended(sb))
+               dquot_resume(sb, -1);
        sb->s_flags = old_sb_flags;
        sbi->s_mount_opt = old_opts.s_mount_opt;
        sbi->s_mount_opt2 = old_opts.s_mount_opt2;
@@ -6678,8 +6690,9 @@ static int ext4_reconfigure(struct fs_context *fc)
        if (ret < 0)
                return ret;
 
-       ext4_msg(sb, KERN_INFO, "re-mounted %pU. Quota mode: %s.",
-                &sb->s_uuid, ext4_quota_mode(sb));
+       ext4_msg(sb, KERN_INFO, "re-mounted %pU %s. Quota mode: %s.",
+                &sb->s_uuid, sb_rdonly(sb) ? "ro" : "r/w",
+                ext4_quota_mode(sb));
 
        return 0;
 }
index dadad29bd81bf0739273c1283592a246967b9234..13d7f17a9c8cce74442e07aa1c67adb2133c737c 100644 (file)
@@ -121,7 +121,11 @@ ext4_expand_inode_array(struct ext4_xattr_inode_array **ea_inode_array,
 #ifdef CONFIG_LOCKDEP
 void ext4_xattr_inode_set_class(struct inode *ea_inode)
 {
+       struct ext4_inode_info *ei = EXT4_I(ea_inode);
+
        lockdep_set_subclass(&ea_inode->i_rwsem, 1);
+       (void) ei;      /* shut up clang warning if !CONFIG_LOCKDEP */
+       lockdep_set_subclass(&ei->i_data_sem, I_DATA_SEM_EA);
 }
 #endif
 
@@ -433,7 +437,7 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
                return -EFSCORRUPTED;
        }
 
-       inode = ext4_iget(parent->i_sb, ea_ino, EXT4_IGET_NORMAL);
+       inode = ext4_iget(parent->i_sb, ea_ino, EXT4_IGET_EA_INODE);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                ext4_error(parent->i_sb,
@@ -441,23 +445,6 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
                           err);
                return err;
        }
-
-       if (is_bad_inode(inode)) {
-               ext4_error(parent->i_sb,
-                          "error while reading EA inode %lu is_bad_inode",
-                          ea_ino);
-               err = -EIO;
-               goto error;
-       }
-
-       if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) {
-               ext4_error(parent->i_sb,
-                          "EA inode %lu does not have EXT4_EA_INODE_FL flag",
-                           ea_ino);
-               err = -EINVAL;
-               goto error;
-       }
-
        ext4_xattr_inode_set_class(inode);
 
        /*
@@ -478,9 +465,6 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
 
        *ea_inode = inode;
        return 0;
-error:
-       iput(inode);
-       return err;
 }
 
 /* Remove entry from mbcache when EA inode is getting evicted */
@@ -1556,11 +1540,11 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value,
 
        while (ce) {
                ea_inode = ext4_iget(inode->i_sb, ce->e_value,
-                                    EXT4_IGET_NORMAL);
-               if (!IS_ERR(ea_inode) &&
-                   !is_bad_inode(ea_inode) &&
-                   (EXT4_I(ea_inode)->i_flags & EXT4_EA_INODE_FL) &&
-                   i_size_read(ea_inode) == value_len &&
+                                    EXT4_IGET_EA_INODE);
+               if (IS_ERR(ea_inode))
+                       goto next_entry;
+               ext4_xattr_inode_set_class(ea_inode);
+               if (i_size_read(ea_inode) == value_len &&
                    !ext4_xattr_inode_read(ea_inode, ea_data, value_len) &&
                    !ext4_xattr_inode_verify_hashes(ea_inode, NULL, ea_data,
                                                    value_len) &&
@@ -1570,9 +1554,8 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value,
                        kvfree(ea_data);
                        return ea_inode;
                }
-
-               if (!IS_ERR(ea_inode))
-                       iput(ea_inode);
+               iput(ea_inode);
+       next_entry:
                ce = mb_cache_entry_find_next(ea_inode_cache, ce);
        }
        kvfree(ea_data);
@@ -2614,6 +2597,7 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
                .in_inode = !!entry->e_value_inum,
        };
        struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode);
+       int needs_kvfree = 0;
        int error;
 
        is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
@@ -2636,7 +2620,7 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
                        error = -ENOMEM;
                        goto out;
                }
-
+               needs_kvfree = 1;
                error = ext4_xattr_inode_get(inode, entry, buffer, value_size);
                if (error)
                        goto out;
@@ -2675,7 +2659,7 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
 
 out:
        kfree(b_entry_name);
-       if (entry->e_value_inum && buffer)
+       if (needs_kvfree && buffer)
                kvfree(buffer);
        if (is)
                brelse(is->iloc.bh);
index 5eed8c2375000833b5ecbbd82751417aed538773..a84bf6444bba958647ce7fd2ddb9c7f7c5287cb3 100644 (file)
@@ -1419,6 +1419,14 @@ static void gfs2_evict_inode(struct inode *inode)
        if (inode->i_nlink || sb_rdonly(sb) || !ip->i_no_addr)
                goto out;
 
+       /*
+        * In case of an incomplete mount, gfs2_evict_inode() may be called for
+        * system files without having an active journal to write to.  In that
+        * case, skip the filesystem evict.
+        */
+       if (!sdp->sd_jdesc)
+               goto out;
+
        gfs2_holder_mark_uninitialized(&gh);
        ret = evict_should_delete(inode, &gh);
        if (ret == SHOULD_DEFER_EVICTION)
index bb94949bc2235d6fc4a8654b3f071ad4a9b13528..04ba95b83d16832680b03cfc3e096987a55d7f19 100644 (file)
@@ -77,9 +77,9 @@ static const unsigned long    nlm_grace_period_min = 0;
 static const unsigned long     nlm_grace_period_max = 240;
 static const unsigned long     nlm_timeout_min = 3;
 static const unsigned long     nlm_timeout_max = 20;
-static const int               nlm_port_min = 0, nlm_port_max = 65535;
 
 #ifdef CONFIG_SYSCTL
+static const int               nlm_port_min = 0, nlm_port_max = 65535;
 static struct ctl_table_header * nlm_sysctl_table;
 #endif
 
index bacad0c57810487f47138a11ffcfc43a043fb4d6..8f3112e71a6a62a489b6796d7065fababa4f3416 100644 (file)
@@ -317,7 +317,7 @@ static int nfs_readdir_folio_array_append(struct folio *folio,
 
        name = nfs_readdir_copy_name(entry->name, entry->len);
 
-       array = kmap_atomic(folio_page(folio, 0));
+       array = kmap_local_folio(folio, 0);
        if (!name)
                goto out;
        ret = nfs_readdir_array_can_expand(array);
@@ -340,7 +340,7 @@ static int nfs_readdir_folio_array_append(struct folio *folio,
                nfs_readdir_array_set_eof(array);
 out:
        *cookie = array->last_cookie;
-       kunmap_atomic(array);
+       kunmap_local(array);
        return ret;
 }
 
@@ -402,7 +402,7 @@ static struct folio *nfs_readdir_folio_get_locked(struct address_space *mapping,
        struct folio *folio;
 
        folio = filemap_grab_folio(mapping, index);
-       if (!folio)
+       if (IS_ERR(folio))
                return NULL;
        nfs_readdir_folio_init_and_validate(folio, cookie, change_attr);
        return folio;
index 18f25ff4bff7ba8889bc7e5e67686bb43a331d17..d3665390c4cb8030348bf067c86efe45bc10f27c 100644 (file)
@@ -5437,10 +5437,18 @@ static bool nfs4_read_plus_not_supported(struct rpc_task *task,
        return false;
 }
 
-static int nfs4_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
+static inline void nfs4_read_plus_scratch_free(struct nfs_pgio_header *hdr)
 {
-       if (hdr->res.scratch)
+       if (hdr->res.scratch) {
                kfree(hdr->res.scratch);
+               hdr->res.scratch = NULL;
+       }
+}
+
+static int nfs4_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
+{
+       nfs4_read_plus_scratch_free(hdr);
+
        if (!nfs4_sequence_done(task, &hdr->res.seq_res))
                return -EAGAIN;
        if (nfs4_read_stateid_changed(task, &hdr->args))
index 7b8f17ee52243171fac7b30284c8986725a8232c..b4fd7a7062d5e8c271e596168e333c54229b63cc 100644 (file)
@@ -153,18 +153,6 @@ static int exports_net_open(struct net *net, struct file *file)
        return 0;
 }
 
-static int exports_proc_open(struct inode *inode, struct file *file)
-{
-       return exports_net_open(current->nsproxy->net_ns, file);
-}
-
-static const struct proc_ops exports_proc_ops = {
-       .proc_open      = exports_proc_open,
-       .proc_read      = seq_read,
-       .proc_lseek     = seq_lseek,
-       .proc_release   = seq_release,
-};
-
 static int exports_nfsd_open(struct inode *inode, struct file *file)
 {
        return exports_net_open(inode->i_sb->s_fs_info, file);
@@ -702,16 +690,11 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred
        if (err != 0 || fd < 0)
                return -EINVAL;
 
-       if (svc_alien_sock(net, fd)) {
-               printk(KERN_ERR "%s: socket net is different to NFSd's one\n", __func__);
-               return -EINVAL;
-       }
-
        err = nfsd_create_serv(net);
        if (err != 0)
                return err;
 
-       err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT, cred);
+       err = svc_addsock(nn->nfsd_serv, net, fd, buf, SIMPLE_TRANSACTION_LIMIT, cred);
 
        if (err >= 0 &&
            !nn->nfsd_serv->sv_nrthreads && !xchg(&nn->keep_active, 1))
@@ -1458,6 +1441,19 @@ static struct file_system_type nfsd_fs_type = {
 MODULE_ALIAS_FS("nfsd");
 
 #ifdef CONFIG_PROC_FS
+
+static int exports_proc_open(struct inode *inode, struct file *file)
+{
+       return exports_net_open(current->nsproxy->net_ns, file);
+}
+
+static const struct proc_ops exports_proc_ops = {
+       .proc_open      = exports_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release,
+};
+
 static int create_proc_exports_entry(void)
 {
        struct proc_dir_entry *entry;
index 4183819ea08290780d7ec04f0eb48da919b91f70..72a906a053dcd2432c54bda87104df5834c0f7f2 100644 (file)
@@ -1365,19 +1365,19 @@ TRACE_EVENT(nfsd_cb_setup,
                __field(u32, cl_id)
                __field(unsigned long, authflavor)
                __sockaddr(addr, clp->cl_cb_conn.cb_addrlen)
-               __array(unsigned char, netid, 8)
+               __string(netid, netid)
        ),
        TP_fast_assign(
                __entry->cl_boot = clp->cl_clientid.cl_boot;
                __entry->cl_id = clp->cl_clientid.cl_id;
-               strlcpy(__entry->netid, netid, sizeof(__entry->netid));
+               __assign_str(netid, netid);
                __entry->authflavor = authflavor;
                __assign_sockaddr(addr, &clp->cl_cb_conn.cb_addr,
                                  clp->cl_cb_conn.cb_addrlen)
        ),
        TP_printk("addr=%pISpc client %08x:%08x proto=%s flavor=%s",
                __get_sockaddr(addr), __entry->cl_boot, __entry->cl_id,
-               __entry->netid, show_nfsd_authflavor(__entry->authflavor))
+               __get_str(netid), show_nfsd_authflavor(__entry->authflavor))
 );
 
 TRACE_EVENT(nfsd_cb_setup_err,
index bb9d471721623607061a86ea666d4e0dedb596dc..db67f8e19344a454dbc8aa8166fe362ef156145d 100644 (file)
@@ -536,7 +536,15 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
 
        inode_lock(inode);
        for (retries = 1;;) {
-               host_err = __nfsd_setattr(dentry, iap);
+               struct iattr attrs;
+
+               /*
+                * notify_change() can alter its iattr argument, making
+                * @iap unsuitable for submission multiple times. Make a
+                * copy for every loop iteration.
+                */
+               attrs = *iap;
+               host_err = __nfsd_setattr(dentry, &attrs);
                if (host_err != -EAGAIN || !retries--)
                        break;
                if (!nfsd_wait_for_delegreturn(rqstp, inode))
index 1310d2d5feb38778188d894fa0bc189c4a7f30e3..a8ce522ac747931575104447288cdbe2ed317d0f 100644 (file)
@@ -917,6 +917,7 @@ void nilfs_evict_inode(struct inode *inode)
        struct nilfs_transaction_info ti;
        struct super_block *sb = inode->i_sb;
        struct nilfs_inode_info *ii = NILFS_I(inode);
+       struct the_nilfs *nilfs;
        int ret;
 
        if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) {
@@ -929,6 +930,23 @@ void nilfs_evict_inode(struct inode *inode)
 
        truncate_inode_pages_final(&inode->i_data);
 
+       nilfs = sb->s_fs_info;
+       if (unlikely(sb_rdonly(sb) || !nilfs->ns_writer)) {
+               /*
+                * If this inode is about to be disposed after the file system
+                * has been degraded to read-only due to file system corruption
+                * or after the writer has been detached, do not make any
+                * changes that cause writes, just clear it.
+                * Do this check after read-locking ns_segctor_sem by
+                * nilfs_transaction_begin() in order to avoid a race with
+                * the writer detach operation.
+                */
+               clear_inode(inode);
+               nilfs_clear_inode(inode);
+               nilfs_transaction_abort(sb);
+               return;
+       }
+
        /* TODO: some of the following operations may fail.  */
        nilfs_truncate_bmap(ii, 0);
        nilfs_mark_inode_dirty(inode);
index 49cfe2ae6d23dff0e593d2faabb5b44b549b1404..993375f0db673112808bab6fe787bfbcc2a4a238 100644 (file)
@@ -65,7 +65,7 @@ int inotify_handle_inode_event(struct fsnotify_mark *inode_mark, u32 mask,
        struct fsnotify_event *fsn_event;
        struct fsnotify_group *group = inode_mark->group;
        int ret;
-       int len = 0;
+       int len = 0, wd;
        int alloc_len = sizeof(struct inotify_event_info);
        struct mem_cgroup *old_memcg;
 
@@ -80,6 +80,13 @@ int inotify_handle_inode_event(struct fsnotify_mark *inode_mark, u32 mask,
        i_mark = container_of(inode_mark, struct inotify_inode_mark,
                              fsn_mark);
 
+       /*
+        * We can be racing with mark being detached. Don't report event with
+        * invalid wd.
+        */
+       wd = READ_ONCE(i_mark->wd);
+       if (wd == -1)
+               return 0;
        /*
         * Whoever is interested in the event, pays for the allocation. Do not
         * trigger OOM killer in the target monitoring memcg as it may have
@@ -110,7 +117,7 @@ int inotify_handle_inode_event(struct fsnotify_mark *inode_mark, u32 mask,
        fsn_event = &event->fse;
        fsnotify_init_event(fsn_event);
        event->mask = mask;
-       event->wd = i_mark->wd;
+       event->wd = wd;
        event->sync_cookie = cookie;
        event->name_len = len;
        if (len)
index ceb17d2dfa195a077d0f0014866b3bfc33f5aeac..2d88f73f585a21aaf5a5fa20df08e269bcec3909 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -342,7 +342,8 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
                        break;
                if (ret)
                        break;
-               if (filp->f_flags & O_NONBLOCK) {
+               if ((filp->f_flags & O_NONBLOCK) ||
+                   (iocb->ki_flags & IOCB_NOWAIT)) {
                        ret = -EAGAIN;
                        break;
                }
@@ -547,7 +548,8 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
                        continue;
 
                /* Wait for buffer space to become available. */
-               if (filp->f_flags & O_NONBLOCK) {
+               if ((filp->f_flags & O_NONBLOCK) ||
+                   (iocb->ki_flags & IOCB_NOWAIT)) {
                        if (!ret)
                                ret = -EAGAIN;
                        break;
diff --git a/fs/smb/Kconfig b/fs/smb/Kconfig
new file mode 100644 (file)
index 0000000..ef42578
--- /dev/null
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# smbfs configuration
+
+source "fs/smb/client/Kconfig"
+source "fs/smb/server/Kconfig"
+
+config SMBFS
+       tristate
+       default y if CIFS=y || SMB_SERVER=y
+       default m if CIFS=m || SMB_SERVER=m
diff --git a/fs/smb/Makefile b/fs/smb/Makefile
new file mode 100644 (file)
index 0000000..9a1bf59
--- /dev/null
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_SMBFS)            += common/
+obj-$(CONFIG_CIFS)             += client/
+obj-$(CONFIG_SMB_SERVER)       += server/
similarity index 100%
rename from fs/cifs/Kconfig
rename to fs/smb/client/Kconfig
similarity index 100%
rename from fs/cifs/Makefile
rename to fs/smb/client/Makefile
similarity index 100%
rename from fs/cifs/asn1.c
rename to fs/smb/client/asn1.c
similarity index 99%
rename from fs/cifs/cifs_debug.c
rename to fs/smb/client/cifs_debug.c
index d4ed200a9471492e8e171019d45619b7c599b22a..5034b862cec2653346fd7880729f9bf3ccefa6b9 100644 (file)
@@ -108,7 +108,7 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
        if ((tcon->seal) ||
            (tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) ||
            (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA))
-               seq_printf(m, " Encrypted");
+               seq_puts(m, " encrypted");
        if (tcon->nocase)
                seq_printf(m, " nocase");
        if (tcon->unix_ext)
@@ -415,8 +415,12 @@ skip_rdma:
 
                        /* dump session id helpful for use with network trace */
                        seq_printf(m, " SessionId: 0x%llx", ses->Suid);
-                       if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
+                       if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) {
                                seq_puts(m, " encrypted");
+                               /* can help in debugging to show encryption type */
+                               if (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
+                                       seq_puts(m, "(gcm256)");
+                       }
                        if (ses->sign)
                                seq_puts(m, " signed");
 
similarity index 100%
rename from fs/cifs/cifs_swn.c
rename to fs/smb/client/cifs_swn.c
similarity index 100%
rename from fs/cifs/cifs_swn.h
rename to fs/smb/client/cifs_swn.h
similarity index 100%
rename from fs/cifs/cifsacl.c
rename to fs/smb/client/cifsacl.c
similarity index 100%
rename from fs/cifs/cifsacl.h
rename to fs/smb/client/cifsacl.h
similarity index 99%
rename from fs/cifs/cifsencrypt.c
rename to fs/smb/client/cifsencrypt.c
index 357bd27a7fd15b390fc3142a1735c31c266e22b6..ef4c2e3c9fa6130b129be94d4a15c4724b952ed9 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/random.h>
 #include <linux/highmem.h>
 #include <linux/fips.h>
-#include "../smbfs_common/arc4.h"
+#include "../common/arc4.h"
 #include <crypto/aead.h>
 
 /*
similarity index 99%
rename from fs/cifs/cifsfs.c
rename to fs/smb/client/cifsfs.c
index 32f7c81a7b89f400ee9b417320d4357760bb0067..43a4d8603db34154f394f2393a03e86692e9ab26 100644 (file)
@@ -246,7 +246,7 @@ cifs_read_super(struct super_block *sb)
        if (cifs_sb->ctx->rasize)
                sb->s_bdi->ra_pages = cifs_sb->ctx->rasize / PAGE_SIZE;
        else
-               sb->s_bdi->ra_pages = cifs_sb->ctx->rsize / PAGE_SIZE;
+               sb->s_bdi->ra_pages = 2 * (cifs_sb->ctx->rsize / PAGE_SIZE);
 
        sb->s_blocksize = CIFS_MAX_MSGSIZE;
        sb->s_blocksize_bits = 14;      /* default 2**14 = CIFS_MAX_MSGSIZE */
@@ -744,6 +744,7 @@ static void cifs_umount_begin(struct super_block *sb)
        spin_unlock(&tcon->tc_lock);
        spin_unlock(&cifs_tcp_ses_lock);
 
+       cifs_close_all_deferred_files(tcon);
        /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
        /* cancel_notify_requests(tcon); */
        if (tcon->ses && tcon->ses->server) {
@@ -759,6 +760,20 @@ static void cifs_umount_begin(struct super_block *sb)
        return;
 }
 
+static int cifs_freeze(struct super_block *sb)
+{
+       struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+       struct cifs_tcon *tcon;
+
+       if (cifs_sb == NULL)
+               return 0;
+
+       tcon = cifs_sb_master_tcon(cifs_sb);
+
+       cifs_close_all_deferred_files(tcon);
+       return 0;
+}
+
 #ifdef CONFIG_CIFS_STATS2
 static int cifs_show_stats(struct seq_file *s, struct dentry *root)
 {
@@ -797,6 +812,7 @@ static const struct super_operations cifs_super_ops = {
        as opens */
        .show_options = cifs_show_options,
        .umount_begin   = cifs_umount_begin,
+       .freeze_fs      = cifs_freeze,
 #ifdef CONFIG_CIFS_STATS2
        .show_stats = cifs_show_stats,
 #endif
similarity index 100%
rename from fs/cifs/cifsfs.h
rename to fs/smb/client/cifsfs.h
similarity index 99%
rename from fs/cifs/cifsglob.h
rename to fs/smb/client/cifsglob.h
index 414685c5d530687565617e960c063a1d050c4cb4..0d84bb1a8cd9d74dba12ace2c6ddc050a655e55c 100644 (file)
@@ -24,7 +24,7 @@
 #include "cifsacl.h"
 #include <crypto/internal/hash.h>
 #include <uapi/linux/cifs/cifs_mount.h>
-#include "../smbfs_common/smb2pdu.h"
+#include "../common/smb2pdu.h"
 #include "smb2pdu.h"
 #include <linux/filelock.h>
 
@@ -424,8 +424,8 @@ struct smb_version_operations {
        /* check for STATUS_NETWORK_SESSION_EXPIRED */
        bool (*is_session_expired)(char *);
        /* send oplock break response */
-       int (*oplock_response)(struct cifs_tcon *, struct cifs_fid *,
-                              struct cifsInodeInfo *);
+       int (*oplock_response)(struct cifs_tcon *tcon, __u64 persistent_fid, __u64 volatile_fid,
+                       __u16 net_fid, struct cifsInodeInfo *cifs_inode);
        /* query remote filesystem */
        int (*queryfs)(const unsigned int, struct cifs_tcon *,
                       struct cifs_sb_info *, struct kstatfs *);
similarity index 99%
rename from fs/cifs/cifspdu.h
rename to fs/smb/client/cifspdu.h
index 445e3eaebcc190b5e35253f9c693ab1c8c0fcc47..e17222fec9d290a643559603068a863b2a97b8ff 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <net/sock.h>
 #include <asm/unaligned.h>
-#include "../smbfs_common/smbfsctl.h"
+#include "../common/smbfsctl.h"
 
 #define CIFS_PROT   0
 #define POSIX_PROT  (CIFS_PROT+1)
similarity index 100%
rename from fs/cifs/cifsroot.c
rename to fs/smb/client/cifsroot.c
similarity index 100%
rename from fs/cifs/cifssmb.c
rename to fs/smb/client/cifssmb.c
similarity index 99%
rename from fs/cifs/connect.c
rename to fs/smb/client/connect.c
index eeeed6fda13b4467bd0b0e18b49bbec14cdbe384..8e9a672320ab72dcdc26ed92310f0a5d0a2792eb 100644 (file)
@@ -2709,6 +2709,13 @@ cifs_match_super(struct super_block *sb, void *data)
 
        spin_lock(&cifs_tcp_ses_lock);
        cifs_sb = CIFS_SB(sb);
+
+       /* We do not want to use a superblock that has been shutdown */
+       if (CIFS_MOUNT_SHUTDOWN & cifs_sb->mnt_cifs_flags) {
+               spin_unlock(&cifs_tcp_ses_lock);
+               return 0;
+       }
+
        tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
        if (tlink == NULL) {
                /* can not match superblock if tlink were ever null */
similarity index 99%
rename from fs/cifs/dfs.c
rename to fs/smb/client/dfs.c
index a93dbca1411b25b941703d06eb795e54b37a37d8..2f93bf8c3325ac3d090600a21e3e660306dbc74c 100644 (file)
@@ -303,7 +303,7 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
        if (!nodfs) {
                rc = dfs_get_referral(mnt_ctx, ctx->UNC + 1, NULL, NULL);
                if (rc) {
-                       if (rc != -ENOENT && rc != -EOPNOTSUPP)
+                       if (rc != -ENOENT && rc != -EOPNOTSUPP && rc != -EIO)
                                goto out;
                        nodfs = true;
                }
similarity index 100%
rename from fs/cifs/dfs.h
rename to fs/smb/client/dfs.h
similarity index 100%
rename from fs/cifs/dir.c
rename to fs/smb/client/dir.c
similarity index 100%
rename from fs/cifs/export.c
rename to fs/smb/client/export.c
similarity index 99%
rename from fs/cifs/file.c
rename to fs/smb/client/file.c
index c5fcefdfd7976666fdf01d4bda1b5f8da14388dc..df88b8c04d03d8ff27f9a2aeb5e9af3327209521 100644 (file)
@@ -3353,9 +3353,10 @@ static size_t cifs_limit_bvec_subset(const struct iov_iter *iter, size_t max_siz
        while (n && ix < nbv) {
                len = min3(n, bvecs[ix].bv_len - skip, max_size);
                span += len;
+               max_size -= len;
                nsegs++;
                ix++;
-               if (span >= max_size || nsegs >= max_segs)
+               if (max_size == 0 || nsegs >= max_segs)
                        break;
                skip = 0;
                n -= len;
@@ -4881,9 +4882,9 @@ void cifs_oplock_break(struct work_struct *work)
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
        struct TCP_Server_Info *server = tcon->ses->server;
        int rc = 0;
-       bool purge_cache = false;
-       struct cifs_deferred_close *dclose;
-       bool is_deferred = false;
+       bool purge_cache = false, oplock_break_cancelled;
+       __u64 persistent_fid, volatile_fid;
+       __u16 net_fid;
 
        wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
                        TASK_UNINTERRUPTIBLE);
@@ -4924,28 +4925,28 @@ oplock_break_ack:
         * file handles but cached, then schedule deferred close immediately.
         * So, new open will not use cached handle.
         */
-       spin_lock(&CIFS_I(inode)->deferred_lock);
-       is_deferred = cifs_is_deferred_close(cfile, &dclose);
-       spin_unlock(&CIFS_I(inode)->deferred_lock);
 
-       if (!CIFS_CACHE_HANDLE(cinode) && is_deferred &&
-                       cfile->deferred_close_scheduled && delayed_work_pending(&cfile->deferred)) {
+       if (!CIFS_CACHE_HANDLE(cinode) && !list_empty(&cinode->deferred_closes))
                cifs_close_deferred_file(cinode);
-       }
 
+       persistent_fid = cfile->fid.persistent_fid;
+       volatile_fid = cfile->fid.volatile_fid;
+       net_fid = cfile->fid.netfid;
+       oplock_break_cancelled = cfile->oplock_break_cancelled;
+
+       _cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);
        /*
         * releasing stale oplock after recent reconnect of smb session using
         * a now incorrect file handle is not a data integrity issue but do
         * not bother sending an oplock release if session to server still is
         * disconnected since oplock already released by the server
         */
-       if (!cfile->oplock_break_cancelled) {
-               rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
-                                                            cinode);
+       if (!oplock_break_cancelled) {
+               rc = tcon->ses->server->ops->oplock_response(tcon, persistent_fid,
+                               volatile_fid, net_fid, cinode);
                cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
        }
 
-       _cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);
        cifs_done_oplock_break(cinode);
 }
 
similarity index 99%
rename from fs/cifs/fs_context.c
rename to fs/smb/client/fs_context.c
index ace11a1a7c8abc07e9df9ec7e9fbf2bd61455e1c..1bda75609b6422ea0a7c7adf0a083094eefaaa5b 100644 (file)
@@ -904,6 +904,14 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
                        ctx->sfu_remap = false; /* disable SFU mapping */
                }
                break;
+       case Opt_mapchars:
+               if (result.negated)
+                       ctx->sfu_remap = false;
+               else {
+                       ctx->sfu_remap = true;
+                       ctx->remap = false; /* disable SFM (mapposix) mapping */
+               }
+               break;
        case Opt_user_xattr:
                if (result.negated)
                        ctx->no_xattr = 1;
similarity index 100%
rename from fs/cifs/fscache.c
rename to fs/smb/client/fscache.c
similarity index 100%
rename from fs/cifs/fscache.h
rename to fs/smb/client/fscache.h
similarity index 100%
rename from fs/cifs/inode.c
rename to fs/smb/client/inode.c
similarity index 98%
rename from fs/cifs/ioctl.c
rename to fs/smb/client/ioctl.c
index cb3be58cd55eb0d59efcbf3ee30360dad43150a2..fff092bbc7a37f5e58f1a56c3c6646673743a844 100644 (file)
@@ -321,7 +321,11 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
        struct tcon_link *tlink;
        struct cifs_sb_info *cifs_sb;
        __u64   ExtAttrBits = 0;
+#ifdef CONFIG_CIFS_POSIX
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
        __u64   caps;
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+#endif /* CONFIG_CIFS_POSIX */
 
        xid = get_xid();
 
@@ -331,9 +335,9 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
                        if (pSMBFile == NULL)
                                break;
                        tcon = tlink_tcon(pSMBFile->tlink);
-                       caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
 #ifdef CONFIG_CIFS_POSIX
 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+                       caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
                        if (CIFS_UNIX_EXTATTR_CAP & caps) {
                                __u64   ExtAttrMask = 0;
                                rc = CIFSGetExtAttr(xid, tcon,
similarity index 100%
rename from fs/cifs/link.c
rename to fs/smb/client/link.c
similarity index 100%
rename from fs/cifs/misc.c
rename to fs/smb/client/misc.c
similarity index 100%
rename from fs/cifs/netlink.c
rename to fs/smb/client/netlink.c
similarity index 100%
rename from fs/cifs/netlink.h
rename to fs/smb/client/netlink.h
similarity index 100%
rename from fs/cifs/netmisc.c
rename to fs/smb/client/netmisc.c
similarity index 100%
rename from fs/cifs/nterr.c
rename to fs/smb/client/nterr.c
similarity index 100%
rename from fs/cifs/nterr.h
rename to fs/smb/client/nterr.h
similarity index 100%
rename from fs/cifs/ntlmssp.h
rename to fs/smb/client/ntlmssp.h
similarity index 100%
rename from fs/cifs/readdir.c
rename to fs/smb/client/readdir.c
similarity index 100%
rename from fs/cifs/sess.c
rename to fs/smb/client/sess.c
similarity index 99%
rename from fs/cifs/smb1ops.c
rename to fs/smb/client/smb1ops.c
index abda6148be10f122cd4e2df60f19239e2165b344..7d1b3fc014d94ac9dd1c9364c99e7e4a4b363359 100644 (file)
@@ -897,12 +897,11 @@ cifs_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
 }
 
 static int
-cifs_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid,
-                    struct cifsInodeInfo *cinode)
+cifs_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
+               __u64 volatile_fid, __u16 net_fid, struct cifsInodeInfo *cinode)
 {
-       return CIFSSMBLock(0, tcon, fid->netfid, current->tgid, 0, 0, 0, 0,
-                          LOCKING_ANDX_OPLOCK_RELEASE, false,
-                          CIFS_CACHE_READ(cinode) ? 1 : 0);
+       return CIFSSMBLock(0, tcon, net_fid, current->tgid, 0, 0, 0, 0,
+                          LOCKING_ANDX_OPLOCK_RELEASE, false, CIFS_CACHE_READ(cinode) ? 1 : 0);
 }
 
 static int
similarity index 100%
rename from fs/cifs/smb2file.c
rename to fs/smb/client/smb2file.c
similarity index 100%
rename from fs/cifs/smb2glob.h
rename to fs/smb/client/smb2glob.h
similarity index 100%
rename from fs/cifs/smb2misc.c
rename to fs/smb/client/smb2misc.c
similarity index 99%
rename from fs/cifs/smb2ops.c
rename to fs/smb/client/smb2ops.c
index a81758225fcdc7b24b8921bf37ef95c79fde2ba3..6e3be58cfe49ff5b5f1bc0bb192488b1589acaa0 100644 (file)
@@ -618,7 +618,6 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
                 * Add a new one instead
                 */
                spin_lock(&ses->iface_lock);
-               iface = niface = NULL;
                list_for_each_entry_safe(iface, niface, &ses->iface_list,
                                         iface_head) {
                        ret = iface_cmp(iface, &tmp_iface);
@@ -1682,7 +1681,7 @@ smb2_copychunk_range(const unsigned int xid,
                pcchunk->SourceOffset = cpu_to_le64(src_off);
                pcchunk->TargetOffset = cpu_to_le64(dest_off);
                pcchunk->Length =
-                       cpu_to_le32(min_t(u32, len, tcon->max_bytes_chunk));
+                       cpu_to_le32(min_t(u64, len, tcon->max_bytes_chunk));
 
                /* Request server copy to target from src identified by key */
                kfree(retbuf);
@@ -2383,15 +2382,14 @@ smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
 }
 
 static int
-smb2_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid,
-                    struct cifsInodeInfo *cinode)
+smb2_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
+               __u64 volatile_fid, __u16 net_fid, struct cifsInodeInfo *cinode)
 {
        if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
                return SMB2_lease_break(0, tcon, cinode->lease_key,
                                        smb2_get_lease_state(cinode));
 
-       return SMB2_oplock_break(0, tcon, fid->persistent_fid,
-                                fid->volatile_fid,
+       return SMB2_oplock_break(0, tcon, persistent_fid, volatile_fid,
                                 CIFS_CACHE_READ(cinode) ? 1 : 0);
 }
 
similarity index 99%
rename from fs/cifs/smb2pdu.c
rename to fs/smb/client/smb2pdu.c
index e33ca0d33906e5bce5530cf6c6304a6869e0b7bb..7063b395d22f2e5605d636cd848babf98adc894c 100644 (file)
@@ -1947,6 +1947,9 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
        init_copy_chunk_defaults(tcon);
        if (server->ops->validate_negotiate)
                rc = server->ops->validate_negotiate(xid, tcon);
+       if (rc == 0) /* See MS-SMB2 2.2.10 and 3.2.5.5 */
+               if (tcon->share_flags & SMB2_SHAREFLAG_ISOLATED_TRANSPORT)
+                       server->nosharesock = true;
 tcon_exit:
 
        free_rsp_buf(resp_buftype, rsp);
@@ -3722,7 +3725,7 @@ SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon,
                if (*out_data == NULL) {
                        rc = -ENOMEM;
                        goto cnotify_exit;
-               } else
+               } else if (plen)
                        *plen = le32_to_cpu(smb_rsp->OutputBufferLength);
        }
 
similarity index 100%
rename from fs/cifs/smb2pdu.h
rename to fs/smb/client/smb2pdu.h
similarity index 98%
rename from fs/cifs/smbencrypt.c
rename to fs/smb/client/smbencrypt.c
index 4a048775386910936400a2d2e052116cf6754db0..f0ce26414f17377365ed0201f21dd4e9cdf06b59 100644 (file)
@@ -24,7 +24,7 @@
 #include "cifsglob.h"
 #include "cifs_debug.h"
 #include "cifsproto.h"
-#include "../smbfs_common/md4.h"
+#include "../common/md4.h"
 
 #ifndef false
 #define false 0
similarity index 100%
rename from fs/cifs/smberr.h
rename to fs/smb/client/smberr.h
similarity index 100%
rename from fs/cifs/trace.c
rename to fs/smb/client/trace.c
similarity index 100%
rename from fs/cifs/trace.h
rename to fs/smb/client/trace.h
similarity index 100%
rename from fs/cifs/unc.c
rename to fs/smb/client/unc.c
similarity index 100%
rename from fs/cifs/winucase.c
rename to fs/smb/client/winucase.c
similarity index 100%
rename from fs/cifs/xattr.c
rename to fs/smb/client/xattr.c
similarity index 59%
rename from fs/smbfs_common/Makefile
rename to fs/smb/common/Makefile
index cafc61a3bfc3721216a30fc54096abc84ba209c1..c66dbbc1469c3f68e29660885f12305c3aa8dfe4 100644 (file)
@@ -3,5 +3,5 @@
 # Makefile for Linux filesystem routines that are shared by client and server.
 #
 
-obj-$(CONFIG_SMBFS_COMMON) += cifs_arc4.o
-obj-$(CONFIG_SMBFS_COMMON) += cifs_md4.o
+obj-$(CONFIG_SMBFS) += cifs_arc4.o
+obj-$(CONFIG_SMBFS) += cifs_md4.o
similarity index 100%
rename from fs/smbfs_common/arc4.h
rename to fs/smb/common/arc4.h
similarity index 100%
rename from fs/smbfs_common/md4.h
rename to fs/smb/common/md4.h
similarity index 100%
rename from fs/ksmbd/Kconfig
rename to fs/smb/server/Kconfig
similarity index 100%
rename from fs/ksmbd/Makefile
rename to fs/smb/server/Makefile
similarity index 100%
rename from fs/ksmbd/asn1.c
rename to fs/smb/server/asn1.c
similarity index 100%
rename from fs/ksmbd/asn1.h
rename to fs/smb/server/asn1.h
similarity index 99%
rename from fs/ksmbd/auth.c
rename to fs/smb/server/auth.c
index df8fb076f6f141b36bbe1b09b297912a9c96a188..5e5e120edcc22d88028a9ff48c6c0724b09b4b99 100644 (file)
@@ -29,7 +29,7 @@
 #include "mgmt/user_config.h"
 #include "crypto_ctx.h"
 #include "transport_ipc.h"
-#include "../smbfs_common/arc4.h"
+#include "../common/arc4.h"
 
 /*
  * Fixed format data defining GSS header and fixed string
similarity index 100%
rename from fs/ksmbd/auth.h
rename to fs/smb/server/auth.h
similarity index 99%
rename from fs/ksmbd/connection.c
rename to fs/smb/server/connection.c
index 4ed379f9b1aa65d635e774ae354310a9c0a60a95..4882a812ea86735374b930ae258e4d041aba602d 100644 (file)
@@ -351,7 +351,8 @@ int ksmbd_conn_handler_loop(void *p)
                        break;
 
                /* 4 for rfc1002 length field */
-               size = pdu_size + 4;
+               /* 1 for implied bcc[0] */
+               size = pdu_size + 4 + 1;
                conn->request_buf = kvmalloc(size, GFP_KERNEL);
                if (!conn->request_buf)
                        break;
similarity index 100%
rename from fs/ksmbd/glob.h
rename to fs/smb/server/glob.h
similarity index 100%
rename from fs/ksmbd/misc.c
rename to fs/smb/server/misc.c
similarity index 100%
rename from fs/ksmbd/misc.h
rename to fs/smb/server/misc.h
similarity index 100%
rename from fs/ksmbd/ndr.c
rename to fs/smb/server/ndr.c
similarity index 100%
rename from fs/ksmbd/ndr.h
rename to fs/smb/server/ndr.h
similarity index 100%
rename from fs/ksmbd/nterr.h
rename to fs/smb/server/nterr.h
similarity index 100%
rename from fs/ksmbd/ntlmssp.h
rename to fs/smb/server/ntlmssp.h
similarity index 97%
rename from fs/ksmbd/oplock.c
rename to fs/smb/server/oplock.c
index 2e54ded4d92c21f254659326fc54f2d20dcedd3d..db181bdad73a258993f029d4effe7e1be054f529 100644 (file)
@@ -157,13 +157,42 @@ static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci)
        rcu_read_lock();
        opinfo = list_first_or_null_rcu(&ci->m_op_list, struct oplock_info,
                                        op_entry);
-       if (opinfo && !atomic_inc_not_zero(&opinfo->refcount))
-               opinfo = NULL;
+       if (opinfo) {
+               if (!atomic_inc_not_zero(&opinfo->refcount))
+                       opinfo = NULL;
+               else {
+                       atomic_inc(&opinfo->conn->r_count);
+                       if (ksmbd_conn_releasing(opinfo->conn)) {
+                               atomic_dec(&opinfo->conn->r_count);
+                               atomic_dec(&opinfo->refcount);
+                               opinfo = NULL;
+                       }
+               }
+       }
+
        rcu_read_unlock();
 
        return opinfo;
 }
 
+static void opinfo_conn_put(struct oplock_info *opinfo)
+{
+       struct ksmbd_conn *conn;
+
+       if (!opinfo)
+               return;
+
+       conn = opinfo->conn;
+       /*
+        * Checking waitqueue to dropping pending requests on
+        * disconnection. waitqueue_active is safe because it
+        * uses atomic operation for condition.
+        */
+       if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
+               wake_up(&conn->r_count_q);
+       opinfo_put(opinfo);
+}
+
 void opinfo_put(struct oplock_info *opinfo)
 {
        if (!atomic_dec_and_test(&opinfo->refcount))
@@ -666,13 +695,6 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
 
 out:
        ksmbd_free_work_struct(work);
-       /*
-        * Checking waitqueue to dropping pending requests on
-        * disconnection. waitqueue_active is safe because it
-        * uses atomic operation for condition.
-        */
-       if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
-               wake_up(&conn->r_count_q);
 }
 
 /**
@@ -706,7 +728,6 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo)
        work->conn = conn;
        work->sess = opinfo->sess;
 
-       atomic_inc(&conn->r_count);
        if (opinfo->op_state == OPLOCK_ACK_WAIT) {
                INIT_WORK(&work->work, __smb2_oplock_break_noti);
                ksmbd_queue_work(work);
@@ -776,13 +797,6 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
 
 out:
        ksmbd_free_work_struct(work);
-       /*
-        * Checking waitqueue to dropping pending requests on
-        * disconnection. waitqueue_active is safe because it
-        * uses atomic operation for condition.
-        */
-       if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
-               wake_up(&conn->r_count_q);
 }
 
 /**
@@ -822,7 +836,6 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)
        work->conn = conn;
        work->sess = opinfo->sess;
 
-       atomic_inc(&conn->r_count);
        if (opinfo->op_state == OPLOCK_ACK_WAIT) {
                list_for_each_safe(tmp, t, &opinfo->interim_list) {
                        struct ksmbd_work *in_work;
@@ -1144,8 +1157,10 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
        }
        prev_opinfo = opinfo_get_list(ci);
        if (!prev_opinfo ||
-           (prev_opinfo->level == SMB2_OPLOCK_LEVEL_NONE && lctx))
+           (prev_opinfo->level == SMB2_OPLOCK_LEVEL_NONE && lctx)) {
+               opinfo_conn_put(prev_opinfo);
                goto set_lev;
+       }
        prev_op_has_lease = prev_opinfo->is_lease;
        if (prev_op_has_lease)
                prev_op_state = prev_opinfo->o_lease->state;
@@ -1153,19 +1168,19 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
        if (share_ret < 0 &&
            prev_opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
                err = share_ret;
-               opinfo_put(prev_opinfo);
+               opinfo_conn_put(prev_opinfo);
                goto err_out;
        }
 
        if (prev_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH &&
            prev_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
-               opinfo_put(prev_opinfo);
+               opinfo_conn_put(prev_opinfo);
                goto op_break_not_needed;
        }
 
        list_add(&work->interim_entry, &prev_opinfo->interim_list);
        err = oplock_break(prev_opinfo, SMB2_OPLOCK_LEVEL_II);
-       opinfo_put(prev_opinfo);
+       opinfo_conn_put(prev_opinfo);
        if (err == -ENOENT)
                goto set_lev;
        /* Check all oplock was freed by close */
@@ -1228,14 +1243,14 @@ static void smb_break_all_write_oplock(struct ksmbd_work *work,
                return;
        if (brk_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH &&
            brk_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
-               opinfo_put(brk_opinfo);
+               opinfo_conn_put(brk_opinfo);
                return;
        }
 
        brk_opinfo->open_trunc = is_trunc;
        list_add(&work->interim_entry, &brk_opinfo->interim_list);
        oplock_break(brk_opinfo, SMB2_OPLOCK_LEVEL_II);
-       opinfo_put(brk_opinfo);
+       opinfo_conn_put(brk_opinfo);
 }
 
 /**
@@ -1263,6 +1278,13 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
        list_for_each_entry_rcu(brk_op, &ci->m_op_list, op_entry) {
                if (!atomic_inc_not_zero(&brk_op->refcount))
                        continue;
+
+               atomic_inc(&brk_op->conn->r_count);
+               if (ksmbd_conn_releasing(brk_op->conn)) {
+                       atomic_dec(&brk_op->conn->r_count);
+                       continue;
+               }
+
                rcu_read_unlock();
                if (brk_op->is_lease && (brk_op->o_lease->state &
                    (~(SMB2_LEASE_READ_CACHING_LE |
@@ -1292,7 +1314,7 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
                brk_op->open_trunc = is_trunc;
                oplock_break(brk_op, SMB2_OPLOCK_LEVEL_NONE);
 next:
-               opinfo_put(brk_op);
+               opinfo_conn_put(brk_op);
                rcu_read_lock();
        }
        rcu_read_unlock();
@@ -1449,11 +1471,12 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
  * smb2_find_context_vals() - find a particular context info in open request
  * @open_req:  buffer containing smb2 file open(create) request
  * @tag:       context name to search for
+ * @tag_len:   the length of tag
  *
  * Return:     pointer to requested context, NULL if @str context not found
  *             or error pointer if name length is invalid.
  */
-struct create_context *smb2_find_context_vals(void *open_req, const char *tag)
+struct create_context *smb2_find_context_vals(void *open_req, const char *tag, int tag_len)
 {
        struct create_context *cc;
        unsigned int next = 0;
@@ -1492,7 +1515,7 @@ struct create_context *smb2_find_context_vals(void *open_req, const char *tag)
                        return ERR_PTR(-EINVAL);
 
                name = (char *)cc + name_off;
-               if (memcmp(name, tag, name_len) == 0)
+               if (name_len == tag_len && !memcmp(name, tag, name_len))
                        return cc;
 
                remain_len -= next;
similarity index 99%
rename from fs/ksmbd/oplock.h
rename to fs/smb/server/oplock.h
index 09753448f7798de7ff5af0bc1aa38096861d05b5..4b0fe6da76940f54a915cb4bd20d3ce67539bd3e 100644 (file)
@@ -118,7 +118,7 @@ void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp);
 void create_mxac_rsp_buf(char *cc, int maximal_access);
 void create_disk_id_rsp_buf(char *cc, __u64 file_id, __u64 vol_id);
 void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp);
-struct create_context *smb2_find_context_vals(void *open_req, const char *str);
+struct create_context *smb2_find_context_vals(void *open_req, const char *tag, int tag_len);
 struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,
                                          char *lease_key);
 int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci,
similarity index 100%
rename from fs/ksmbd/server.c
rename to fs/smb/server/server.c
similarity index 100%
rename from fs/ksmbd/server.h
rename to fs/smb/server/server.h
similarity index 98%
rename from fs/ksmbd/smb2misc.c
rename to fs/smb/server/smb2misc.c
index fbdde426dd01dfe35725bfc40be9ca8e6f81de29..0ffe663b75906a9556d7e4ef55ed754c38fc27ae 100644 (file)
@@ -416,8 +416,11 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
 
                /*
                 * Allow a message that padded to 8byte boundary.
+                * Linux 4.19.217 with smb 3.0.2 are sometimes
+                * sending messages where the cls_len is exactly
+                * 8 bytes less than len.
                 */
-               if (clc_len < len && (len - clc_len) < 8)
+               if (clc_len < len && (len - clc_len) <= 8)
                        goto validate_credit;
 
                pr_err_ratelimited(
similarity index 100%
rename from fs/ksmbd/smb2ops.c
rename to fs/smb/server/smb2ops.c
similarity index 99%
rename from fs/ksmbd/smb2pdu.c
rename to fs/smb/server/smb2pdu.c
index cb93fd231f4e1fd7b6ae71b5b58d96b867ee6318..7a81541de602141ee188581bf7901f5dc84ba076 100644 (file)
@@ -326,13 +326,9 @@ int smb2_set_rsp_credits(struct ksmbd_work *work)
        if (hdr->Command == SMB2_NEGOTIATE)
                aux_max = 1;
        else
-               aux_max = conn->vals->max_credits - credit_charge;
+               aux_max = conn->vals->max_credits - conn->total_credits;
        credits_granted = min_t(unsigned short, credits_requested, aux_max);
 
-       if (conn->vals->max_credits - conn->total_credits < credits_granted)
-               credits_granted = conn->vals->max_credits -
-                       conn->total_credits;
-
        conn->total_credits += credits_granted;
        work->credits_granted += credits_granted;
 
@@ -849,13 +845,14 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
 
 static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
                                  struct smb2_preauth_neg_context *pneg_ctxt,
-                                 int len_of_ctxts)
+                                 int ctxt_len)
 {
        /*
         * sizeof(smb2_preauth_neg_context) assumes SMB311_SALT_SIZE Salt,
         * which may not be present. Only check for used HashAlgorithms[1].
         */
-       if (len_of_ctxts < MIN_PREAUTH_CTXT_DATA_LEN)
+       if (ctxt_len <
+           sizeof(struct smb2_neg_context) + MIN_PREAUTH_CTXT_DATA_LEN)
                return STATUS_INVALID_PARAMETER;
 
        if (pneg_ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512)
@@ -867,15 +864,23 @@ static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
 
 static void decode_encrypt_ctxt(struct ksmbd_conn *conn,
                                struct smb2_encryption_neg_context *pneg_ctxt,
-                               int len_of_ctxts)
+                               int ctxt_len)
 {
-       int cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount);
-       int i, cphs_size = cph_cnt * sizeof(__le16);
+       int cph_cnt;
+       int i, cphs_size;
+
+       if (sizeof(struct smb2_encryption_neg_context) > ctxt_len) {
+               pr_err("Invalid SMB2_ENCRYPTION_CAPABILITIES context size\n");
+               return;
+       }
 
        conn->cipher_type = 0;
 
+       cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount);
+       cphs_size = cph_cnt * sizeof(__le16);
+
        if (sizeof(struct smb2_encryption_neg_context) + cphs_size >
-           len_of_ctxts) {
+           ctxt_len) {
                pr_err("Invalid cipher count(%d)\n", cph_cnt);
                return;
        }
@@ -923,15 +928,22 @@ static void decode_compress_ctxt(struct ksmbd_conn *conn,
 
 static void decode_sign_cap_ctxt(struct ksmbd_conn *conn,
                                 struct smb2_signing_capabilities *pneg_ctxt,
-                                int len_of_ctxts)
+                                int ctxt_len)
 {
-       int sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount);
-       int i, sign_alos_size = sign_algo_cnt * sizeof(__le16);
+       int sign_algo_cnt;
+       int i, sign_alos_size;
+
+       if (sizeof(struct smb2_signing_capabilities) > ctxt_len) {
+               pr_err("Invalid SMB2_SIGNING_CAPABILITIES context length\n");
+               return;
+       }
 
        conn->signing_negotiated = false;
+       sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount);
+       sign_alos_size = sign_algo_cnt * sizeof(__le16);
 
        if (sizeof(struct smb2_signing_capabilities) + sign_alos_size >
-           len_of_ctxts) {
+           ctxt_len) {
                pr_err("Invalid signing algorithm count(%d)\n", sign_algo_cnt);
                return;
        }
@@ -969,18 +981,16 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
        len_of_ctxts = len_of_smb - offset;
 
        while (i++ < neg_ctxt_cnt) {
-               int clen;
-
-               /* check that offset is not beyond end of SMB */
-               if (len_of_ctxts == 0)
-                       break;
+               int clen, ctxt_len;
 
                if (len_of_ctxts < sizeof(struct smb2_neg_context))
                        break;
 
                pctx = (struct smb2_neg_context *)((char *)pctx + offset);
                clen = le16_to_cpu(pctx->DataLength);
-               if (clen + sizeof(struct smb2_neg_context) > len_of_ctxts)
+               ctxt_len = clen + sizeof(struct smb2_neg_context);
+
+               if (ctxt_len > len_of_ctxts)
                        break;
 
                if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES) {
@@ -991,7 +1001,7 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
 
                        status = decode_preauth_ctxt(conn,
                                                     (struct smb2_preauth_neg_context *)pctx,
-                                                    len_of_ctxts);
+                                                    ctxt_len);
                        if (status != STATUS_SUCCESS)
                                break;
                } else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) {
@@ -1002,7 +1012,7 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
 
                        decode_encrypt_ctxt(conn,
                                            (struct smb2_encryption_neg_context *)pctx,
-                                           len_of_ctxts);
+                                           ctxt_len);
                } else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES) {
                        ksmbd_debug(SMB,
                                    "deassemble SMB2_COMPRESSION_CAPABILITIES context\n");
@@ -1021,9 +1031,10 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
                } else if (pctx->ContextType == SMB2_SIGNING_CAPABILITIES) {
                        ksmbd_debug(SMB,
                                    "deassemble SMB2_SIGNING_CAPABILITIES context\n");
+
                        decode_sign_cap_ctxt(conn,
                                             (struct smb2_signing_capabilities *)pctx,
-                                            len_of_ctxts);
+                                            ctxt_len);
                }
 
                /* offsets must be 8 byte aligned */
@@ -1057,16 +1068,16 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
                return rc;
        }
 
-       if (req->DialectCount == 0) {
-               pr_err("malformed packet\n");
+       smb2_buf_len = get_rfc1002_len(work->request_buf);
+       smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects);
+       if (smb2_neg_size > smb2_buf_len) {
                rsp->hdr.Status = STATUS_INVALID_PARAMETER;
                rc = -EINVAL;
                goto err_out;
        }
 
-       smb2_buf_len = get_rfc1002_len(work->request_buf);
-       smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects);
-       if (smb2_neg_size > smb2_buf_len) {
+       if (req->DialectCount == 0) {
+               pr_err("malformed packet\n");
                rsp->hdr.Status = STATUS_INVALID_PARAMETER;
                rc = -EINVAL;
                goto err_out;
@@ -1356,7 +1367,7 @@ static struct ksmbd_user *session_user(struct ksmbd_conn *conn,
        struct authenticate_message *authblob;
        struct ksmbd_user *user;
        char *name;
-       unsigned int auth_msg_len, name_off, name_len, secbuf_len;
+       unsigned int name_off, name_len, secbuf_len;
 
        secbuf_len = le16_to_cpu(req->SecurityBufferLength);
        if (secbuf_len < sizeof(struct authenticate_message)) {
@@ -1366,9 +1377,8 @@ static struct ksmbd_user *session_user(struct ksmbd_conn *conn,
        authblob = user_authblob(conn, req);
        name_off = le32_to_cpu(authblob->UserName.BufferOffset);
        name_len = le16_to_cpu(authblob->UserName.Length);
-       auth_msg_len = le16_to_cpu(req->SecurityBufferOffset) + secbuf_len;
 
-       if (auth_msg_len < (u64)name_off + name_len)
+       if (secbuf_len < (u64)name_off + name_len)
                return NULL;
 
        name = smb_strndup_from_utf16((const char *)authblob + name_off,
@@ -2464,7 +2474,7 @@ static int smb2_create_sd_buffer(struct ksmbd_work *work,
                return -ENOENT;
 
        /* Parse SD BUFFER create contexts */
-       context = smb2_find_context_vals(req, SMB2_CREATE_SD_BUFFER);
+       context = smb2_find_context_vals(req, SMB2_CREATE_SD_BUFFER, 4);
        if (!context)
                return -ENOENT;
        else if (IS_ERR(context))
@@ -2666,7 +2676,7 @@ int smb2_open(struct ksmbd_work *work)
 
        if (req->CreateContextsOffset) {
                /* Parse non-durable handle create contexts */
-               context = smb2_find_context_vals(req, SMB2_CREATE_EA_BUFFER);
+               context = smb2_find_context_vals(req, SMB2_CREATE_EA_BUFFER, 4);
                if (IS_ERR(context)) {
                        rc = PTR_ERR(context);
                        goto err_out1;
@@ -2686,7 +2696,7 @@ int smb2_open(struct ksmbd_work *work)
                }
 
                context = smb2_find_context_vals(req,
-                                                SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST);
+                                                SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST, 4);
                if (IS_ERR(context)) {
                        rc = PTR_ERR(context);
                        goto err_out1;
@@ -2697,7 +2707,7 @@ int smb2_open(struct ksmbd_work *work)
                }
 
                context = smb2_find_context_vals(req,
-                                                SMB2_CREATE_TIMEWARP_REQUEST);
+                                                SMB2_CREATE_TIMEWARP_REQUEST, 4);
                if (IS_ERR(context)) {
                        rc = PTR_ERR(context);
                        goto err_out1;
@@ -2709,7 +2719,7 @@ int smb2_open(struct ksmbd_work *work)
 
                if (tcon->posix_extensions) {
                        context = smb2_find_context_vals(req,
-                                                        SMB2_CREATE_TAG_POSIX);
+                                                        SMB2_CREATE_TAG_POSIX, 16);
                        if (IS_ERR(context)) {
                                rc = PTR_ERR(context);
                                goto err_out1;
@@ -3107,7 +3117,7 @@ int smb2_open(struct ksmbd_work *work)
                struct create_alloc_size_req *az_req;
 
                az_req = (struct create_alloc_size_req *)smb2_find_context_vals(req,
-                                       SMB2_CREATE_ALLOCATION_SIZE);
+                                       SMB2_CREATE_ALLOCATION_SIZE, 4);
                if (IS_ERR(az_req)) {
                        rc = PTR_ERR(az_req);
                        goto err_out;
@@ -3134,7 +3144,7 @@ int smb2_open(struct ksmbd_work *work)
                                            err);
                }
 
-               context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID);
+               context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID, 4);
                if (IS_ERR(context)) {
                        rc = PTR_ERR(context);
                        goto err_out;
@@ -4359,21 +4369,6 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
        return 0;
 }
 
-static unsigned long long get_allocation_size(struct inode *inode,
-                                             struct kstat *stat)
-{
-       unsigned long long alloc_size = 0;
-
-       if (!S_ISDIR(stat->mode)) {
-               if ((inode->i_blocks << 9) <= stat->size)
-                       alloc_size = stat->size;
-               else
-                       alloc_size = inode->i_blocks << 9;
-       }
-
-       return alloc_size;
-}
-
 static void get_file_standard_info(struct smb2_query_info_rsp *rsp,
                                   struct ksmbd_file *fp, void *rsp_org)
 {
@@ -4388,7 +4383,7 @@ static void get_file_standard_info(struct smb2_query_info_rsp *rsp,
        sinfo = (struct smb2_file_standard_info *)rsp->Buffer;
        delete_pending = ksmbd_inode_pending_delete(fp);
 
-       sinfo->AllocationSize = cpu_to_le64(get_allocation_size(inode, &stat));
+       sinfo->AllocationSize = cpu_to_le64(inode->i_blocks << 9);
        sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
        sinfo->NumberOfLinks = cpu_to_le32(get_nlink(&stat) - delete_pending);
        sinfo->DeletePending = delete_pending;
@@ -4453,7 +4448,7 @@ static int get_file_all_info(struct ksmbd_work *work,
        file_info->Attributes = fp->f_ci->m_fattr;
        file_info->Pad1 = 0;
        file_info->AllocationSize =
-               cpu_to_le64(get_allocation_size(inode, &stat));
+               cpu_to_le64(inode->i_blocks << 9);
        file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
        file_info->NumberOfLinks =
                        cpu_to_le32(get_nlink(&stat) - delete_pending);
@@ -4642,7 +4637,7 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
        file_info->ChangeTime = cpu_to_le64(time);
        file_info->Attributes = fp->f_ci->m_fattr;
        file_info->AllocationSize =
-               cpu_to_le64(get_allocation_size(inode, &stat));
+               cpu_to_le64(inode->i_blocks << 9);
        file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
        file_info->Reserved = cpu_to_le32(0);
        rsp->OutputBufferLength =
@@ -5507,7 +5502,7 @@ static int smb2_create_link(struct ksmbd_work *work,
 {
        char *link_name = NULL, *target_name = NULL, *pathname = NULL;
        struct path path;
-       bool file_present = true;
+       bool file_present = false;
        int rc;
 
        if (buf_len < (u64)sizeof(struct smb2_file_link_info) +
@@ -5540,8 +5535,8 @@ static int smb2_create_link(struct ksmbd_work *work,
        if (rc) {
                if (rc != -ENOENT)
                        goto out;
-               file_present = false;
-       }
+       } else
+               file_present = true;
 
        if (file_info->ReplaceIfExists) {
                if (file_present) {
similarity index 100%
rename from fs/ksmbd/smb2pdu.h
rename to fs/smb/server/smb2pdu.h
similarity index 99%
rename from fs/ksmbd/smb_common.h
rename to fs/smb/server/smb_common.h
index 9130d2e3cd78c0966d266f7bf72dfe390bd06462..6b0d5f1fe85ca52db294ea4c054cb6fe7d98d723 100644 (file)
@@ -10,7 +10,7 @@
 
 #include "glob.h"
 #include "nterr.h"
-#include "../smbfs_common/smb2pdu.h"
+#include "../common/smb2pdu.h"
 #include "smb2pdu.h"
 
 /* ksmbd's Specific ERRNO */
similarity index 100%
rename from fs/ksmbd/smbacl.c
rename to fs/smb/server/smbacl.c
similarity index 100%
rename from fs/ksmbd/smbacl.h
rename to fs/smb/server/smbacl.h
similarity index 98%
rename from fs/ksmbd/smbfsctl.h
rename to fs/smb/server/smbfsctl.h
index b98418aae20cd5a90dff8c507d8b515786ca2514..ecdf8f6e0df4d4486ac3c0b71d6894afb9c128cf 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 /*
- *   fs/cifs/smbfsctl.h: SMB, CIFS, SMB2 FSCTL definitions
+ *   fs/smb/server/smbfsctl.h: SMB, CIFS, SMB2 FSCTL definitions
  *
  *   Copyright (c) International Business Machines  Corp., 2002,2009
  *   Author(s): Steve French (sfrench@us.ibm.com)
similarity index 99%
rename from fs/ksmbd/smbstatus.h
rename to fs/smb/server/smbstatus.h
index 108a8b6ed24a009d6afdc56797b131b8a017e42e..8963deb42404e7da057d6c16e01d53651188c062 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 /*
- *   fs/cifs/smb2status.h
+ *   fs/server/smb2status.h
  *
  *   SMB2 Status code (network error) definitions
  *   Definitions are from MS-ERREF
similarity index 100%
rename from fs/ksmbd/unicode.c
rename to fs/smb/server/unicode.c
similarity index 100%
rename from fs/ksmbd/unicode.h
rename to fs/smb/server/unicode.h
similarity index 100%
rename from fs/ksmbd/uniupr.h
rename to fs/smb/server/uniupr.h
similarity index 99%
rename from fs/ksmbd/vfs.c
rename to fs/smb/server/vfs.c
index 778c152708e433102b9b10bf816533d31111878c..6f302919e9f77021c6881b5aa41a4286943205f3 100644 (file)
@@ -86,12 +86,14 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
        err = vfs_path_parent_lookup(filename, flags,
                                     &parent_path, &last, &type,
                                     root_share_path);
-       putname(filename);
-       if (err)
+       if (err) {
+               putname(filename);
                return err;
+       }
 
        if (unlikely(type != LAST_NORM)) {
                path_put(&parent_path);
+               putname(filename);
                return -ENOENT;
        }
 
@@ -108,12 +110,14 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
        path->dentry = d;
        path->mnt = share_conf->vfs_path.mnt;
        path_put(&parent_path);
+       putname(filename);
 
        return 0;
 
 err_out:
        inode_unlock(parent_path.dentry->d_inode);
        path_put(&parent_path);
+       putname(filename);
        return -ENOENT;
 }
 
@@ -743,6 +747,7 @@ retry:
        rd.new_dir              = new_path.dentry->d_inode,
        rd.new_dentry           = new_dentry,
        rd.flags                = flags,
+       rd.delegated_inode      = NULL,
        err = vfs_rename(&rd);
        if (err)
                ksmbd_debug(VFS, "vfs_rename failed err %d\n", err);
similarity index 100%
rename from fs/ksmbd/vfs.h
rename to fs/smb/server/vfs.h
similarity index 100%
rename from fs/ksmbd/xattr.h
rename to fs/smb/server/xattr.h
index 0ba34c1355932401d44ad7007679e82fba2abb3a..96d1c3edf289c035b629a82060f5b5d7e5955595 100644 (file)
@@ -130,6 +130,7 @@ static int do_statfs_native(struct kstatfs *st, struct statfs __user *p)
        if (sizeof(buf) == sizeof(*st))
                memcpy(&buf, st, sizeof(*st));
        else {
+               memset(&buf, 0, sizeof(buf));
                if (sizeof buf.f_blocks == 4) {
                        if ((st->f_blocks | st->f_bfree | st->f_bavail |
                             st->f_bsize | st->f_frsize) &
@@ -158,7 +159,6 @@ static int do_statfs_native(struct kstatfs *st, struct statfs __user *p)
                buf.f_namelen = st->f_namelen;
                buf.f_frsize = st->f_frsize;
                buf.f_flags = st->f_flags;
-               memset(buf.f_spare, 0, sizeof(buf.f_spare));
        }
        if (copy_to_user(p, &buf, sizeof(buf)))
                return -EFAULT;
@@ -171,6 +171,7 @@ static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p)
        if (sizeof(buf) == sizeof(*st))
                memcpy(&buf, st, sizeof(*st));
        else {
+               memset(&buf, 0, sizeof(buf));
                buf.f_type = st->f_type;
                buf.f_bsize = st->f_bsize;
                buf.f_blocks = st->f_blocks;
@@ -182,7 +183,6 @@ static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p)
                buf.f_namelen = st->f_namelen;
                buf.f_frsize = st->f_frsize;
                buf.f_flags = st->f_flags;
-               memset(buf.f_spare, 0, sizeof(buf.f_spare));
        }
        if (copy_to_user(p, &buf, sizeof(buf)))
                return -EFAULT;
index fcf67d80d7f9cad3d3d8c3b6672f4100e87aed0e..e7bbb7f57557d7bbcbd2e0394539a0af2d274d3e 100644 (file)
@@ -985,9 +985,16 @@ int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name)
        return 0;
 }
 
-/*
+/**
+ * generic_listxattr - run through a dentry's xattr list() operations
+ * @dentry: dentry to list the xattrs
+ * @buffer: result buffer
+ * @buffer_size: size of @buffer
+ *
  * Combine the results of the list() operation from every xattr_handler in the
- * list.
+ * xattr_handler stack.
+ *
+ * Note that this will not include the entries for POSIX ACLs.
  */
 ssize_t
 generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
@@ -996,10 +1003,6 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
        ssize_t remaining_size = buffer_size;
        int err = 0;
 
-       err = posix_acl_listxattr(d_inode(dentry), &buffer, &remaining_size);
-       if (err)
-               return err;
-
        for_each_xattr_handler(handlers, handler) {
                if (!handler->name || (handler->list && !handler->list(dentry)))
                        continue;
index 1b078bbbf2252b850246ba72d29cd77afa881124..9b373a0c7aaf14ff6f13b2071ad8bee978d9401c 100644 (file)
@@ -495,10 +495,12 @@ xfs_freesp_init_recs(
                ASSERT(start >= mp->m_ag_prealloc_blocks);
                if (start != mp->m_ag_prealloc_blocks) {
                        /*
-                        * Modify first record to pad stripe align of log
+                        * Modify first record to pad stripe align of log and
+                        * bump the record count.
                         */
                        arec->ar_blockcount = cpu_to_be32(start -
                                                mp->m_ag_prealloc_blocks);
+                       be16_add_cpu(&block->bb_numrecs, 1);
                        nrec = arec + 1;
 
                        /*
@@ -509,7 +511,6 @@ xfs_freesp_init_recs(
                                        be32_to_cpu(arec->ar_startblock) +
                                        be32_to_cpu(arec->ar_blockcount));
                        arec = nrec;
-                       be16_add_cpu(&block->bb_numrecs, 1);
                }
                /*
                 * Change record start to after the internal log
@@ -518,15 +519,13 @@ xfs_freesp_init_recs(
        }
 
        /*
-        * Calculate the record block count and check for the case where
-        * the log might have consumed all available space in the AG. If
-        * so, reset the record count to 0 to avoid exposure of an invalid
-        * record start block.
+        * Calculate the block count of this record; if it is nonzero,
+        * increment the record count.
         */
        arec->ar_blockcount = cpu_to_be32(id->agsize -
                                          be32_to_cpu(arec->ar_startblock));
-       if (!arec->ar_blockcount)
-               block->bb_numrecs = 0;
+       if (arec->ar_blockcount)
+               be16_add_cpu(&block->bb_numrecs, 1);
 }
 
 /*
@@ -538,7 +537,7 @@ xfs_bnoroot_init(
        struct xfs_buf          *bp,
        struct aghdr_init_data  *id)
 {
-       xfs_btree_init_block(mp, bp, XFS_BTNUM_BNO, 0, 1, id->agno);
+       xfs_btree_init_block(mp, bp, XFS_BTNUM_BNO, 0, 0, id->agno);
        xfs_freesp_init_recs(mp, bp, id);
 }
 
@@ -548,7 +547,7 @@ xfs_cntroot_init(
        struct xfs_buf          *bp,
        struct aghdr_init_data  *id)
 {
-       xfs_btree_init_block(mp, bp, XFS_BTNUM_CNT, 0, 1, id->agno);
+       xfs_btree_init_block(mp, bp, XFS_BTNUM_CNT, 0, 0, id->agno);
        xfs_freesp_init_recs(mp, bp, id);
 }
 
index b512de0540d54f2968d13d56400aaf97704c5fd8..cd8870a16fd14d977826780f651e7f6b12b31ca6 100644 (file)
@@ -3494,8 +3494,10 @@ xfs_bmap_btalloc_at_eof(
                if (!caller_pag)
                        args->pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, ap->blkno));
                error = xfs_alloc_vextent_exact_bno(args, ap->blkno);
-               if (!caller_pag)
+               if (!caller_pag) {
                        xfs_perag_put(args->pag);
+                       args->pag = NULL;
+               }
                if (error)
                        return error;
 
@@ -3505,7 +3507,6 @@ xfs_bmap_btalloc_at_eof(
                 * Exact allocation failed. Reset to try an aligned allocation
                 * according to the original allocation specification.
                 */
-               args->pag = NULL;
                args->alignment = stripe_align;
                args->minlen = nextminlen;
                args->minalignslop = 0;
index 87ab9f95a487adc13fa0e4af24ba1b2b904aac23..69bc89d0fc68dd18dbc9e22723f5143fee808310 100644 (file)
@@ -42,12 +42,12 @@ xchk_setup_inode_bmap(
        xfs_ilock(sc->ip, XFS_IOLOCK_EXCL);
 
        /*
-        * We don't want any ephemeral data fork updates sitting around
+        * We don't want any ephemeral data/cow fork updates sitting around
         * while we inspect block mappings, so wait for directio to finish
         * and flush dirty data if we have delalloc reservations.
         */
        if (S_ISREG(VFS_I(sc->ip)->i_mode) &&
-           sc->sm->sm_type == XFS_SCRUB_TYPE_BMBTD) {
+           sc->sm->sm_type != XFS_SCRUB_TYPE_BMBTA) {
                struct address_space    *mapping = VFS_I(sc->ip)->i_mapping;
 
                sc->ilock_flags |= XFS_MMAPLOCK_EXCL;
index 9aa79665c6080538c72a24ece5166cbff9d8086c..7a20256be969a45c716f7cdf54f23a048c15d4ba 100644 (file)
@@ -1164,32 +1164,6 @@ xchk_metadata_inode_forks(
        return 0;
 }
 
-/* Pause background reaping of resources. */
-void
-xchk_stop_reaping(
-       struct xfs_scrub        *sc)
-{
-       sc->flags |= XCHK_REAPING_DISABLED;
-       xfs_blockgc_stop(sc->mp);
-       xfs_inodegc_stop(sc->mp);
-}
-
-/* Restart background reaping of resources. */
-void
-xchk_start_reaping(
-       struct xfs_scrub        *sc)
-{
-       /*
-        * Readonly filesystems do not perform inactivation or speculative
-        * preallocation, so there's no need to restart the workers.
-        */
-       if (!xfs_is_readonly(sc->mp)) {
-               xfs_inodegc_start(sc->mp);
-               xfs_blockgc_start(sc->mp);
-       }
-       sc->flags &= ~XCHK_REAPING_DISABLED;
-}
-
 /*
  * Enable filesystem hooks (i.e. runtime code patching) before starting a scrub
  * operation.  Callers must not hold any locks that intersect with the CPU
index 18b5f2b62f13620113f23a14f8819980d5ed34e4..791235cd9b0083e6b43c560cd469789b8a90c7ec 100644 (file)
@@ -156,8 +156,6 @@ static inline bool xchk_skip_xref(struct xfs_scrub_metadata *sm)
 }
 
 int xchk_metadata_inode_forks(struct xfs_scrub *sc);
-void xchk_stop_reaping(struct xfs_scrub *sc);
-void xchk_start_reaping(struct xfs_scrub *sc);
 
 /*
  * Setting up a hook to wait for intents to drain is costly -- we have to take
index faa315be7978d4f11715c8c90ea76595f68104a9..e382a35e98d88c81396c33830290039749b6ba6a 100644 (file)
@@ -150,13 +150,6 @@ xchk_setup_fscounters(
        if (error)
                return error;
 
-       /*
-        * Pause background reclaim while we're scrubbing to reduce the
-        * likelihood of background perturbations to the counters throwing off
-        * our calculations.
-        */
-       xchk_stop_reaping(sc);
-
        return xchk_trans_alloc(sc, 0);
 }
 
@@ -453,6 +446,12 @@ xchk_fscounters(
        if (frextents > mp->m_sb.sb_rextents)
                xchk_set_corrupt(sc);
 
+       /*
+        * XXX: We can't quiesce percpu counter updates, so exit early.
+        * This can be re-enabled when we gain exclusive freeze functionality.
+        */
+       return 0;
+
        /*
         * If ifree exceeds icount by more than the minimum variance then
         * something's probably wrong with the counters.
index 02819bedc5b1589e9bc94d4c85d7806f871455c0..3d98f604765e17d8af7e0504ba3dafeb8cdc5b46 100644 (file)
@@ -186,8 +186,6 @@ xchk_teardown(
        }
        if (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR)
                mnt_drop_write_file(sc->file);
-       if (sc->flags & XCHK_REAPING_DISABLED)
-               xchk_start_reaping(sc);
        if (sc->buf) {
                if (sc->buf_cleanup)
                        sc->buf_cleanup(sc->buf);
index e71903474cd794cf90541103926258399bd3feb3..b38e93830ddea2b011ab57a7f900f540a6106e24 100644 (file)
@@ -106,7 +106,6 @@ struct xfs_scrub {
 
 /* XCHK state flags grow up from zero, XREP state flags grown down from 2^31 */
 #define XCHK_TRY_HARDER                (1 << 0)  /* can't get resources, try again */
-#define XCHK_REAPING_DISABLED  (1 << 1)  /* background block reaping paused */
 #define XCHK_FSGATES_DRAIN     (1 << 2)  /* defer ops draining enabled */
 #define XCHK_NEED_DRAIN                (1 << 3)  /* scrub needs to drain defer ops */
 #define XREP_ALREADY_FIXED     (1 << 31) /* checking our repair work */
index 68efd6fda61c15db6fa29c9e89597157584356c7..b3894daeb86a96f10f4d1201a569a494978e62a6 100644 (file)
@@ -98,7 +98,6 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_FSCOUNTERS);
 
 #define XFS_SCRUB_STATE_STRINGS \
        { XCHK_TRY_HARDER,                      "try_harder" }, \
-       { XCHK_REAPING_DISABLED,                "reaping_disabled" }, \
        { XCHK_FSGATES_DRAIN,                   "fsgates_drain" }, \
        { XCHK_NEED_DRAIN,                      "need_drain" }, \
        { XREP_ALREADY_FIXED,                   "already_fixed" }
index f032d3a4b727b1e44c3d0f4aad0acc3d25565555..fbb675563208db12a05b7f825bc1d02c681a4d59 100644 (file)
@@ -558,7 +558,9 @@ xfs_getbmap(
                if (!xfs_iext_next_extent(ifp, &icur, &got)) {
                        xfs_fileoff_t   end = XFS_B_TO_FSB(mp, XFS_ISIZE(ip));
 
-                       out[bmv->bmv_entries - 1].bmv_oflags |= BMV_OF_LAST;
+                       if (bmv->bmv_entries > 0)
+                               out[bmv->bmv_entries - 1].bmv_oflags |=
+                                                               BMV_OF_LAST;
 
                        if (whichfork != XFS_ATTR_FORK && bno < end &&
                            !xfs_getbmap_full(bmv)) {
index 351849fc18ffcc55ffc64a0c6a0593b19fa4aee1..0f60e301eb1fd8b72a9a94a2f062d26ab8e3d19a 100644 (file)
@@ -435,18 +435,23 @@ xfs_iget_check_free_state(
 }
 
 /* Make all pending inactivation work start immediately. */
-static void
+static bool
 xfs_inodegc_queue_all(
        struct xfs_mount        *mp)
 {
        struct xfs_inodegc      *gc;
        int                     cpu;
+       bool                    ret = false;
 
        for_each_online_cpu(cpu) {
                gc = per_cpu_ptr(mp->m_inodegc, cpu);
-               if (!llist_empty(&gc->list))
+               if (!llist_empty(&gc->list)) {
                        mod_delayed_work_on(cpu, mp->m_inodegc_wq, &gc->work, 0);
+                       ret = true;
+               }
        }
+
+       return ret;
 }
 
 /*
@@ -1856,6 +1861,8 @@ xfs_inodegc_worker(
        struct xfs_inode        *ip, *n;
        unsigned int            nofs_flag;
 
+       ASSERT(gc->cpu == smp_processor_id());
+
        WRITE_ONCE(gc->items, 0);
 
        if (!node)
@@ -1909,24 +1916,41 @@ xfs_inodegc_flush(
 
 /*
  * Flush all the pending work and then disable the inode inactivation background
- * workers and wait for them to stop.
+ * workers and wait for them to stop.  Caller must hold sb->s_umount to
+ * coordinate changes in the inodegc_enabled state.
  */
 void
 xfs_inodegc_stop(
        struct xfs_mount        *mp)
 {
+       bool                    rerun;
+
        if (!xfs_clear_inodegc_enabled(mp))
                return;
 
+       /*
+        * Drain all pending inodegc work, including inodes that could be
+        * queued by racing xfs_inodegc_queue or xfs_inodegc_shrinker_scan
+        * threads that sample the inodegc state just prior to us clearing it.
+        * The inodegc flag state prevents new threads from queuing more
+        * inodes, so we queue pending work items and flush the workqueue until
+        * all inodegc lists are empty.  IOWs, we cannot use drain_workqueue
+        * here because it does not allow other unserialized mechanisms to
+        * reschedule inodegc work while this draining is in progress.
+        */
        xfs_inodegc_queue_all(mp);
-       drain_workqueue(mp->m_inodegc_wq);
+       do {
+               flush_workqueue(mp->m_inodegc_wq);
+               rerun = xfs_inodegc_queue_all(mp);
+       } while (rerun);
 
        trace_xfs_inodegc_stop(mp, __return_address);
 }
 
 /*
  * Enable the inode inactivation background workers and schedule deferred inode
- * inactivation work if there is any.
+ * inactivation work if there is any.  Caller must hold sb->s_umount to
+ * coordinate changes in the inodegc_enabled state.
  */
 void
 xfs_inodegc_start(
@@ -2069,7 +2093,8 @@ xfs_inodegc_queue(
                queue_delay = 0;
 
        trace_xfs_inodegc_queue(mp, __return_address);
-       mod_delayed_work(mp->m_inodegc_wq, &gc->work, queue_delay);
+       mod_delayed_work_on(current_cpu(), mp->m_inodegc_wq, &gc->work,
+                       queue_delay);
        put_cpu_ptr(gc);
 
        if (xfs_inodegc_want_flush_work(ip, items, shrinker_hits)) {
@@ -2113,7 +2138,8 @@ xfs_inodegc_cpu_dead(
 
        if (xfs_is_inodegc_enabled(mp)) {
                trace_xfs_inodegc_queue(mp, __return_address);
-               mod_delayed_work(mp->m_inodegc_wq, &gc->work, 0);
+               mod_delayed_work_on(current_cpu(), mp->m_inodegc_wq, &gc->work,
+                               0);
        }
        put_cpu_ptr(gc);
 }
index 285885c308bd7db943ca58357305a52a70cdcb6f..18c8f168b1532d043b76d201fff199a936c0cf0d 100644 (file)
@@ -1006,8 +1006,9 @@ xfs_buffered_write_iomap_begin(
        if (eof)
                imap.br_startoff = end_fsb; /* fake hole until the end */
 
-       /* We never need to allocate blocks for zeroing a hole. */
-       if ((flags & IOMAP_ZERO) && imap.br_startoff > offset_fsb) {
+       /* We never need to allocate blocks for zeroing or unsharing a hole. */
+       if ((flags & (IOMAP_UNSHARE | IOMAP_ZERO)) &&
+           imap.br_startoff > offset_fsb) {
                xfs_hole_to_iomap(ip, iomap, offset_fsb, imap.br_startoff);
                goto out_unlock;
        }
index f3269c0626f0576b669d8881572f1e45ba5cfb80..aaaf5ec13492d2f0b09ae9165be574ba20d80bfd 100644 (file)
@@ -66,6 +66,9 @@ struct xfs_inodegc {
        /* approximate count of inodes in the list */
        unsigned int            items;
        unsigned int            shrinker_hits;
+#if defined(DEBUG) || defined(XFS_WARN)
+       unsigned int            cpu;
+#endif
 };
 
 /*
index 4d2e87462ac4a19499ad45ea17f2246379beb577..7e706255f165027c2c6e161f2878673ac89dad23 100644 (file)
@@ -1095,6 +1095,9 @@ xfs_inodegc_init_percpu(
 
        for_each_possible_cpu(cpu) {
                gc = per_cpu_ptr(mp->m_inodegc, cpu);
+#if defined(DEBUG) || defined(XFS_WARN)
+               gc->cpu = cpu;
+#endif
                init_llist_head(&gc->list);
                gc->items = 0;
                INIT_DELAYED_WORK(&gc->work, xfs_inodegc_worker);
index d1f57e4868ed341dc00e668b1cde16db0a265781..cebdf1ca415de46ba42678a8c9444f788f28611d 100644 (file)
 /*
  * Discard .note.GNU-stack, which is emitted as PROGBITS by the compiler.
  * Otherwise, the type of .notes section would become PROGBITS instead of NOTES.
+ *
+ * Also, discard .note.gnu.property, otherwise it forces the notes section to
+ * be 8-byte aligned which causes alignment mismatches with the kernel's custom
+ * 4-byte aligned notes.
  */
 #define NOTES                                                          \
-       /DISCARD/ : { *(.note.GNU-stack) }                              \
+       /DISCARD/ : {                                                   \
+               *(.note.GNU-stack)                                      \
+               *(.note.gnu.property)                                   \
+       }                                                               \
        .notes : AT(ADDR(.notes) - LOAD_OFFSET) {                       \
                BOUNDED_SECTION_BY(.note.*, _notes)                     \
        } NOTES_HEADERS                                                 \
index 358db4a9f167adc2b710d9e7411a68ee1b2e256b..f8813c1e059bef177a6406f057bef8305fbf5c92 100644 (file)
 
 #define DP_DSC_MAX_BITS_PER_PIXEL_HI        0x068   /* eDP 1.4 */
 # define DP_DSC_MAX_BITS_PER_PIXEL_HI_MASK  (0x3 << 0)
-# define DP_DSC_MAX_BITS_PER_PIXEL_HI_SHIFT 8
-# define DP_DSC_MAX_BPP_DELTA_VERSION_MASK  0x06
-# define DP_DSC_MAX_BPP_DELTA_AVAILABILITY  0x08
+# define DP_DSC_MAX_BPP_DELTA_VERSION_MASK  (0x3 << 5) /* eDP 1.5 & DP 2.0 */
+# define DP_DSC_MAX_BPP_DELTA_AVAILABILITY  (1 << 7)   /* eDP 1.5 & DP 2.0 */
 
 #define DP_DSC_DEC_COLOR_FORMAT_CAP         0x069
 # define DP_DSC_RGB                         (1 << 0)
index 533d3ee7fe05246f94a1fd45c758377206449c65..86f24a759268ae0ac313a6d7ed7a1a0892e38084 100644 (file)
@@ -181,9 +181,8 @@ static inline u16
 drm_edp_dsc_sink_output_bpp(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE])
 {
        return dsc_dpcd[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] |
-               (dsc_dpcd[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] &
-                DP_DSC_MAX_BITS_PER_PIXEL_HI_MASK <<
-                DP_DSC_MAX_BITS_PER_PIXEL_HI_SHIFT);
+               ((dsc_dpcd[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] &
+                 DP_DSC_MAX_BITS_PER_PIXEL_HI_MASK) << 8);
 }
 
 static inline u32
index 359883942612e5eba9ab8ad6a56d2b7cbe5a12e2..ad08f834af408f7d8b01d3335a1332601766eb03 100644 (file)
@@ -105,6 +105,22 @@ char *drmm_kstrdup(struct drm_device *dev, const char *s, gfp_t gfp);
 
 void drmm_kfree(struct drm_device *dev, void *data);
 
-int drmm_mutex_init(struct drm_device *dev, struct mutex *lock);
+void __drmm_mutex_release(struct drm_device *dev, void *res);
+
+/**
+ * drmm_mutex_init - &drm_device-managed mutex_init()
+ * @dev: DRM device
+ * @lock: lock to be initialized
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise.
+ *
+ * This is a &drm_device-managed version of mutex_init(). The initialized
+ * lock is automatically destroyed on the final drm_dev_put().
+ */
+#define drmm_mutex_init(dev, lock) ({                                       \
+       mutex_init(lock);                                                    \
+       drmm_add_action_or_reset(dev, __drmm_mutex_release, lock);           \
+})                                                                          \
 
 #endif
index d3116c52ab720d7f7b45978d31ac01ec4795b939..669ca2d6abce5d36d3c25e71b8df7b44210ad96b 100644 (file)
 #define J721S2_SERDES0_LANE3_USB               0x2
 #define J721S2_SERDES0_LANE3_IP4_UNUSED                0x3
 
+/* J784S4 */
+
+#define J784S4_SERDES0_LANE0_IP1_UNUSED                0x0
+#define J784S4_SERDES0_LANE0_PCIE1_LANE0       0x1
+#define J784S4_SERDES0_LANE0_IP3_UNUSED                0x2
+#define J784S4_SERDES0_LANE0_IP4_UNUSED                0x3
+
+#define J784S4_SERDES0_LANE1_IP1_UNUSED                0x0
+#define J784S4_SERDES0_LANE1_PCIE1_LANE1       0x1
+#define J784S4_SERDES0_LANE1_IP3_UNUSED                0x2
+#define J784S4_SERDES0_LANE1_IP4_UNUSED                0x3
+
+#define J784S4_SERDES0_LANE2_PCIE3_LANE0       0x0
+#define J784S4_SERDES0_LANE2_PCIE1_LANE2       0x1
+#define J784S4_SERDES0_LANE2_IP3_UNUSED                0x2
+#define J784S4_SERDES0_LANE2_IP4_UNUSED                0x3
+
+#define J784S4_SERDES0_LANE3_PCIE3_LANE1       0x0
+#define J784S4_SERDES0_LANE3_PCIE1_LANE3       0x1
+#define J784S4_SERDES0_LANE3_USB               0x2
+#define J784S4_SERDES0_LANE3_IP4_UNUSED                0x3
+
+#define J784S4_SERDES1_LANE0_QSGMII_LANE3      0x0
+#define J784S4_SERDES1_LANE0_PCIE0_LANE0       0x1
+#define J784S4_SERDES1_LANE0_IP3_UNUSED                0x2
+#define J784S4_SERDES1_LANE0_IP4_UNUSED                0x3
+
+#define J784S4_SERDES1_LANE1_QSGMII_LANE4      0x0
+#define J784S4_SERDES1_LANE1_PCIE0_LANE1       0x1
+#define J784S4_SERDES1_LANE1_IP3_UNUSED                0x2
+#define J784S4_SERDES1_LANE1_IP4_UNUSED                0x3
+
+#define J784S4_SERDES1_LANE2_QSGMII_LANE1      0x0
+#define J784S4_SERDES1_LANE2_PCIE0_LANE2       0x1
+#define J784S4_SERDES1_LANE2_PCIE2_LANE0       0x2
+#define J784S4_SERDES1_LANE2_IP4_UNUSED                0x3
+
+#define J784S4_SERDES1_LANE3_QSGMII_LANE2      0x0
+#define J784S4_SERDES1_LANE3_PCIE0_LANE3       0x1
+#define J784S4_SERDES1_LANE3_PCIE2_LANE1       0x2
+#define J784S4_SERDES1_LANE3_IP4_UNUSED                0x3
+
+#define J784S4_SERDES2_LANE0_QSGMII_LANE5      0x0
+#define J784S4_SERDES2_LANE0_IP2_UNUSED                0x1
+#define J784S4_SERDES2_LANE0_IP3_UNUSED                0x2
+#define J784S4_SERDES2_LANE0_IP4_UNUSED                0x3
+
+#define J784S4_SERDES2_LANE1_QSGMII_LANE6      0x0
+#define J784S4_SERDES2_LANE1_IP2_UNUSED                0x1
+#define J784S4_SERDES2_LANE1_IP3_UNUSED                0x2
+#define J784S4_SERDES2_LANE1_IP4_UNUSED                0x3
+
+#define J784S4_SERDES2_LANE2_QSGMII_LANE7      0x0
+#define J784S4_SERDES2_LANE2_QSGMII_LANE1      0x1
+#define J784S4_SERDES2_LANE2_IP3_UNUSED                0x2
+#define J784S4_SERDES2_LANE2_IP4_UNUSED                0x3
+
+#define J784S4_SERDES2_LANE3_QSGMII_LANE8      0x0
+#define J784S4_SERDES2_LANE3_QSGMII_LANE2      0x1
+#define J784S4_SERDES2_LANE3_IP3_UNUSED                0x2
+#define J784S4_SERDES2_LANE3_IP4_UNUSED                0x3
+
 #endif /* _DT_BINDINGS_MUX_TI_SERDES */
index 5001e14c5c06ddac13d6cb64d0d50d8e8b4c7b17..c60a6a14638caa0163ffe0ea20d376b54b1b95ba 100644 (file)
@@ -107,7 +107,7 @@ enum amba_vendor {
 
 extern struct bus_type amba_bustype;
 
-#define to_amba_device(d)      container_of(d, struct amba_device, dev)
+#define to_amba_device(d)      container_of_const(d, struct amba_device, dev)
 
 #define amba_get_drvdata(d)    dev_get_drvdata(&d->dev)
 #define amba_set_drvdata(d,p)  dev_set_drvdata(&d->dev, p)
index c87aeecaa9b2ad3183d1db19a51586e4aafc6e11..583fe3b49a49ccd5e18b1d3963b94e46df00622e 100644 (file)
@@ -96,6 +96,7 @@
 
 /* FFA Bus/Device/Driver related */
 struct ffa_device {
+       u32 id;
        int vm_id;
        bool mode_32bit;
        uuid_t uuid;
index b441e633f4dd497e73dd826b6445c5c1c934751f..c0ffe203a6022807668a37a1183f1bb3a70ecd19 100644 (file)
@@ -1376,8 +1376,6 @@ enum blk_unique_id {
        BLK_UID_NAA     = 3,
 };
 
-#define NFL4_UFLG_MASK                 0x0000003F
-
 struct block_device_operations {
        void (*submit_bio)(struct bio *bio);
        int (*poll_bio)(struct bio *bio, struct io_comp_batch *iob,
index 947a60b801dbde79fa95caac51e4624d85d9e348..d7779a18b24fc3bfe25ad325e9fa802d7552a7b0 100644 (file)
  * Note: DISABLE_BRANCH_PROFILING can be used by special lowlevel code
  * to disable branch tracing on a per file basis.
  */
-#if defined(CONFIG_TRACE_BRANCH_PROFILING) \
-    && !defined(DISABLE_BRANCH_PROFILING) && !defined(__CHECKER__)
 void ftrace_likely_update(struct ftrace_likely_data *f, int val,
                          int expect, int is_constant);
-
+#if defined(CONFIG_TRACE_BRANCH_PROFILING) \
+    && !defined(DISABLE_BRANCH_PROFILING) && !defined(__CHECKER__)
 #define likely_notrace(x)      __builtin_expect(!!(x), 1)
 #define unlikely_notrace(x)    __builtin_expect(!!(x), 0)
 
index eacb7dd7b3af34a6ea82c17eda3752b4cfb072b2..c1a7dc3251215a5ba0e982568a746ff5b04602d1 100644 (file)
@@ -572,4 +572,10 @@ void cper_print_proc_ia(const char *pfx,
 int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg);
 int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg);
 
+struct acpi_hest_generic_status;
+void cper_estatus_print(const char *pfx,
+                       const struct acpi_hest_generic_status *estatus);
+int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus);
+int cper_estatus_check(const struct acpi_hest_generic_status *estatus);
+
 #endif
index 9deeaeb457bbaa504fffbf71c8b368ca4da3034f..abf3d3bfb6fe4dc3f29e26c599a8b18a676793ba 100644 (file)
@@ -74,6 +74,7 @@ struct class {
 struct class_dev_iter {
        struct klist_iter               ki;
        const struct device_type        *type;
+       struct subsys_private           *sp;
 };
 
 int __must_check class_register(const struct class *class);
index 6c5733981563eadf5f06c59c5dc97df961692b02..f343bc9aa2ec95adaa3ea685c38dd596758d88b5 100644 (file)
@@ -236,8 +236,9 @@ void dim_park_tired(struct dim *dim);
  *
  * Calculate the delta between two samples (in data rates).
  * Takes into consideration counter wrap-around.
+ * Returned boolean indicates whether curr_stats are reliable.
  */
-void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
+bool dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
                    struct dim_stats *curr_stats);
 
 /**
index 7aa62c92185f6467069fe07aedb8cf4e0041d352..571d1a6e1b7448c1b07d9c42e610926f8d0b9ef2 100644 (file)
@@ -1338,4 +1338,6 @@ bool efi_config_table_is_usable(const efi_guid_t *guid, unsigned long table)
        return xen_efi_config_table_is_usable(guid, table);
 }
 
+umode_t efi_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n);
+
 #endif /* _LINUX_EFI_H */
index 1716c01c4e5410f26a4d9d5180cc59ccfb50cd3c..efb6e2cf203439d3aaf759f3f80c1745c397b6ff 100644 (file)
@@ -391,7 +391,7 @@ struct fw_iso_packet {
        u32 tag:2;              /* tx: Tag in packet header             */
        u32 sy:4;               /* tx: Sy in packet header              */
        u32 header_length:8;    /* Length of immediate header           */
-       u32 header[0];          /* tx: Top of 1394 isoch. data_block    */
+       u32 header[];           /* tx: Top of 1394 isoch. data_block    */
 };
 
 #define FW_ISO_CONTEXT_TRANSMIT                        0
index f5da516770695265a4fe94ec5a8e904478b3c8c8..9dda7d9898ff7c89b1ca30cfe2a4e9cc20014093 100644 (file)
@@ -4,7 +4,7 @@
  *
  *  Copyright (C) 2014-2021 Xilinx
  *
- *  Michal Simek <michal.simek@xilinx.com>
+ *  Michal Simek <michal.simek@amd.com>
  *  Davorin Mista <davorin.mista@aggios.com>
  *  Jolly Shah <jollys@xilinx.com>
  *  Rajan Vaja <rajanv@xilinx.com>
index 21a98168085641d2ca0f7d6e20e4e279755bbf57..133f0640fb2411478a2dbaacbbee0fec9336c27b 100644 (file)
@@ -1076,29 +1076,29 @@ extern int send_sigurg(struct fown_struct *fown);
  * sb->s_flags.  Note that these mirror the equivalent MS_* flags where
  * represented in both.
  */
-#define SB_RDONLY       1      /* Mount read-only */
-#define SB_NOSUID       2      /* Ignore suid and sgid bits */
-#define SB_NODEV        4      /* Disallow access to device special files */
-#define SB_NOEXEC       8      /* Disallow program execution */
-#define SB_SYNCHRONOUS 16      /* Writes are synced at once */
-#define SB_MANDLOCK    64      /* Allow mandatory locks on an FS */
-#define SB_DIRSYNC     128     /* Directory modifications are synchronous */
-#define SB_NOATIME     1024    /* Do not update access times. */
-#define SB_NODIRATIME  2048    /* Do not update directory access times */
-#define SB_SILENT      32768
-#define SB_POSIXACL    (1<<16) /* VFS does not apply the umask */
-#define SB_INLINECRYPT (1<<17) /* Use blk-crypto for encrypted files */
-#define SB_KERNMOUNT   (1<<22) /* this is a kern_mount call */
-#define SB_I_VERSION   (1<<23) /* Update inode I_version field */
-#define SB_LAZYTIME    (1<<25) /* Update the on-disk [acm]times lazily */
+#define SB_RDONLY       BIT(0) /* Mount read-only */
+#define SB_NOSUID       BIT(1) /* Ignore suid and sgid bits */
+#define SB_NODEV        BIT(2) /* Disallow access to device special files */
+#define SB_NOEXEC       BIT(3) /* Disallow program execution */
+#define SB_SYNCHRONOUS  BIT(4) /* Writes are synced at once */
+#define SB_MANDLOCK     BIT(6) /* Allow mandatory locks on an FS */
+#define SB_DIRSYNC      BIT(7) /* Directory modifications are synchronous */
+#define SB_NOATIME      BIT(10)        /* Do not update access times. */
+#define SB_NODIRATIME   BIT(11)        /* Do not update directory access times */
+#define SB_SILENT       BIT(15)
+#define SB_POSIXACL     BIT(16)        /* VFS does not apply the umask */
+#define SB_INLINECRYPT  BIT(17)        /* Use blk-crypto for encrypted files */
+#define SB_KERNMOUNT    BIT(22)        /* this is a kern_mount call */
+#define SB_I_VERSION    BIT(23)        /* Update inode I_version field */
+#define SB_LAZYTIME     BIT(25)        /* Update the on-disk [acm]times lazily */
 
 /* These sb flags are internal to the kernel */
-#define SB_SUBMOUNT     (1<<26)
-#define SB_FORCE       (1<<27)
-#define SB_NOSEC       (1<<28)
-#define SB_BORN                (1<<29)
-#define SB_ACTIVE      (1<<30)
-#define SB_NOUSER      (1<<31)
+#define SB_SUBMOUNT     BIT(26)
+#define SB_FORCE        BIT(27)
+#define SB_NOSEC        BIT(28)
+#define SB_BORN         BIT(29)
+#define SB_ACTIVE       BIT(30)
+#define SB_NOUSER       BIT(31)
 
 /* These flags relate to encoding and casefolding */
 #define SB_ENC_STRICT_MODE_FL  (1 << 0)
diff --git a/include/linux/i8254.h b/include/linux/i8254.h
new file mode 100644 (file)
index 0000000..a675c30
--- /dev/null
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) William Breathitt Gray */
+#ifndef _I8254_H_
+#define _I8254_H_
+
+struct device;
+struct regmap;
+
+/**
+ * struct i8254_regmap_config - Configuration for the register map of an i8254
+ * @parent:    parent device
+ * @map:       regmap for the i8254
+ */
+struct i8254_regmap_config {
+       struct device *parent;
+       struct regmap *map;
+};
+
+int devm_i8254_regmap_register(struct device *dev, const struct i8254_regmap_config *config);
+
+#endif /* _I8254_H_ */
index fc985e5c739d434148e8ff19d30ebc3ee8abf1d8..8de6b6e678295385071575eaca58fab7614366fe 100644 (file)
@@ -208,6 +208,7 @@ struct team {
        bool queue_override_enabled;
        struct list_head *qom_lists; /* array of queue override mapping lists */
        bool port_mtu_change_allowed;
+       bool notifier_ctx;
        struct {
                unsigned int count;
                unsigned int interval; /* in ms */
index 0f40f379d75cb1e80aaff132842a8d1b968ad087..6ba71957851e22829ec9f18cd29bea2d92dfa583 100644 (file)
@@ -637,6 +637,23 @@ static inline __be16 vlan_get_protocol(const struct sk_buff *skb)
        return __vlan_get_protocol(skb, skb->protocol, NULL);
 }
 
+/* This version of __vlan_get_protocol() also pulls mac header in skb->head */
+static inline __be16 vlan_get_protocol_and_depth(struct sk_buff *skb,
+                                                __be16 type, int *depth)
+{
+       int maclen;
+
+       type = __vlan_get_protocol(skb, type, &maclen);
+
+       if (type) {
+               if (!pskb_may_pull(skb, maclen))
+                       type = 0;
+               else if (depth)
+                       *depth = maclen;
+       }
+       return type;
+}
+
 /* A getter for the SKB protocol field which will handle VLAN tags consistently
  * whether VLAN acceleration is enabled or not.
  */
index f5f3ee57bc70a7bb3aa6d201577d5b88cfe55145..607c3a89a6471df963e6fc4ed09df84b53c0db0f 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/platform_data/st_sensors_pdata.h>
 
 #define LSM9DS0_IMU_DEV_NAME           "lsm9ds0"
+#define LSM303D_IMU_DEV_NAME           "lsm303d"
 
 /*
  * Buffer size max case: 2bytes per channel, 3 channels in total +
index dd64e544a3daa8f1be15d8a47742bf54317d982e..9cb6c80dea716cb80b69bee5277230bafe1c9a95 100644 (file)
@@ -135,7 +135,7 @@ static inline int iio_gts_find_int_time_by_sel(struct iio_gts *gts, int sel)
 /**
  * iio_gts_find_sel_by_int_time - find selector matching integration time
  * @gts:       Gain time scale descriptor
- * @gain:      HW-gain for which matching selector is searched for
+ * @time:      Integration time for which matching selector is searched for
  *
  * Return:     a selector matching given integration time or -EINVAL if
  *             selector was not found.
index 81413cd3a3e7a570627b969a4d976a0d6ba3cfab..6fc06063505a745a03c8b8f9578445c538bb4a6d 100644 (file)
@@ -221,6 +221,9 @@ struct iio_event_spec {
  * @extend_name:       Allows labeling of channel attributes with an
  *                     informative name. Note this has no effect codes etc,
  *                     unlike modifiers.
+ *                     This field is deprecated in favour of providing
+ *                     iio_info->read_label() to override the label, which
+ *                     unlike @extend_name does not affect sysfs filenames.
  * @datasheet_name:    A name used in in-kernel mapping of channels. It should
  *                     correspond to the first name that the channel is referred
  *                     to by in the datasheet (e.g. IND), or the nearest
index 51f52c5c6092e33f55eaefd383df305911372f96..bce3b178819950ac5fab599181efbd71a7d8aa8e 100644 (file)
@@ -171,6 +171,7 @@ void iio_trigger_free(struct iio_trigger *trig);
  */
 bool iio_trigger_using_own(struct iio_dev *indio_dev);
 
+int iio_validate_own_trigger(struct iio_dev *idev, struct iio_trigger *trig);
 int iio_trigger_validate_own_device(struct iio_trigger *trig,
                                     struct iio_dev *indio_dev);
 
index 3399d979ee1ca72b75be67b6794bcfb3ea920011..7fe31b2cd02f1ebac6c2fb8aaf476d07085f7ae2 100644 (file)
@@ -36,6 +36,11 @@ struct io_uring_cmd {
        u8              pdu[32]; /* available inline for free use */
 };
 
+static inline const void *io_uring_sqe_cmd(const struct io_uring_sqe *sqe)
+{
+       return sqe->cmd;
+}
+
 #if defined(CONFIG_IO_URING)
 int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
                              struct iov_iter *iter, void *ioucmd);
@@ -66,11 +71,6 @@ static inline void io_uring_free(struct task_struct *tsk)
        if (tsk->io_uring)
                __io_uring_free(tsk);
 }
-
-static inline const void *io_uring_sqe_cmd(const struct io_uring_sqe *sqe)
-{
-       return sqe->cmd;
-}
 #else
 static inline int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
                              struct iov_iter *iter, void *ioucmd)
index b32256e9e94434e9189688ef4b5dde29e6369b84..74bd269a80a25ee733d7fff4f93114835244fef2 100644 (file)
@@ -344,6 +344,16 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie);
 #define lockdep_repin_lock(l,c)        lock_repin_lock(&(l)->dep_map, (c))
 #define lockdep_unpin_lock(l,c)        lock_unpin_lock(&(l)->dep_map, (c))
 
+/*
+ * Must use lock_map_aquire_try() with override maps to avoid
+ * lockdep thinking they participate in the block chain.
+ */
+#define DEFINE_WAIT_OVERRIDE_MAP(_name, _wait_type)    \
+       struct lockdep_map _name = {                    \
+               .name = #_name "-wait-type-override",   \
+               .wait_type_inner = _wait_type,          \
+               .lock_type = LD_LOCK_WAIT_OVERRIDE, }
+
 #else /* !CONFIG_LOCKDEP */
 
 static inline void lockdep_init_task(struct task_struct *task)
@@ -432,6 +442,9 @@ extern int lockdep_is_held(const void *);
 #define lockdep_repin_lock(l, c)               do { (void)(l); (void)(c); } while (0)
 #define lockdep_unpin_lock(l, c)               do { (void)(l); (void)(c); } while (0)
 
+#define DEFINE_WAIT_OVERRIDE_MAP(_name, _wait_type)    \
+       struct lockdep_map __maybe_unused _name = {}
+
 #endif /* !LOCKDEP */
 
 enum xhlock_context_t {
@@ -556,6 +569,7 @@ do {                                                                        \
 #define rwsem_release(l, i)                    lock_release(l, i)
 
 #define lock_map_acquire(l)                    lock_acquire_exclusive(l, 0, 0, NULL, _THIS_IP_)
+#define lock_map_acquire_try(l)                        lock_acquire_exclusive(l, 0, 1, NULL, _THIS_IP_)
 #define lock_map_acquire_read(l)               lock_acquire_shared_recursive(l, 0, 0, NULL, _THIS_IP_)
 #define lock_map_acquire_tryread(l)            lock_acquire_shared_recursive(l, 0, 1, NULL, _THIS_IP_)
 #define lock_map_release(l)                    lock_release(l, _THIS_IP_)
index d22430840b53f99451cff84abdc202588a45e81d..59f4fb1626ea60e76c27d8d4e9a0f0eaf831bac4 100644 (file)
@@ -33,6 +33,7 @@ enum lockdep_wait_type {
 enum lockdep_lock_type {
        LD_LOCK_NORMAL = 0,     /* normal, catch all */
        LD_LOCK_PERCPU,         /* percpu */
+       LD_LOCK_WAIT_OVERRIDE,  /* annotation */
        LD_LOCK_MAX,
 };
 
diff --git a/include/linux/mfd/tps6594.h b/include/linux/mfd/tps6594.h
new file mode 100644 (file)
index 0000000..3f7c5e2
--- /dev/null
@@ -0,0 +1,1020 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Functions to access TPS6594 Power Management IC
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#ifndef __LINUX_MFD_TPS6594_H
+#define __LINUX_MFD_TPS6594_H
+
+#include <linux/device.h>
+#include <linux/regmap.h>
+
+struct regmap_irq_chip_data;
+
+/* Chip id list */
+enum pmic_id {
+       TPS6594,
+       TPS6593,
+       LP8764,
+};
+
+/* Macro to get page index from register address */
+#define TPS6594_REG_TO_PAGE(reg)       ((reg) >> 8)
+
+/* Registers for page 0 of TPS6594 */
+#define TPS6594_REG_DEV_REV                            0x01
+
+#define TPS6594_REG_NVM_CODE_1                         0x02
+#define TPS6594_REG_NVM_CODE_2                         0x03
+
+#define TPS6594_REG_BUCKX_CTRL(buck_inst)              (0x04 + ((buck_inst) << 1))
+#define TPS6594_REG_BUCKX_CONF(buck_inst)              (0x05 + ((buck_inst) << 1))
+#define TPS6594_REG_BUCKX_VOUT_1(buck_inst)            (0x0e + ((buck_inst) << 1))
+#define TPS6594_REG_BUCKX_VOUT_2(buck_inst)            (0x0f + ((buck_inst) << 1))
+#define TPS6594_REG_BUCKX_PG_WINDOW(buck_inst)         (0x18 + (buck_inst))
+
+#define TPS6594_REG_LDOX_CTRL(ldo_inst)                        (0x1d + (ldo_inst))
+#define TPS6594_REG_LDORTC_CTRL                                0x22
+#define TPS6594_REG_LDOX_VOUT(ldo_inst)                        (0x23 + (ldo_inst))
+#define TPS6594_REG_LDOX_PG_WINDOW(ldo_inst)           (0x27 + (ldo_inst))
+
+#define TPS6594_REG_VCCA_VMON_CTRL                     0x2b
+#define TPS6594_REG_VCCA_PG_WINDOW                     0x2c
+#define TPS6594_REG_VMON1_PG_WINDOW                    0x2d
+#define TPS6594_REG_VMON1_PG_LEVEL                     0x2e
+#define TPS6594_REG_VMON2_PG_WINDOW                    0x2f
+#define TPS6594_REG_VMON2_PG_LEVEL                     0x30
+
+#define TPS6594_REG_GPIOX_CONF(gpio_inst)              (0x31 + (gpio_inst))
+#define TPS6594_REG_NPWRON_CONF                                0x3c
+#define TPS6594_REG_GPIO_OUT_1                         0x3d
+#define TPS6594_REG_GPIO_OUT_2                         0x3e
+#define TPS6594_REG_GPIO_IN_1                          0x3f
+#define TPS6594_REG_GPIO_IN_2                          0x40
+#define TPS6594_REG_GPIOX_OUT(gpio_inst)               (TPS6594_REG_GPIO_OUT_1 + (gpio_inst) / 8)
+#define TPS6594_REG_GPIOX_IN(gpio_inst)                        (TPS6594_REG_GPIO_IN_1 + (gpio_inst) / 8)
+
+#define TPS6594_REG_GPIO_IN_1                          0x3f
+#define TPS6594_REG_GPIO_IN_2                          0x40
+
+#define TPS6594_REG_RAIL_SEL_1                         0x41
+#define TPS6594_REG_RAIL_SEL_2                         0x42
+#define TPS6594_REG_RAIL_SEL_3                         0x43
+
+#define TPS6594_REG_FSM_TRIG_SEL_1                     0x44
+#define TPS6594_REG_FSM_TRIG_SEL_2                     0x45
+#define TPS6594_REG_FSM_TRIG_MASK_1                    0x46
+#define TPS6594_REG_FSM_TRIG_MASK_2                    0x47
+#define TPS6594_REG_FSM_TRIG_MASK_3                    0x48
+
+#define TPS6594_REG_MASK_BUCK1_2                       0x49
+#define TPS6594_REG_MASK_BUCK3_4                       0x4a
+#define TPS6594_REG_MASK_BUCK5                         0x4b
+#define TPS6594_REG_MASK_LDO1_2                                0x4c
+#define TPS6594_REG_MASK_LDO3_4                                0x4d
+#define TPS6594_REG_MASK_VMON                          0x4e
+#define TPS6594_REG_MASK_GPIO1_8_FALL                  0x4f
+#define TPS6594_REG_MASK_GPIO1_8_RISE                  0x50
+#define TPS6594_REG_MASK_GPIO9_11                      0x51
+#define TPS6594_REG_MASK_STARTUP                       0x52
+#define TPS6594_REG_MASK_MISC                          0x53
+#define TPS6594_REG_MASK_MODERATE_ERR                  0x54
+#define TPS6594_REG_MASK_FSM_ERR                       0x56
+#define TPS6594_REG_MASK_COMM_ERR                      0x57
+#define TPS6594_REG_MASK_READBACK_ERR                  0x58
+#define TPS6594_REG_MASK_ESM                           0x59
+
+#define TPS6594_REG_INT_TOP                            0x5a
+#define TPS6594_REG_INT_BUCK                           0x5b
+#define TPS6594_REG_INT_BUCK1_2                                0x5c
+#define TPS6594_REG_INT_BUCK3_4                                0x5d
+#define TPS6594_REG_INT_BUCK5                          0x5e
+#define TPS6594_REG_INT_LDO_VMON                       0x5f
+#define TPS6594_REG_INT_LDO1_2                         0x60
+#define TPS6594_REG_INT_LDO3_4                         0x61
+#define TPS6594_REG_INT_VMON                           0x62
+#define TPS6594_REG_INT_GPIO                           0x63
+#define TPS6594_REG_INT_GPIO1_8                                0x64
+#define TPS6594_REG_INT_STARTUP                                0x65
+#define TPS6594_REG_INT_MISC                           0x66
+#define TPS6594_REG_INT_MODERATE_ERR                   0x67
+#define TPS6594_REG_INT_SEVERE_ERR                     0x68
+#define TPS6594_REG_INT_FSM_ERR                                0x69
+#define TPS6594_REG_INT_COMM_ERR                       0x6a
+#define TPS6594_REG_INT_READBACK_ERR                   0x6b
+#define TPS6594_REG_INT_ESM                            0x6c
+
+#define TPS6594_REG_STAT_BUCK1_2                       0x6d
+#define TPS6594_REG_STAT_BUCK3_4                       0x6e
+#define TPS6594_REG_STAT_BUCK5                         0x6f
+#define TPS6594_REG_STAT_LDO1_2                                0x70
+#define TPS6594_REG_STAT_LDO3_4                                0x71
+#define TPS6594_REG_STAT_VMON                          0x72
+#define TPS6594_REG_STAT_STARTUP                       0x73
+#define TPS6594_REG_STAT_MISC                          0x74
+#define TPS6594_REG_STAT_MODERATE_ERR                  0x75
+#define TPS6594_REG_STAT_SEVERE_ERR                    0x76
+#define TPS6594_REG_STAT_READBACK_ERR                  0x77
+
+#define TPS6594_REG_PGOOD_SEL_1                                0x78
+#define TPS6594_REG_PGOOD_SEL_2                                0x79
+#define TPS6594_REG_PGOOD_SEL_3                                0x7a
+#define TPS6594_REG_PGOOD_SEL_4                                0x7b
+
+#define TPS6594_REG_PLL_CTRL                           0x7c
+
+#define TPS6594_REG_CONFIG_1                           0x7d
+#define TPS6594_REG_CONFIG_2                           0x7e
+
+#define TPS6594_REG_ENABLE_DRV_REG                     0x80
+
+#define TPS6594_REG_MISC_CTRL                          0x81
+
+#define TPS6594_REG_ENABLE_DRV_STAT                    0x82
+
+#define TPS6594_REG_RECOV_CNT_REG_1                    0x83
+#define TPS6594_REG_RECOV_CNT_REG_2                    0x84
+
+#define TPS6594_REG_FSM_I2C_TRIGGERS                   0x85
+#define TPS6594_REG_FSM_NSLEEP_TRIGGERS                        0x86
+
+#define TPS6594_REG_BUCK_RESET_REG                     0x87
+
+#define TPS6594_REG_SPREAD_SPECTRUM_1                  0x88
+
+#define TPS6594_REG_FREQ_SEL                           0x8a
+
+#define TPS6594_REG_FSM_STEP_SIZE                      0x8b
+
+#define TPS6594_REG_LDO_RV_TIMEOUT_REG_1               0x8c
+#define TPS6594_REG_LDO_RV_TIMEOUT_REG_2               0x8d
+
+#define TPS6594_REG_USER_SPARE_REGS                    0x8e
+
+#define TPS6594_REG_ESM_MCU_START_REG                  0x8f
+#define TPS6594_REG_ESM_MCU_DELAY1_REG                 0x90
+#define TPS6594_REG_ESM_MCU_DELAY2_REG                 0x91
+#define TPS6594_REG_ESM_MCU_MODE_CFG                   0x92
+#define TPS6594_REG_ESM_MCU_HMAX_REG                   0x93
+#define TPS6594_REG_ESM_MCU_HMIN_REG                   0x94
+#define TPS6594_REG_ESM_MCU_LMAX_REG                   0x95
+#define TPS6594_REG_ESM_MCU_LMIN_REG                   0x96
+#define TPS6594_REG_ESM_MCU_ERR_CNT_REG                        0x97
+#define TPS6594_REG_ESM_SOC_START_REG                  0x98
+#define TPS6594_REG_ESM_SOC_DELAY1_REG                 0x99
+#define TPS6594_REG_ESM_SOC_DELAY2_REG                 0x9a
+#define TPS6594_REG_ESM_SOC_MODE_CFG                   0x9b
+#define TPS6594_REG_ESM_SOC_HMAX_REG                   0x9c
+#define TPS6594_REG_ESM_SOC_HMIN_REG                   0x9d
+#define TPS6594_REG_ESM_SOC_LMAX_REG                   0x9e
+#define TPS6594_REG_ESM_SOC_LMIN_REG                   0x9f
+#define TPS6594_REG_ESM_SOC_ERR_CNT_REG                        0xa0
+
+#define TPS6594_REG_REGISTER_LOCK                      0xa1
+
+#define TPS6594_REG_MANUFACTURING_VER                  0xa6
+
+#define TPS6594_REG_CUSTOMER_NVM_ID_REG                        0xa7
+
+#define TPS6594_REG_VMON_CONF_REG                      0xa8
+
+#define TPS6594_REG_SOFT_REBOOT_REG                    0xab
+
+#define TPS6594_REG_RTC_SECONDS                                0xb5
+#define TPS6594_REG_RTC_MINUTES                                0xb6
+#define TPS6594_REG_RTC_HOURS                          0xb7
+#define TPS6594_REG_RTC_DAYS                           0xb8
+#define TPS6594_REG_RTC_MONTHS                         0xb9
+#define TPS6594_REG_RTC_YEARS                          0xba
+#define TPS6594_REG_RTC_WEEKS                          0xbb
+
+#define TPS6594_REG_ALARM_SECONDS                      0xbc
+#define TPS6594_REG_ALARM_MINUTES                      0xbd
+#define TPS6594_REG_ALARM_HOURS                                0xbe
+#define TPS6594_REG_ALARM_DAYS                         0xbf
+#define TPS6594_REG_ALARM_MONTHS                       0xc0
+#define TPS6594_REG_ALARM_YEARS                                0xc1
+
+#define TPS6594_REG_RTC_CTRL_1                         0xc2
+#define TPS6594_REG_RTC_CTRL_2                         0xc3
+#define TPS6594_REG_RTC_STATUS                         0xc4
+#define TPS6594_REG_RTC_INTERRUPTS                     0xc5
+#define TPS6594_REG_RTC_COMP_LSB                       0xc6
+#define TPS6594_REG_RTC_COMP_MSB                       0xc7
+#define TPS6594_REG_RTC_RESET_STATUS                   0xc8
+
+#define TPS6594_REG_SCRATCH_PAD_REG_1                  0xc9
+#define TPS6594_REG_SCRATCH_PAD_REG_2                  0xca
+#define TPS6594_REG_SCRATCH_PAD_REG_3                  0xcb
+#define TPS6594_REG_SCRATCH_PAD_REG_4                  0xcc
+
+#define TPS6594_REG_PFSM_DELAY_REG_1                   0xcd
+#define TPS6594_REG_PFSM_DELAY_REG_2                   0xce
+#define TPS6594_REG_PFSM_DELAY_REG_3                   0xcf
+#define TPS6594_REG_PFSM_DELAY_REG_4                   0xd0
+
+/* Registers for page 1 of TPS6594 */
+#define TPS6594_REG_SERIAL_IF_CONFIG                   0x11a
+#define TPS6594_REG_I2C1_ID                            0x122
+#define TPS6594_REG_I2C2_ID                            0x123
+
+/* Registers for page 4 of TPS6594 */
+#define TPS6594_REG_WD_ANSWER_REG                      0x401
+#define TPS6594_REG_WD_QUESTION_ANSW_CNT               0x402
+#define TPS6594_REG_WD_WIN1_CFG                                0x403
+#define TPS6594_REG_WD_WIN2_CFG                                0x404
+#define TPS6594_REG_WD_LONGWIN_CFG                     0x405
+#define TPS6594_REG_WD_MODE_REG                                0x406
+#define TPS6594_REG_WD_QA_CFG                          0x407
+#define TPS6594_REG_WD_ERR_STATUS                      0x408
+#define TPS6594_REG_WD_THR_CFG                         0x409
+#define TPS6594_REG_DWD_FAIL_CNT_REG                   0x40a
+
+/* BUCKX_CTRL register field definition */
+#define TPS6594_BIT_BUCK_EN                            BIT(0)
+#define TPS6594_BIT_BUCK_FPWM                          BIT(1)
+#define TPS6594_BIT_BUCK_FPWM_MP                       BIT(2)
+#define TPS6594_BIT_BUCK_VSEL                          BIT(3)
+#define TPS6594_BIT_BUCK_VMON_EN                       BIT(4)
+#define TPS6594_BIT_BUCK_PLDN                          BIT(5)
+#define TPS6594_BIT_BUCK_RV_SEL                                BIT(7)
+
+/* BUCKX_CONF register field definition */
+#define TPS6594_MASK_BUCK_SLEW_RATE                    GENMASK(2, 0)
+#define TPS6594_MASK_BUCK_ILIM                         GENMASK(5, 3)
+
+/* BUCKX_PG_WINDOW register field definition */
+#define TPS6594_MASK_BUCK_OV_THR                       GENMASK(2, 0)
+#define TPS6594_MASK_BUCK_UV_THR                       GENMASK(5, 3)
+
+/* BUCKX VSET */
+#define TPS6594_MASK_BUCKS_VSET GENMASK(7, 0)
+
+/* LDOX_CTRL register field definition */
+#define TPS6594_BIT_LDO_EN                             BIT(0)
+#define TPS6594_BIT_LDO_SLOW_RAMP                      BIT(1)
+#define TPS6594_BIT_LDO_VMON_EN                                BIT(4)
+#define TPS6594_MASK_LDO_PLDN                          GENMASK(6, 5)
+#define TPS6594_BIT_LDO_RV_SEL                         BIT(7)
+
+/* LDORTC_CTRL register field definition */
+#define TPS6594_BIT_LDORTC_DIS                         BIT(0)
+
+/* LDOX_VOUT register field definition */
+#define TPS6594_MASK_LDO123_VSET                       GENMASK(6, 1)
+#define TPS6594_MASK_LDO4_VSET                         GENMASK(6, 0)
+#define TPS6594_BIT_LDO_BYPASS                         BIT(7)
+
+/* LDOX_PG_WINDOW register field definition */
+#define TPS6594_MASK_LDO_OV_THR                                GENMASK(2, 0)
+#define TPS6594_MASK_LDO_UV_THR                                GENMASK(5, 3)
+
+/* VCCA_VMON_CTRL register field definition */
+#define TPS6594_BIT_VMON_EN                            BIT(0)
+#define TPS6594_BIT_VMON1_EN                           BIT(1)
+#define TPS6594_BIT_VMON1_RV_SEL                       BIT(2)
+#define TPS6594_BIT_VMON2_EN                           BIT(3)
+#define TPS6594_BIT_VMON2_RV_SEL                       BIT(4)
+#define TPS6594_BIT_VMON_DEGLITCH_SEL                  BIT(5)
+
+/* VCCA_PG_WINDOW register field definition */
+#define TPS6594_MASK_VCCA_OV_THR                       GENMASK(2, 0)
+#define TPS6594_MASK_VCCA_UV_THR                       GENMASK(5, 3)
+#define TPS6594_BIT_VCCA_PG_SET                                BIT(6)
+
+/* VMONX_PG_WINDOW register field definition */
+#define TPS6594_MASK_VMONX_OV_THR                      GENMASK(2, 0)
+#define TPS6594_MASK_VMONX_UV_THR                      GENMASK(5, 3)
+#define TPS6594_BIT_VMONX_RANGE                                BIT(6)
+
+/* GPIOX_CONF register field definition */
+#define TPS6594_BIT_GPIO_DIR                           BIT(0)
+#define TPS6594_BIT_GPIO_OD                            BIT(1)
+#define TPS6594_BIT_GPIO_PU_SEL                                BIT(2)
+#define TPS6594_BIT_GPIO_PU_PD_EN                      BIT(3)
+#define TPS6594_BIT_GPIO_DEGLITCH_EN                   BIT(4)
+#define TPS6594_MASK_GPIO_SEL                          GENMASK(7, 5)
+
+/* NPWRON_CONF register field definition */
+#define TPS6594_BIT_NRSTOUT_OD                         BIT(0)
+#define TPS6594_BIT_ENABLE_PU_SEL                      BIT(2)
+#define TPS6594_BIT_ENABLE_PU_PD_EN                    BIT(3)
+#define TPS6594_BIT_ENABLE_DEGLITCH_EN                 BIT(4)
+#define TPS6594_BIT_ENABLE_POL                         BIT(5)
+#define TPS6594_MASK_NPWRON_SEL                                GENMASK(7, 6)
+
+/* GPIO_OUT_X register field definition */
+#define TPS6594_BIT_GPIOX_OUT(gpio_inst)               BIT((gpio_inst) % 8)
+
+/* GPIO_IN_X register field definition */
+#define TPS6594_BIT_GPIOX_IN(gpio_inst)                        BIT((gpio_inst) % 8)
+#define TPS6594_BIT_NPWRON_IN                          BIT(3)
+
+/* RAIL_SEL_1 register field definition */
+#define TPS6594_MASK_BUCK1_GRP_SEL                     GENMASK(1, 0)
+#define TPS6594_MASK_BUCK2_GRP_SEL                     GENMASK(3, 2)
+#define TPS6594_MASK_BUCK3_GRP_SEL                     GENMASK(5, 4)
+#define TPS6594_MASK_BUCK4_GRP_SEL                     GENMASK(7, 6)
+
+/* RAIL_SEL_2 register field definition */
+#define TPS6594_MASK_BUCK5_GRP_SEL                     GENMASK(1, 0)
+#define TPS6594_MASK_LDO1_GRP_SEL                      GENMASK(3, 2)
+#define TPS6594_MASK_LDO2_GRP_SEL                      GENMASK(5, 4)
+#define TPS6594_MASK_LDO3_GRP_SEL                      GENMASK(7, 6)
+
+/* RAIL_SEL_3 register field definition */
+#define TPS6594_MASK_LDO4_GRP_SEL                      GENMASK(1, 0)
+#define TPS6594_MASK_VCCA_GRP_SEL                      GENMASK(3, 2)
+#define TPS6594_MASK_VMON1_GRP_SEL                     GENMASK(5, 4)
+#define TPS6594_MASK_VMON2_GRP_SEL                     GENMASK(7, 6)
+
+/* FSM_TRIG_SEL_1 register field definition */
+#define TPS6594_MASK_MCU_RAIL_TRIG                     GENMASK(1, 0)
+#define TPS6594_MASK_SOC_RAIL_TRIG                     GENMASK(3, 2)
+#define TPS6594_MASK_OTHER_RAIL_TRIG                   GENMASK(5, 4)
+#define TPS6594_MASK_SEVERE_ERR_TRIG                   GENMASK(7, 6)
+
+/* FSM_TRIG_SEL_2 register field definition */
+#define TPS6594_MASK_MODERATE_ERR_TRIG                 GENMASK(1, 0)
+
+/* FSM_TRIG_MASK_X register field definition */
+#define TPS6594_BIT_GPIOX_FSM_MASK(gpio_inst)          BIT(((gpio_inst) << 1) % 8)
+#define TPS6594_BIT_GPIOX_FSM_MASK_POL(gpio_inst)      BIT(((gpio_inst) << 1) % 8 + 1)
+
+/* MASK_BUCKX register field definition */
+#define TPS6594_BIT_BUCKX_OV_MASK(buck_inst)           BIT(((buck_inst) << 2) % 8)
+#define TPS6594_BIT_BUCKX_UV_MASK(buck_inst)           BIT(((buck_inst) << 2) % 8 + 1)
+#define TPS6594_BIT_BUCKX_ILIM_MASK(buck_inst)         BIT(((buck_inst) << 2) % 8 + 3)
+
+/* MASK_LDOX register field definition */
+#define TPS6594_BIT_LDOX_OV_MASK(ldo_inst)             BIT(((ldo_inst) << 2) % 8)
+#define TPS6594_BIT_LDOX_UV_MASK(ldo_inst)             BIT(((ldo_inst) << 2) % 8 + 1)
+#define TPS6594_BIT_LDOX_ILIM_MASK(ldo_inst)           BIT(((ldo_inst) << 2) % 8 + 3)
+
+/* MASK_VMON register field definition */
+#define TPS6594_BIT_VCCA_OV_MASK                       BIT(0)
+#define TPS6594_BIT_VCCA_UV_MASK                       BIT(1)
+#define TPS6594_BIT_VMON1_OV_MASK                      BIT(2)
+#define TPS6594_BIT_VMON1_UV_MASK                      BIT(3)
+#define TPS6594_BIT_VMON2_OV_MASK                      BIT(5)
+#define TPS6594_BIT_VMON2_UV_MASK                      BIT(6)
+
+/* MASK_GPIOX register field definition */
+#define TPS6594_BIT_GPIOX_FALL_MASK(gpio_inst)         BIT((gpio_inst) < 8 ? \
+                                                           (gpio_inst) : (gpio_inst) % 8)
+#define TPS6594_BIT_GPIOX_RISE_MASK(gpio_inst)         BIT((gpio_inst) < 8 ? \
+                                                           (gpio_inst) : (gpio_inst) % 8 + 3)
+
+/* MASK_STARTUP register field definition */
+#define TPS6594_BIT_NPWRON_START_MASK                  BIT(0)
+#define TPS6594_BIT_ENABLE_MASK                                BIT(1)
+#define TPS6594_BIT_FSD_MASK                           BIT(4)
+#define TPS6594_BIT_SOFT_REBOOT_MASK                   BIT(5)
+
+/* MASK_MISC register field definition */
+#define TPS6594_BIT_BIST_PASS_MASK                     BIT(0)
+#define TPS6594_BIT_EXT_CLK_MASK                       BIT(1)
+#define TPS6594_BIT_TWARN_MASK                         BIT(3)
+
+/* MASK_MODERATE_ERR register field definition */
+#define TPS6594_BIT_BIST_FAIL_MASK                     BIT(1)
+#define TPS6594_BIT_REG_CRC_ERR_MASK                   BIT(2)
+#define TPS6594_BIT_SPMI_ERR_MASK                      BIT(4)
+#define TPS6594_BIT_NPWRON_LONG_MASK                   BIT(5)
+#define TPS6594_BIT_NINT_READBACK_MASK                 BIT(6)
+#define TPS6594_BIT_NRSTOUT_READBACK_MASK              BIT(7)
+
+/* MASK_FSM_ERR register field definition */
+#define TPS6594_BIT_IMM_SHUTDOWN_MASK                  BIT(0)
+#define TPS6594_BIT_ORD_SHUTDOWN_MASK                  BIT(1)
+#define TPS6594_BIT_MCU_PWR_ERR_MASK                   BIT(2)
+#define TPS6594_BIT_SOC_PWR_ERR_MASK                   BIT(3)
+
+/* MASK_COMM_ERR register field definition */
+#define TPS6594_BIT_COMM_FRM_ERR_MASK                  BIT(0)
+#define TPS6594_BIT_COMM_CRC_ERR_MASK                  BIT(1)
+#define TPS6594_BIT_COMM_ADR_ERR_MASK                  BIT(3)
+#define TPS6594_BIT_I2C2_CRC_ERR_MASK                  BIT(5)
+#define TPS6594_BIT_I2C2_ADR_ERR_MASK                  BIT(7)
+
+/* MASK_READBACK_ERR register field definition */
+#define TPS6594_BIT_EN_DRV_READBACK_MASK               BIT(0)
+#define TPS6594_BIT_NRSTOUT_SOC_READBACK_MASK          BIT(3)
+
+/* MASK_ESM register field definition */
+#define TPS6594_BIT_ESM_SOC_PIN_MASK                   BIT(0)
+#define TPS6594_BIT_ESM_SOC_FAIL_MASK                  BIT(1)
+#define TPS6594_BIT_ESM_SOC_RST_MASK                   BIT(2)
+#define TPS6594_BIT_ESM_MCU_PIN_MASK                   BIT(3)
+#define TPS6594_BIT_ESM_MCU_FAIL_MASK                  BIT(4)
+#define TPS6594_BIT_ESM_MCU_RST_MASK                   BIT(5)
+
+/* INT_TOP register field definition */
+#define TPS6594_BIT_BUCK_INT                           BIT(0)
+#define TPS6594_BIT_LDO_VMON_INT                       BIT(1)
+#define TPS6594_BIT_GPIO_INT                           BIT(2)
+#define TPS6594_BIT_STARTUP_INT                                BIT(3)
+#define TPS6594_BIT_MISC_INT                           BIT(4)
+#define TPS6594_BIT_MODERATE_ERR_INT                   BIT(5)
+#define TPS6594_BIT_SEVERE_ERR_INT                     BIT(6)
+#define TPS6594_BIT_FSM_ERR_INT                                BIT(7)
+
+/* INT_BUCK register field definition */
+#define TPS6594_BIT_BUCK1_2_INT                                BIT(0)
+#define TPS6594_BIT_BUCK3_4_INT                                BIT(1)
+#define TPS6594_BIT_BUCK5_INT                          BIT(2)
+
+/* INT_BUCKX register field definition */
+#define TPS6594_BIT_BUCKX_OV_INT(buck_inst)            BIT(((buck_inst) << 2) % 8)
+#define TPS6594_BIT_BUCKX_UV_INT(buck_inst)            BIT(((buck_inst) << 2) % 8 + 1)
+#define TPS6594_BIT_BUCKX_SC_INT(buck_inst)            BIT(((buck_inst) << 2) % 8 + 2)
+#define TPS6594_BIT_BUCKX_ILIM_INT(buck_inst)          BIT(((buck_inst) << 2) % 8 + 3)
+
+/* INT_LDO_VMON register field definition */
+#define TPS6594_BIT_LDO1_2_INT                         BIT(0)
+#define TPS6594_BIT_LDO3_4_INT                         BIT(1)
+#define TPS6594_BIT_VCCA_INT                           BIT(4)
+
+/* INT_LDOX register field definition */
+#define TPS6594_BIT_LDOX_OV_INT(ldo_inst)              BIT(((ldo_inst) << 2) % 8)
+#define TPS6594_BIT_LDOX_UV_INT(ldo_inst)              BIT(((ldo_inst) << 2) % 8 + 1)
+#define TPS6594_BIT_LDOX_SC_INT(ldo_inst)              BIT(((ldo_inst) << 2) % 8 + 2)
+#define TPS6594_BIT_LDOX_ILIM_INT(ldo_inst)            BIT(((ldo_inst) << 2) % 8 + 3)
+
+/* INT_VMON register field definition */
+#define TPS6594_BIT_VCCA_OV_INT                                BIT(0)
+#define TPS6594_BIT_VCCA_UV_INT                                BIT(1)
+#define TPS6594_BIT_VMON1_OV_INT                       BIT(2)
+#define TPS6594_BIT_VMON1_UV_INT                       BIT(3)
+#define TPS6594_BIT_VMON1_RV_INT                       BIT(4)
+#define TPS6594_BIT_VMON2_OV_INT                       BIT(5)
+#define TPS6594_BIT_VMON2_UV_INT                       BIT(6)
+#define TPS6594_BIT_VMON2_RV_INT                       BIT(7)
+
+/* INT_GPIO register field definition */
+#define TPS6594_BIT_GPIO9_INT                          BIT(0)
+#define TPS6594_BIT_GPIO10_INT                         BIT(1)
+#define TPS6594_BIT_GPIO11_INT                         BIT(2)
+#define TPS6594_BIT_GPIO1_8_INT                                BIT(3)
+
+/* INT_GPIOX register field definition */
+#define TPS6594_BIT_GPIOX_INT(gpio_inst)               BIT(gpio_inst)
+
+/* INT_STARTUP register field definition */
+#define TPS6594_BIT_NPWRON_START_INT                   BIT(0)
+#define TPS6594_BIT_ENABLE_INT                         BIT(1)
+#define TPS6594_BIT_RTC_INT                            BIT(2)
+#define TPS6594_BIT_FSD_INT                            BIT(4)
+#define TPS6594_BIT_SOFT_REBOOT_INT                    BIT(5)
+
+/* INT_MISC register field definition */
+#define TPS6594_BIT_BIST_PASS_INT                      BIT(0)
+#define TPS6594_BIT_EXT_CLK_INT                                BIT(1)
+#define TPS6594_BIT_TWARN_INT                          BIT(3)
+
+/* INT_MODERATE_ERR register field definition */
+#define TPS6594_BIT_TSD_ORD_INT                                BIT(0)
+#define TPS6594_BIT_BIST_FAIL_INT                      BIT(1)
+#define TPS6594_BIT_REG_CRC_ERR_INT                    BIT(2)
+#define TPS6594_BIT_RECOV_CNT_INT                      BIT(3)
+#define TPS6594_BIT_SPMI_ERR_INT                       BIT(4)
+#define TPS6594_BIT_NPWRON_LONG_INT                    BIT(5)
+#define TPS6594_BIT_NINT_READBACK_INT                  BIT(6)
+#define TPS6594_BIT_NRSTOUT_READBACK_INT               BIT(7)
+
+/* INT_SEVERE_ERR register field definition */
+#define TPS6594_BIT_TSD_IMM_INT                                BIT(0)
+#define TPS6594_BIT_VCCA_OVP_INT                       BIT(1)
+#define TPS6594_BIT_PFSM_ERR_INT                       BIT(2)
+
+/* INT_FSM_ERR register field definition */
+#define TPS6594_BIT_IMM_SHUTDOWN_INT                   BIT(0)
+#define TPS6594_BIT_ORD_SHUTDOWN_INT                   BIT(1)
+#define TPS6594_BIT_MCU_PWR_ERR_INT                    BIT(2)
+#define TPS6594_BIT_SOC_PWR_ERR_INT                    BIT(3)
+#define TPS6594_BIT_COMM_ERR_INT                       BIT(4)
+#define TPS6594_BIT_READBACK_ERR_INT                   BIT(5)
+#define TPS6594_BIT_ESM_INT                            BIT(6)
+#define TPS6594_BIT_WD_INT                             BIT(7)
+
+/* INT_COMM_ERR register field definition */
+#define TPS6594_BIT_COMM_FRM_ERR_INT                   BIT(0)
+#define TPS6594_BIT_COMM_CRC_ERR_INT                   BIT(1)
+#define TPS6594_BIT_COMM_ADR_ERR_INT                   BIT(3)
+#define TPS6594_BIT_I2C2_CRC_ERR_INT                   BIT(5)
+#define TPS6594_BIT_I2C2_ADR_ERR_INT                   BIT(7)
+
+/* INT_READBACK_ERR register field definition */
+#define TPS6594_BIT_EN_DRV_READBACK_INT                        BIT(0)
+#define TPS6594_BIT_NRSTOUT_SOC_READBACK_INT           BIT(3)
+
+/* INT_ESM register field definition */
+#define TPS6594_BIT_ESM_SOC_PIN_INT                    BIT(0)
+#define TPS6594_BIT_ESM_SOC_FAIL_INT                   BIT(1)
+#define TPS6594_BIT_ESM_SOC_RST_INT                    BIT(2)
+#define TPS6594_BIT_ESM_MCU_PIN_INT                    BIT(3)
+#define TPS6594_BIT_ESM_MCU_FAIL_INT                   BIT(4)
+#define TPS6594_BIT_ESM_MCU_RST_INT                    BIT(5)
+
+/* STAT_BUCKX register field definition */
+#define TPS6594_BIT_BUCKX_OV_STAT(buck_inst)           BIT(((buck_inst) << 2) % 8)
+#define TPS6594_BIT_BUCKX_UV_STAT(buck_inst)           BIT(((buck_inst) << 2) % 8 + 1)
+#define TPS6594_BIT_BUCKX_ILIM_STAT(buck_inst)         BIT(((buck_inst) << 2) % 8 + 3)
+
+/* STAT_LDOX register field definition */
+#define TPS6594_BIT_LDOX_OV_STAT(ldo_inst)             BIT(((ldo_inst) << 2) % 8)
+#define TPS6594_BIT_LDOX_UV_STAT(ldo_inst)             BIT(((ldo_inst) << 2) % 8 + 1)
+#define TPS6594_BIT_LDOX_ILIM_STAT(ldo_inst)           BIT(((ldo_inst) << 2) % 8 + 3)
+
+/* STAT_VMON register field definition */
+#define TPS6594_BIT_VCCA_OV_STAT                       BIT(0)
+#define TPS6594_BIT_VCCA_UV_STAT                       BIT(1)
+#define TPS6594_BIT_VMON1_OV_STAT                      BIT(2)
+#define TPS6594_BIT_VMON1_UV_STAT                      BIT(3)
+#define TPS6594_BIT_VMON2_OV_STAT                      BIT(5)
+#define TPS6594_BIT_VMON2_UV_STAT                      BIT(6)
+
+/* STAT_STARTUP register field definition */
+#define TPS6594_BIT_ENABLE_STAT                                BIT(1)
+
+/* STAT_MISC register field definition */
+#define TPS6594_BIT_EXT_CLK_STAT                       BIT(1)
+#define TPS6594_BIT_TWARN_STAT                         BIT(3)
+
+/* STAT_MODERATE_ERR register field definition */
+#define TPS6594_BIT_TSD_ORD_STAT                       BIT(0)
+
+/* STAT_SEVERE_ERR register field definition */
+#define TPS6594_BIT_TSD_IMM_STAT                       BIT(0)
+#define TPS6594_BIT_VCCA_OVP_STAT                      BIT(1)
+
+/* STAT_READBACK_ERR register field definition */
+#define TPS6594_BIT_EN_DRV_READBACK_STAT               BIT(0)
+#define TPS6594_BIT_NINT_READBACK_STAT                 BIT(1)
+#define TPS6594_BIT_NRSTOUT_READBACK_STAT              BIT(2)
+#define TPS6594_BIT_NRSTOUT_SOC_READBACK_STAT          BIT(3)
+
+/* PGOOD_SEL_1 register field definition */
+#define TPS6594_MASK_PGOOD_SEL_BUCK1                   GENMASK(1, 0)
+#define TPS6594_MASK_PGOOD_SEL_BUCK2                   GENMASK(3, 2)
+#define TPS6594_MASK_PGOOD_SEL_BUCK3                   GENMASK(5, 4)
+#define TPS6594_MASK_PGOOD_SEL_BUCK4                   GENMASK(7, 6)
+
+/* PGOOD_SEL_2 register field definition */
+#define TPS6594_MASK_PGOOD_SEL_BUCK5                   GENMASK(1, 0)
+
+/* PGOOD_SEL_3 register field definition */
+#define TPS6594_MASK_PGOOD_SEL_LDO1                    GENMASK(1, 0)
+#define TPS6594_MASK_PGOOD_SEL_LDO2                    GENMASK(3, 2)
+#define TPS6594_MASK_PGOOD_SEL_LDO3                    GENMASK(5, 4)
+#define TPS6594_MASK_PGOOD_SEL_LDO4                    GENMASK(7, 6)
+
+/* PGOOD_SEL_4 register field definition */
+#define TPS6594_BIT_PGOOD_SEL_VCCA                     BIT(0)
+#define TPS6594_BIT_PGOOD_SEL_VMON1                    BIT(1)
+#define TPS6594_BIT_PGOOD_SEL_VMON2                    BIT(2)
+#define TPS6594_BIT_PGOOD_SEL_TDIE_WARN                        BIT(3)
+#define TPS6594_BIT_PGOOD_SEL_NRSTOUT                  BIT(4)
+#define TPS6594_BIT_PGOOD_SEL_NRSTOUT_SOC              BIT(5)
+#define TPS6594_BIT_PGOOD_POL                          BIT(6)
+#define TPS6594_BIT_PGOOD_WINDOW                       BIT(7)
+
+/* PLL_CTRL register field definition */
+#define TPS6594_MASK_EXT_CLK_FREQ                      GENMASK(1, 0)
+
+/* CONFIG_1 register field definition */
+#define TPS6594_BIT_TWARN_LEVEL                                BIT(0)
+#define TPS6594_BIT_TSD_ORD_LEVEL                      BIT(1)
+#define TPS6594_BIT_I2C1_HS                            BIT(3)
+#define TPS6594_BIT_I2C2_HS                            BIT(4)
+#define TPS6594_BIT_EN_ILIM_FSM_CTRL                   BIT(5)
+#define TPS6594_BIT_NSLEEP1_MASK                       BIT(6)
+#define TPS6594_BIT_NSLEEP2_MASK                       BIT(7)
+
+/* CONFIG_2 register field definition */
+#define TPS6594_BIT_BB_CHARGER_EN                      BIT(0)
+#define TPS6594_BIT_BB_ICHR                            BIT(1)
+#define TPS6594_MASK_BB_VEOC                           GENMASK(3, 2)
+#define TPS6594_BB_EOC_RDY                             BIT(7)
+
+/* ENABLE_DRV_REG register field definition */
+#define TPS6594_BIT_ENABLE_DRV                         BIT(0)
+
+/* MISC_CTRL register field definition */
+#define TPS6594_BIT_NRSTOUT                            BIT(0)
+#define TPS6594_BIT_NRSTOUT_SOC                                BIT(1)
+#define TPS6594_BIT_LPM_EN                             BIT(2)
+#define TPS6594_BIT_CLKMON_EN                          BIT(3)
+#define TPS6594_BIT_AMUXOUT_EN                         BIT(4)
+#define TPS6594_BIT_SEL_EXT_CLK                                BIT(5)
+#define TPS6594_MASK_SYNCCLKOUT_FREQ_SEL               GENMASK(7, 6)
+
+/* ENABLE_DRV_STAT register field definition */
+#define TPS6594_BIT_EN_DRV_IN                          BIT(0)
+#define TPS6594_BIT_NRSTOUT_IN                         BIT(1)
+#define TPS6594_BIT_NRSTOUT_SOC_IN                     BIT(2)
+#define TPS6594_BIT_FORCE_EN_DRV_LOW                   BIT(3)
+#define TPS6594_BIT_SPMI_LPM_EN                                BIT(4)
+
+/* RECOV_CNT_REG_1 register field definition */
+#define TPS6594_MASK_RECOV_CNT                         GENMASK(3, 0)
+
+/* RECOV_CNT_REG_2 register field definition */
+#define TPS6594_MASK_RECOV_CNT_THR                     GENMASK(3, 0)
+#define TPS6594_BIT_RECOV_CNT_CLR                      BIT(4)
+
+/* FSM_I2C_TRIGGERS register field definition */
+#define TPS6594_BIT_TRIGGER_I2C(bit)                   BIT(bit)
+
+/* FSM_NSLEEP_TRIGGERS register field definition */
+#define TPS6594_BIT_NSLEEP1B                           BIT(0)
+#define TPS6594_BIT_NSLEEP2B                           BIT(1)
+
+/* BUCK_RESET_REG register field definition */
+#define TPS6594_BIT_BUCKX_RESET(buck_inst)             BIT(buck_inst)
+
+/* SPREAD_SPECTRUM_1 register field definition */
+#define TPS6594_MASK_SS_DEPTH                          GENMASK(1, 0)
+#define TPS6594_BIT_SS_EN                              BIT(2)
+
+/* FREQ_SEL register field definition */
+#define TPS6594_BIT_BUCKX_FREQ_SEL(buck_inst)          BIT(buck_inst)
+
+/* FSM_STEP_SIZE register field definition */
+#define TPS6594_MASK_PFSM_DELAY_STEP                   GENMASK(4, 0)
+
+/* LDO_RV_TIMEOUT_REG_1 register field definition */
+#define TPS6594_MASK_LDO1_RV_TIMEOUT                   GENMASK(3, 0)
+#define TPS6594_MASK_LDO2_RV_TIMEOUT                   GENMASK(7, 4)
+
+/* LDO_RV_TIMEOUT_REG_2 register field definition */
+#define TPS6594_MASK_LDO3_RV_TIMEOUT                   GENMASK(3, 0)
+#define TPS6594_MASK_LDO4_RV_TIMEOUT                   GENMASK(7, 4)
+
+/* USER_SPARE_REGS register field definition */
+#define TPS6594_BIT_USER_SPARE(bit)                    BIT(bit)
+
+/* ESM_MCU_START_REG register field definition */
+#define TPS6594_BIT_ESM_MCU_START                      BIT(0)
+
+/* ESM_MCU_MODE_CFG register field definition */
+#define TPS6594_MASK_ESM_MCU_ERR_CNT_TH                        GENMASK(3, 0)
+#define TPS6594_BIT_ESM_MCU_ENDRV                      BIT(5)
+#define TPS6594_BIT_ESM_MCU_EN                         BIT(6)
+#define TPS6594_BIT_ESM_MCU_MODE                       BIT(7)
+
+/* ESM_MCU_ERR_CNT_REG register field definition */
+#define TPS6594_MASK_ESM_MCU_ERR_CNT                   GENMASK(4, 0)
+
+/* ESM_SOC_START_REG register field definition */
+#define TPS6594_BIT_ESM_SOC_START                      BIT(0)
+
+/* ESM_SOC_MODE_CFG register field definition */
+#define TPS6594_MASK_ESM_SOC_ERR_CNT_TH                        GENMASK(3, 0)
+#define TPS6594_BIT_ESM_SOC_ENDRV                      BIT(5)
+#define TPS6594_BIT_ESM_SOC_EN                         BIT(6)
+#define TPS6594_BIT_ESM_SOC_MODE                       BIT(7)
+
+/* ESM_SOC_ERR_CNT_REG register field definition */
+#define TPS6594_MASK_ESM_SOC_ERR_CNT                   GENMASK(4, 0)
+
+/* REGISTER_LOCK register field definition */
+#define TPS6594_BIT_REGISTER_LOCK_STATUS               BIT(0)
+
+/* VMON_CONF register field definition */
+#define TPS6594_MASK_VMON1_SLEW_RATE                   GENMASK(2, 0)
+#define TPS6594_MASK_VMON2_SLEW_RATE                   GENMASK(5, 3)
+
+/* SOFT_REBOOT_REG register field definition */
+#define TPS6594_BIT_SOFT_REBOOT                                BIT(0)
+
+/* RTC_SECONDS & ALARM_SECONDS register field definition */
+#define TPS6594_MASK_SECOND_0                          GENMASK(3, 0)
+#define TPS6594_MASK_SECOND_1                          GENMASK(6, 4)
+
+/* RTC_MINUTES & ALARM_MINUTES register field definition */
+#define TPS6594_MASK_MINUTE_0                          GENMASK(3, 0)
+#define TPS6594_MASK_MINUTE_1                          GENMASK(6, 4)
+
+/* RTC_HOURS & ALARM_HOURS register field definition */
+#define TPS6594_MASK_HOUR_0                            GENMASK(3, 0)
+#define TPS6594_MASK_HOUR_1                            GENMASK(5, 4)
+#define TPS6594_BIT_PM_NAM                             BIT(7)
+
+/* RTC_DAYS & ALARM_DAYS register field definition */
+#define TPS6594_MASK_DAY_0                             GENMASK(3, 0)
+#define TPS6594_MASK_DAY_1                             GENMASK(5, 4)
+
+/* RTC_MONTHS & ALARM_MONTHS register field definition */
+#define TPS6594_MASK_MONTH_0                           GENMASK(3, 0)
+#define TPS6594_BIT_MONTH_1                            BIT(4)
+
+/* RTC_YEARS & ALARM_YEARS register field definition */
+#define TPS6594_MASK_YEAR_0                            GENMASK(3, 0)
+#define TPS6594_MASK_YEAR_1                            GENMASK(7, 4)
+
+/* RTC_WEEKS register field definition */
+#define TPS6594_MASK_WEEK                              GENMASK(2, 0)
+
+/* RTC_CTRL_1 register field definition */
+#define TPS6594_BIT_STOP_RTC                           BIT(0)
+#define TPS6594_BIT_ROUND_30S                          BIT(1)
+#define TPS6594_BIT_AUTO_COMP                          BIT(2)
+#define TPS6594_BIT_MODE_12_24                         BIT(3)
+#define TPS6594_BIT_SET_32_COUNTER                     BIT(5)
+#define TPS6594_BIT_GET_TIME                           BIT(6)
+#define TPS6594_BIT_RTC_V_OPT                          BIT(7)
+
+/* RTC_CTRL_2 register field definition */
+#define TPS6594_BIT_XTAL_EN                            BIT(0)
+#define TPS6594_MASK_XTAL_SEL                          GENMASK(2, 1)
+#define TPS6594_BIT_LP_STANDBY_SEL                     BIT(3)
+#define TPS6594_BIT_FAST_BIST                          BIT(4)
+#define TPS6594_MASK_STARTUP_DEST                      GENMASK(6, 5)
+#define TPS6594_BIT_FIRST_STARTUP_DONE                 BIT(7)
+
+/* RTC_STATUS register field definition */
+#define TPS6594_BIT_RUN                                        BIT(1)
+#define TPS6594_BIT_TIMER                              BIT(5)
+#define TPS6594_BIT_ALARM                              BIT(6)
+#define TPS6594_BIT_POWER_UP                           BIT(7)
+
+/* RTC_INTERRUPTS register field definition */
+#define TPS6594_MASK_EVERY                             GENMASK(1, 0)
+#define TPS6594_BIT_IT_TIMER                           BIT(2)
+#define TPS6594_BIT_IT_ALARM                           BIT(3)
+
+/* RTC_RESET_STATUS register field definition */
+#define TPS6594_BIT_RESET_STATUS_RTC                   BIT(0)
+
+/* SERIAL_IF_CONFIG register field definition */
+#define TPS6594_BIT_I2C_SPI_SEL                                BIT(0)
+#define TPS6594_BIT_I2C1_SPI_CRC_EN                    BIT(1)
+#define TPS6594_BIT_I2C2_CRC_EN                                BIT(2)
+#define TPS6594_MASK_T_CRC                             GENMASK(7, 3)
+
+/* WD_QUESTION_ANSW_CNT register field definition */
+#define TPS6594_MASK_WD_QUESTION                       GENMASK(3, 0)
+#define TPS6594_MASK_WD_ANSW_CNT                       GENMASK(5, 4)
+
+/* WD_MODE_REG register field definition */
+#define TPS6594_BIT_WD_RETURN_LONGWIN                  BIT(0)
+#define TPS6594_BIT_WD_MODE_SELECT                     BIT(1)
+#define TPS6594_BIT_WD_PWRHOLD                         BIT(2)
+
+/* WD_QA_CFG register field definition */
+#define TPS6594_MASK_WD_QUESTION_SEED                  GENMASK(3, 0)
+#define TPS6594_MASK_WD_QA_LFSR                                GENMASK(5, 4)
+#define TPS6594_MASK_WD_QA_FDBK                                GENMASK(7, 6)
+
+/* WD_ERR_STATUS register field definition */
+#define TPS6594_BIT_WD_LONGWIN_TIMEOUT_INT             BIT(0)
+#define TPS6594_BIT_WD_TIMEOUT                         BIT(1)
+#define TPS6594_BIT_WD_TRIG_EARLY                      BIT(2)
+#define TPS6594_BIT_WD_ANSW_EARLY                      BIT(3)
+#define TPS6594_BIT_WD_SEQ_ERR                         BIT(4)
+#define TPS6594_BIT_WD_ANSW_ERR                                BIT(5)
+#define TPS6594_BIT_WD_FAIL_INT                                BIT(6)
+#define TPS6594_BIT_WD_RST_INT                         BIT(7)
+
+/* WD_THR_CFG register field definition */
+#define TPS6594_MASK_WD_RST_TH                         GENMASK(2, 0)
+#define TPS6594_MASK_WD_FAIL_TH                                GENMASK(5, 3)
+#define TPS6594_BIT_WD_EN                              BIT(6)
+#define TPS6594_BIT_WD_RST_EN                          BIT(7)
+
+/* WD_FAIL_CNT_REG register field definition */
+#define TPS6594_MASK_WD_FAIL_CNT                       GENMASK(3, 0)
+#define TPS6594_BIT_WD_FIRST_OK                                BIT(5)
+#define TPS6594_BIT_WD_BAD_EVENT                       BIT(6)
+
+/* CRC8 polynomial for I2C & SPI protocols */
+#define TPS6594_CRC8_POLYNOMIAL        0x07
+
+/* IRQs */
+enum tps6594_irqs {
+       /* INT_BUCK1_2 register */
+       TPS6594_IRQ_BUCK1_OV,
+       TPS6594_IRQ_BUCK1_UV,
+       TPS6594_IRQ_BUCK1_SC,
+       TPS6594_IRQ_BUCK1_ILIM,
+       TPS6594_IRQ_BUCK2_OV,
+       TPS6594_IRQ_BUCK2_UV,
+       TPS6594_IRQ_BUCK2_SC,
+       TPS6594_IRQ_BUCK2_ILIM,
+       /* INT_BUCK3_4 register */
+       TPS6594_IRQ_BUCK3_OV,
+       TPS6594_IRQ_BUCK3_UV,
+       TPS6594_IRQ_BUCK3_SC,
+       TPS6594_IRQ_BUCK3_ILIM,
+       TPS6594_IRQ_BUCK4_OV,
+       TPS6594_IRQ_BUCK4_UV,
+       TPS6594_IRQ_BUCK4_SC,
+       TPS6594_IRQ_BUCK4_ILIM,
+       /* INT_BUCK5 register */
+       TPS6594_IRQ_BUCK5_OV,
+       TPS6594_IRQ_BUCK5_UV,
+       TPS6594_IRQ_BUCK5_SC,
+       TPS6594_IRQ_BUCK5_ILIM,
+       /* INT_LDO1_2 register */
+       TPS6594_IRQ_LDO1_OV,
+       TPS6594_IRQ_LDO1_UV,
+       TPS6594_IRQ_LDO1_SC,
+       TPS6594_IRQ_LDO1_ILIM,
+       TPS6594_IRQ_LDO2_OV,
+       TPS6594_IRQ_LDO2_UV,
+       TPS6594_IRQ_LDO2_SC,
+       TPS6594_IRQ_LDO2_ILIM,
+       /* INT_LDO3_4 register */
+       TPS6594_IRQ_LDO3_OV,
+       TPS6594_IRQ_LDO3_UV,
+       TPS6594_IRQ_LDO3_SC,
+       TPS6594_IRQ_LDO3_ILIM,
+       TPS6594_IRQ_LDO4_OV,
+       TPS6594_IRQ_LDO4_UV,
+       TPS6594_IRQ_LDO4_SC,
+       TPS6594_IRQ_LDO4_ILIM,
+       /* INT_VMON register */
+       TPS6594_IRQ_VCCA_OV,
+       TPS6594_IRQ_VCCA_UV,
+       TPS6594_IRQ_VMON1_OV,
+       TPS6594_IRQ_VMON1_UV,
+       TPS6594_IRQ_VMON1_RV,
+       TPS6594_IRQ_VMON2_OV,
+       TPS6594_IRQ_VMON2_UV,
+       TPS6594_IRQ_VMON2_RV,
+       /* INT_GPIO register */
+       TPS6594_IRQ_GPIO9,
+       TPS6594_IRQ_GPIO10,
+       TPS6594_IRQ_GPIO11,
+       /* INT_GPIO1_8 register */
+       TPS6594_IRQ_GPIO1,
+       TPS6594_IRQ_GPIO2,
+       TPS6594_IRQ_GPIO3,
+       TPS6594_IRQ_GPIO4,
+       TPS6594_IRQ_GPIO5,
+       TPS6594_IRQ_GPIO6,
+       TPS6594_IRQ_GPIO7,
+       TPS6594_IRQ_GPIO8,
+       /* INT_STARTUP register */
+       TPS6594_IRQ_NPWRON_START,
+       TPS6594_IRQ_ENABLE,
+       TPS6594_IRQ_FSD,
+       TPS6594_IRQ_SOFT_REBOOT,
+       /* INT_MISC register */
+       TPS6594_IRQ_BIST_PASS,
+       TPS6594_IRQ_EXT_CLK,
+       TPS6594_IRQ_TWARN,
+       /* INT_MODERATE_ERR register */
+       TPS6594_IRQ_TSD_ORD,
+       TPS6594_IRQ_BIST_FAIL,
+       TPS6594_IRQ_REG_CRC_ERR,
+       TPS6594_IRQ_RECOV_CNT,
+       TPS6594_IRQ_SPMI_ERR,
+       TPS6594_IRQ_NPWRON_LONG,
+       TPS6594_IRQ_NINT_READBACK,
+       TPS6594_IRQ_NRSTOUT_READBACK,
+       /* INT_SEVERE_ERR register */
+       TPS6594_IRQ_TSD_IMM,
+       TPS6594_IRQ_VCCA_OVP,
+       TPS6594_IRQ_PFSM_ERR,
+       /* INT_FSM_ERR register */
+       TPS6594_IRQ_IMM_SHUTDOWN,
+       TPS6594_IRQ_ORD_SHUTDOWN,
+       TPS6594_IRQ_MCU_PWR_ERR,
+       TPS6594_IRQ_SOC_PWR_ERR,
+       /* INT_COMM_ERR register */
+       TPS6594_IRQ_COMM_FRM_ERR,
+       TPS6594_IRQ_COMM_CRC_ERR,
+       TPS6594_IRQ_COMM_ADR_ERR,
+       TPS6594_IRQ_I2C2_CRC_ERR,
+       TPS6594_IRQ_I2C2_ADR_ERR,
+       /* INT_READBACK_ERR register */
+       TPS6594_IRQ_EN_DRV_READBACK,
+       TPS6594_IRQ_NRSTOUT_SOC_READBACK,
+       /* INT_ESM register */
+       TPS6594_IRQ_ESM_SOC_PIN,
+       TPS6594_IRQ_ESM_SOC_FAIL,
+       TPS6594_IRQ_ESM_SOC_RST,
+       /* RTC_STATUS register */
+       TPS6594_IRQ_TIMER,
+       TPS6594_IRQ_ALARM,
+       TPS6594_IRQ_POWER_UP,
+};
+
+#define TPS6594_IRQ_NAME_BUCK1_OV              "buck1_ov"
+#define TPS6594_IRQ_NAME_BUCK1_UV              "buck1_uv"
+#define TPS6594_IRQ_NAME_BUCK1_SC              "buck1_sc"
+#define TPS6594_IRQ_NAME_BUCK1_ILIM            "buck1_ilim"
+#define TPS6594_IRQ_NAME_BUCK2_OV              "buck2_ov"
+#define TPS6594_IRQ_NAME_BUCK2_UV              "buck2_uv"
+#define TPS6594_IRQ_NAME_BUCK2_SC              "buck2_sc"
+#define TPS6594_IRQ_NAME_BUCK2_ILIM            "buck2_ilim"
+#define TPS6594_IRQ_NAME_BUCK3_OV              "buck3_ov"
+#define TPS6594_IRQ_NAME_BUCK3_UV              "buck3_uv"
+#define TPS6594_IRQ_NAME_BUCK3_SC              "buck3_sc"
+#define TPS6594_IRQ_NAME_BUCK3_ILIM            "buck3_ilim"
+#define TPS6594_IRQ_NAME_BUCK4_OV              "buck4_ov"
+#define TPS6594_IRQ_NAME_BUCK4_UV              "buck4_uv"
+#define TPS6594_IRQ_NAME_BUCK4_SC              "buck4_sc"
+#define TPS6594_IRQ_NAME_BUCK4_ILIM            "buck4_ilim"
+#define TPS6594_IRQ_NAME_BUCK5_OV              "buck5_ov"
+#define TPS6594_IRQ_NAME_BUCK5_UV              "buck5_uv"
+#define TPS6594_IRQ_NAME_BUCK5_SC              "buck5_sc"
+#define TPS6594_IRQ_NAME_BUCK5_ILIM            "buck5_ilim"
+#define TPS6594_IRQ_NAME_LDO1_OV               "ldo1_ov"
+#define TPS6594_IRQ_NAME_LDO1_UV               "ldo1_uv"
+#define TPS6594_IRQ_NAME_LDO1_SC               "ldo1_sc"
+#define TPS6594_IRQ_NAME_LDO1_ILIM             "ldo1_ilim"
+#define TPS6594_IRQ_NAME_LDO2_OV               "ldo2_ov"
+#define TPS6594_IRQ_NAME_LDO2_UV               "ldo2_uv"
+#define TPS6594_IRQ_NAME_LDO2_SC               "ldo2_sc"
+#define TPS6594_IRQ_NAME_LDO2_ILIM             "ldo2_ilim"
+#define TPS6594_IRQ_NAME_LDO3_OV               "ldo3_ov"
+#define TPS6594_IRQ_NAME_LDO3_UV               "ldo3_uv"
+#define TPS6594_IRQ_NAME_LDO3_SC               "ldo3_sc"
+#define TPS6594_IRQ_NAME_LDO3_ILIM             "ldo3_ilim"
+#define TPS6594_IRQ_NAME_LDO4_OV               "ldo4_ov"
+#define TPS6594_IRQ_NAME_LDO4_UV               "ldo4_uv"
+#define TPS6594_IRQ_NAME_LDO4_SC               "ldo4_sc"
+#define TPS6594_IRQ_NAME_LDO4_ILIM             "ldo4_ilim"
+#define TPS6594_IRQ_NAME_VCCA_OV               "vcca_ov"
+#define TPS6594_IRQ_NAME_VCCA_UV               "vcca_uv"
+#define TPS6594_IRQ_NAME_VMON1_OV              "vmon1_ov"
+#define TPS6594_IRQ_NAME_VMON1_UV              "vmon1_uv"
+#define TPS6594_IRQ_NAME_VMON1_RV              "vmon1_rv"
+#define TPS6594_IRQ_NAME_VMON2_OV              "vmon2_ov"
+#define TPS6594_IRQ_NAME_VMON2_UV              "vmon2_uv"
+#define TPS6594_IRQ_NAME_VMON2_RV              "vmon2_rv"
+#define TPS6594_IRQ_NAME_GPIO9                 "gpio9"
+#define TPS6594_IRQ_NAME_GPIO10                        "gpio10"
+#define TPS6594_IRQ_NAME_GPIO11                        "gpio11"
+#define TPS6594_IRQ_NAME_GPIO1                 "gpio1"
+#define TPS6594_IRQ_NAME_GPIO2                 "gpio2"
+#define TPS6594_IRQ_NAME_GPIO3                 "gpio3"
+#define TPS6594_IRQ_NAME_GPIO4                 "gpio4"
+#define TPS6594_IRQ_NAME_GPIO5                 "gpio5"
+#define TPS6594_IRQ_NAME_GPIO6                 "gpio6"
+#define TPS6594_IRQ_NAME_GPIO7                 "gpio7"
+#define TPS6594_IRQ_NAME_GPIO8                 "gpio8"
+#define TPS6594_IRQ_NAME_NPWRON_START          "npwron_start"
+#define TPS6594_IRQ_NAME_ENABLE                        "enable"
+#define TPS6594_IRQ_NAME_FSD                   "fsd"
+#define TPS6594_IRQ_NAME_SOFT_REBOOT           "soft_reboot"
+#define TPS6594_IRQ_NAME_BIST_PASS             "bist_pass"
+#define TPS6594_IRQ_NAME_EXT_CLK               "ext_clk"
+#define TPS6594_IRQ_NAME_TWARN                 "twarn"
+#define TPS6594_IRQ_NAME_TSD_ORD               "tsd_ord"
+#define TPS6594_IRQ_NAME_BIST_FAIL             "bist_fail"
+#define TPS6594_IRQ_NAME_REG_CRC_ERR           "reg_crc_err"
+#define TPS6594_IRQ_NAME_RECOV_CNT             "recov_cnt"
+#define TPS6594_IRQ_NAME_SPMI_ERR              "spmi_err"
+#define TPS6594_IRQ_NAME_NPWRON_LONG           "npwron_long"
+#define TPS6594_IRQ_NAME_NINT_READBACK         "nint_readback"
+#define TPS6594_IRQ_NAME_NRSTOUT_READBACK      "nrstout_readback"
+#define TPS6594_IRQ_NAME_TSD_IMM               "tsd_imm"
+#define TPS6594_IRQ_NAME_VCCA_OVP              "vcca_ovp"
+#define TPS6594_IRQ_NAME_PFSM_ERR              "pfsm_err"
+#define TPS6594_IRQ_NAME_IMM_SHUTDOWN          "imm_shutdown"
+#define TPS6594_IRQ_NAME_ORD_SHUTDOWN          "ord_shutdown"
+#define TPS6594_IRQ_NAME_MCU_PWR_ERR           "mcu_pwr_err"
+#define TPS6594_IRQ_NAME_SOC_PWR_ERR           "soc_pwr_err"
+#define TPS6594_IRQ_NAME_COMM_FRM_ERR          "comm_frm_err"
+#define TPS6594_IRQ_NAME_COMM_CRC_ERR          "comm_crc_err"
+#define TPS6594_IRQ_NAME_COMM_ADR_ERR          "comm_adr_err"
+#define TPS6594_IRQ_NAME_EN_DRV_READBACK       "en_drv_readback"
+#define TPS6594_IRQ_NAME_NRSTOUT_SOC_READBACK  "nrstout_soc_readback"
+#define TPS6594_IRQ_NAME_ESM_SOC_PIN           "esm_soc_pin"
+#define TPS6594_IRQ_NAME_ESM_SOC_FAIL          "esm_soc_fail"
+#define TPS6594_IRQ_NAME_ESM_SOC_RST           "esm_soc_rst"
+#define TPS6594_IRQ_NAME_TIMER                 "timer"
+#define TPS6594_IRQ_NAME_ALARM                 "alarm"
+#define TPS6594_IRQ_NAME_POWERUP               "powerup"
+
+/**
+ * struct tps6594 - device private data structure
+ *
+ * @dev:      MFD parent device
+ * @chip_id:  chip ID
+ * @reg:      I2C slave address or SPI chip select number
+ * @use_crc:  if true, use CRC for I2C and SPI interface protocols
+ * @regmap:   regmap for accessing the device registers
+ * @irq:      irq generated by the device
+ * @irq_data: regmap irq data used for the irq chip
+ */
+struct tps6594 {
+       struct device *dev;
+       unsigned long chip_id;
+       unsigned short reg;
+       bool use_crc;
+       struct regmap *regmap;
+       int irq;
+       struct regmap_irq_chip_data *irq_data;
+};
+
+bool tps6594_is_volatile_reg(struct device *dev, unsigned int reg);
+int tps6594_device_init(struct tps6594 *tps, bool enable_crc);
+
+#endif /*  __LINUX_MFD_TPS6594_H */
index a4c4f737f9c112a7f760b46571291c50dd008727..94d2be5848ae622f87a3a004b2bbd3277f0c5d7d 100644 (file)
@@ -1093,6 +1093,7 @@ void mlx5_cmdif_debugfs_cleanup(struct mlx5_core_dev *dev);
 int mlx5_core_create_psv(struct mlx5_core_dev *dev, u32 pdn,
                         int npsvs, u32 *sig_index);
 int mlx5_core_destroy_psv(struct mlx5_core_dev *dev, int psv_num);
+__be32 mlx5_core_get_terminate_scatter_list_mkey(struct mlx5_core_dev *dev);
 void mlx5_core_put_rsc(struct mlx5_core_rsc_common *common);
 int mlx5_query_odp_caps(struct mlx5_core_dev *dev,
                        struct mlx5_odp_caps *odp_caps);
index dc5e2cb302a5943532e01d7e3c40cd56b980bb44..b89778d0d3267cb1e03e4078f6149579416c799c 100644 (file)
@@ -1705,7 +1705,9 @@ struct mlx5_ifc_cmd_hca_cap_bits {
        u8         rc[0x1];
 
        u8         uar_4k[0x1];
-       u8         reserved_at_241[0x9];
+       u8         reserved_at_241[0x7];
+       u8         fl_rc_qp_when_roce_disabled[0x1];
+       u8         regexp_params[0x1];
        u8         uar_sz[0x6];
        u8         port_selection_cap[0x1];
        u8         reserved_at_248[0x1];
index cdb14a1ef26810c26a54b94efb3b281996bc7b5e..a50ea79522f85af88f82460f979339ce93d7fbce 100644 (file)
@@ -383,6 +383,13 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
 void arch_teardown_msi_irq(unsigned int irq);
 int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
 void arch_teardown_msi_irqs(struct pci_dev *dev);
+#endif /* CONFIG_PCI_MSI_ARCH_FALLBACKS */
+
+/*
+ * Xen uses non-default msi_domain_ops and hence needs a way to populate sysfs
+ * entries of MSI IRQs.
+ */
+#if defined(CONFIG_PCI_XEN) || defined(CONFIG_PCI_MSI_ARCH_FALLBACKS)
 #ifdef CONFIG_SYSFS
 int msi_device_populate_sysfs(struct device *dev);
 void msi_device_destroy_sysfs(struct device *dev);
@@ -390,7 +397,7 @@ void msi_device_destroy_sysfs(struct device *dev);
 static inline int msi_device_populate_sysfs(struct device *dev) { return 0; }
 static inline void msi_device_destroy_sysfs(struct device *dev) { }
 #endif /* !CONFIG_SYSFS */
-#endif /* CONFIG_PCI_MSI_ARCH_FALLBACKS */
+#endif /* CONFIG_PCI_XEN || CONFIG_PCI_MSI_ARCH_FALLBACKS */
 
 /*
  * The restore hook is still available even for fully irq domain based
index 1c68d67b832ff2bb48c0b7c9dd5fcbe5e9eb27f6..92a2063a0a2323eb44f9fe871a6b5f8928dceffa 100644 (file)
@@ -617,6 +617,12 @@ PAGEFLAG_FALSE(VmemmapSelfHosted, vmemmap_self_hosted)
  * Please note that, confusingly, "page_mapping" refers to the inode
  * address_space which maps the page from disk; whereas "page_mapped"
  * refers to user virtual address space into which the page is mapped.
+ *
+ * For slab pages, since slab reuses the bits in struct page to store its
+ * internal states, the page->mapping does not exist as such, nor do these
+ * flags below.  So in order to avoid testing non-existent bits, please
+ * make sure that PageSlab(page) actually evaluates to false before calling
+ * the following functions (e.g., PageAnon).  See mm/slab.h.
  */
 #define PAGE_MAPPING_ANON      0x1
 #define PAGE_MAPPING_MOVABLE   0x2
index a0bc9e0267b7a1e0f0b7c272ba732eabbd6071a3..fff39bc3062905fc9072ecea60ca90f6806676b5 100644 (file)
@@ -514,7 +514,7 @@ extern int parport_device_proc_register(struct pardevice *device);
 extern int parport_device_proc_unregister(struct pardevice *device);
 
 /* If PC hardware is the only type supported, we can optimise a bit.  */
-#if !defined(CONFIG_PARPORT_NOT_PC)
+#if !defined(CONFIG_PARPORT_NOT_PC) && defined(CONFIG_PARPORT_PC)
 
 #include <linux/parport_pc.h>
 #define parport_write_data(p,x)            parport_pc_write_data(p,x)
index 45c3d62e616d858a2532b80d58a4574dcfc4a4f2..95f33dadb2be2549ef2404649587a1ed22da57d0 100644 (file)
 #define PCI_DEVICE_ID_AMD_19H_M50H_DF_F3 0x166d
 #define PCI_DEVICE_ID_AMD_19H_M60H_DF_F3 0x14e3
 #define PCI_DEVICE_ID_AMD_19H_M70H_DF_F3 0x14f3
+#define PCI_DEVICE_ID_AMD_19H_M78H_DF_F3 0x12fb
 #define PCI_DEVICE_ID_AMD_CNB17H_F3    0x1703
 #define PCI_DEVICE_ID_AMD_LANCE                0x2000
 #define PCI_DEVICE_ID_AMD_LANCE_HOME   0x2001
index 5e1e115408702c777996a2bfd2ca33c0f1547705..fdf9c95709ba097d31fa1581e4658595fa57d866 100644 (file)
 #include <linux/types.h>
 
 /*
- * Linux EFI stub v1.0 adds the following functionality:
- * - Loading initrd from the LINUX_EFI_INITRD_MEDIA_GUID device path,
- * - Loading/starting the kernel from firmware that targets a different
- *   machine type, via the entrypoint exposed in the .compat PE/COFF section.
+ * Starting from version v3.0, the major version field should be interpreted as
+ * a bit mask of features supported by the kernel's EFI stub:
+ * - 0x1: initrd loading from the LINUX_EFI_INITRD_MEDIA_GUID device path,
+ * - 0x2: initrd loading using the initrd= command line option, where the file
+ *        may be specified using device path notation, and is not required to
+ *        reside on the same volume as the loaded kernel image.
  *
  * The recommended way of loading and starting v1.0 or later kernels is to use
  * the LoadImage() and StartImage() EFI boot services, and expose the initrd
  * via the LINUX_EFI_INITRD_MEDIA_GUID device path.
  *
- * Versions older than v1.0 support initrd loading via the image load options
- * (using initrd=, limited to the volume from which the kernel itself was
- * loaded), or via arch specific means (bootparams, DT, etc).
+ * Versions older than v1.0 may support initrd loading via the image load
+ * options (using initrd=, limited to the volume from which the kernel itself
+ * was loaded), or only via arch specific means (bootparams, DT, etc).
  *
- * On x86, LoadImage() and StartImage() can be omitted if the EFI handover
- * protocol is implemented, which can be inferred from the version,
- * handover_offset and xloadflags fields in the bootparams structure.
+ * The minor version field must remain 0x0.
+ * (https://lore.kernel.org/all/efd6f2d4-547c-1378-1faa-53c044dbd297@gmail.com/)
  */
-#define LINUX_EFISTUB_MAJOR_VERSION            0x1
-#define LINUX_EFISTUB_MINOR_VERSION            0x1
+#define LINUX_EFISTUB_MAJOR_VERSION            0x3
+#define LINUX_EFISTUB_MINOR_VERSION            0x0
 
 /*
  * LINUX_PE_MAGIC appears at offset 0x38 into the MS-DOS header of EFI bootable
index c5a0dc829714fb0e301551102451a064b42bd549..6478838405a088e229fff4b802540e9cfae527e0 100644 (file)
@@ -1900,10 +1900,8 @@ void phy_package_leave(struct phy_device *phydev);
 int devm_phy_package_join(struct device *dev, struct phy_device *phydev,
                          int addr, size_t priv_size);
 
-#if IS_ENABLED(CONFIG_PHYLIB)
 int __init mdio_bus_init(void);
 void mdio_bus_exit(void);
-#endif
 
 int phy_ethtool_get_strings(struct phy_device *phydev, u8 *data);
 int phy_ethtool_get_sset_count(struct phy_device *phydev);
index 897051e51b786e2580ca612668513b09dd2b956d..a657830232ae24f1768102c2620da466bec7ec7b 100644 (file)
@@ -15,7 +15,7 @@
  * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2).
  *     Available only for accelerometer, magnetometer and pressure sensors.
  *     Accelerometer DRDY on LSM330 available only on pin 1 (see datasheet).
- *     Magnetometer DRDY is supported only on LSM9DS0.
+ *     Magnetometer DRDY is supported only on LSM9DS0 and LSM303D.
  * @open_drain: set the interrupt line to be open drain if possible.
  * @spi_3wire: enable spi-3wire mode.
  * @pullups: enable/disable i2c controller pullup resistors.
index a1aa68141d0b54615bddc2b2eaa8774b85e1dca1..7c8d65414a70ad5784badca31fedf2c95d44fc0c 100644 (file)
@@ -2,6 +2,8 @@
 #ifndef __LINUX_BQ27X00_BATTERY_H__
 #define __LINUX_BQ27X00_BATTERY_H__
 
+#include <linux/power_supply.h>
+
 enum bq27xxx_chip {
        BQ27000 = 1, /* bq27000, bq27200 */
        BQ27010, /* bq27010, bq27210 */
@@ -68,7 +70,9 @@ struct bq27xxx_device_info {
        struct bq27xxx_access_methods bus;
        struct bq27xxx_reg_cache cache;
        int charge_design_full;
+       bool removed;
        unsigned long last_update;
+       union power_supply_propval last_status;
        struct delayed_work work;
        struct power_supply *bat;
        struct list_head list;
index 537cbf9a2adeab8ef6bc372474ab63afe292d74d..e0f5ac90a228bdb916031594cebd52f7bbe40d62 100644 (file)
@@ -29,7 +29,6 @@ struct kernel_clone_args {
        u32 io_thread:1;
        u32 user_worker:1;
        u32 no_files:1;
-       u32 ignore_signals:1;
        unsigned long stack;
        unsigned long stack_size;
        unsigned long tls;
index 6123c10b99cf3548c9360cb0d19c6062ba0a00a6..837a23624a66a3ed1ceb6958e0fe8f5a98065d82 100644 (file)
@@ -2,22 +2,13 @@
 #ifndef _LINUX_VHOST_TASK_H
 #define _LINUX_VHOST_TASK_H
 
-#include <linux/completion.h>
 
-struct task_struct;
+struct vhost_task;
 
-struct vhost_task {
-       int (*fn)(void *data);
-       void *data;
-       struct completion exited;
-       unsigned long flags;
-       struct task_struct *task;
-};
-
-struct vhost_task *vhost_task_create(int (*fn)(void *), void *arg,
+struct vhost_task *vhost_task_create(bool (*fn)(void *), void *arg,
                                     const char *name);
 void vhost_task_start(struct vhost_task *vtsk);
 void vhost_task_stop(struct vhost_task *vtsk);
-bool vhost_task_should_stop(struct vhost_task *vtsk);
+void vhost_task_wake(struct vhost_task *vtsk);
 
 #endif
index 7bde8e1c228af65d5dadcea501b80c6bc1655219..224293b2dd0663ee56777bc20a5c19f02089d569 100644 (file)
@@ -107,7 +107,10 @@ extern void synchronize_shrinkers(void);
 
 #ifdef CONFIG_SHRINKER_DEBUG
 extern int shrinker_debugfs_add(struct shrinker *shrinker);
-extern struct dentry *shrinker_debugfs_remove(struct shrinker *shrinker);
+extern struct dentry *shrinker_debugfs_detach(struct shrinker *shrinker,
+                                             int *debugfs_id);
+extern void shrinker_debugfs_remove(struct dentry *debugfs_entry,
+                                   int debugfs_id);
 extern int __printf(2, 3) shrinker_debugfs_rename(struct shrinker *shrinker,
                                                  const char *fmt, ...);
 #else /* CONFIG_SHRINKER_DEBUG */
@@ -115,10 +118,16 @@ static inline int shrinker_debugfs_add(struct shrinker *shrinker)
 {
        return 0;
 }
-static inline struct dentry *shrinker_debugfs_remove(struct shrinker *shrinker)
+static inline struct dentry *shrinker_debugfs_detach(struct shrinker *shrinker,
+                                                    int *debugfs_id)
 {
+       *debugfs_id = -1;
        return NULL;
 }
+static inline void shrinker_debugfs_remove(struct dentry *debugfs_entry,
+                                          int debugfs_id)
+{
+}
 static inline __printf(2, 3)
 int shrinker_debugfs_rename(struct shrinker *shrinker, const char *fmt, ...)
 {
index 738776ab8838621ad7653cefb31efbc6298972a4..0b40417457cd12b919fa14d54782570ed6feec89 100644 (file)
@@ -1587,6 +1587,16 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
        to->l4_hash = from->l4_hash;
 };
 
+static inline int skb_cmp_decrypted(const struct sk_buff *skb1,
+                                   const struct sk_buff *skb2)
+{
+#ifdef CONFIG_TLS_DEVICE
+       return skb2->decrypted - skb1->decrypted;
+#else
+       return 0;
+#endif
+}
+
 static inline void skb_copy_decrypted(struct sk_buff *to,
                                      const struct sk_buff *from)
 {
index 84f787416a54d4597aa9a0f032a63d43ecc8aac7..054d7911bfc9f3430c1b7fc124b9b48ad9c391e5 100644 (file)
@@ -71,7 +71,6 @@ struct sk_psock_link {
 };
 
 struct sk_psock_work_state {
-       struct sk_buff                  *skb;
        u32                             len;
        u32                             off;
 };
@@ -105,7 +104,7 @@ struct sk_psock {
        struct proto                    *sk_proto;
        struct mutex                    work_mutex;
        struct sk_psock_work_state      work_state;
-       struct work_struct              work;
+       struct delayed_work             work;
        struct rcu_work                 rwork;
 };
 
index 24aa159d29a7f8eca658baf224c807d67b55d416..fbc4bd423b355953e374f4291083ab50aae287d3 100644 (file)
@@ -176,7 +176,7 @@ extern struct svc_rdma_recv_ctxt *
 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 void svc_rdma_release_ctxt(struct svc_xprt *xprt, void *ctxt);
 extern int svc_rdma_recvfrom(struct svc_rqst *);
 
 /* svc_rdma_rw.c */
index 867479204840da00c2baf8ff4050d9af96f16b2d..a6b12631db21c8f4264164824e3d43ada45cc151 100644 (file)
@@ -23,7 +23,7 @@ struct svc_xprt_ops {
        int             (*xpo_sendto)(struct svc_rqst *);
        int             (*xpo_result_payload)(struct svc_rqst *, unsigned int,
                                              unsigned int);
-       void            (*xpo_release_rqst)(struct svc_rqst *);
+       void            (*xpo_release_ctxt)(struct svc_xprt *xprt, void *ctxt);
        void            (*xpo_detach)(struct svc_xprt *);
        void            (*xpo_free)(struct svc_xprt *);
        void            (*xpo_kill_temp_xprt)(struct svc_xprt *);
index d16ae621782c0c3eb35e96ef3b3ee1e58e8e5aa4..a7116048a4d4bcd6a658c5c01b15e875228a37a5 100644 (file)
@@ -61,10 +61,9 @@ int          svc_recv(struct svc_rqst *, long);
 void           svc_send(struct svc_rqst *rqstp);
 void           svc_drop(struct svc_rqst *);
 void           svc_sock_update_bufs(struct svc_serv *serv);
-bool           svc_alien_sock(struct net *net, int fd);
-int            svc_addsock(struct svc_serv *serv, const int fd,
-                                       char *name_return, const size_t len,
-                                       const struct cred *cred);
+int            svc_addsock(struct svc_serv *serv, struct net *net,
+                           const int fd, char *name_return, const size_t len,
+                           const struct cred *cred);
 void           svc_init_xprt_sock(void);
 void           svc_cleanup_xprt_sock(void);
 struct svc_xprt *svc_sock_create(struct svc_serv *serv, int prot);
index 77693389c3f9a69152cb3958040c08241d52d372..6a1e8f157255186249d1743c9951b4d9ab66eb35 100644 (file)
@@ -282,6 +282,7 @@ enum tpm_chip_flags {
        TPM_CHIP_FLAG_ALWAYS_POWERED            = BIT(5),
        TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED    = BIT(6),
        TPM_CHIP_FLAG_FIRMWARE_UPGRADE          = BIT(7),
+       TPM_CHIP_FLAG_SUSPENDED                 = BIT(8),
 };
 
 #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
index 0e373222a6df8a983f19238239e51954e5bf1535..7c4a0b72334eb4e9eb8b476153317b984d9cc716 100644 (file)
@@ -806,6 +806,7 @@ enum {
        FILTER_TRACE_FN,
        FILTER_COMM,
        FILTER_CPU,
+       FILTER_STACKTRACE,
 };
 
 extern int trace_event_raw_init(struct trace_event_call *call);
index 0a81c3dfd26c802ee7998520b3757f435766021b..e290c026994408519c14546cd995a2fafec237d6 100644 (file)
@@ -86,6 +86,7 @@ enum uacce_q_state {
  * @state: queue state machine
  * @pasid: pasid associated to the mm
  * @handle: iommu_sva handle returned by iommu_sva_bind_device()
+ * @mapping: user space mapping of the queue
  */
 struct uacce_queue {
        struct uacce_device *uacce;
@@ -97,6 +98,7 @@ struct uacce_queue {
        enum uacce_q_state state;
        u32 pasid;
        struct iommu_sva *handle;
+       struct address_space *mapping;
 };
 
 /**
@@ -114,7 +116,6 @@ struct uacce_queue {
  * @mutex: protects uacce operation
  * @priv: private pointer of the uacce
  * @queues: list of queues
- * @inode: core vfs
  */
 struct uacce_device {
        const char *algs;
@@ -130,7 +131,6 @@ struct uacce_device {
        struct mutex mutex;
        void *priv;
        struct list_head queues;
-       struct inode *inode;
 };
 
 #if IS_ENABLED(CONFIG_UACCE)
index a2448e98854f6355b37573111b4b92faad965c3d..07531c4f435040eb4349c1632b82eeaf00312ce8 100644 (file)
@@ -443,7 +443,7 @@ static inline struct usb_composite_driver *to_cdriver(
  * @bcd_webusb_version: 0x0100 by default, WebUSB specification version
  * @b_webusb_vendor_code: 0x0 by default, vendor code for WebUSB
  * @landing_page: empty by default, landing page to announce in WebUSB
- * @use_webusb:: false by default, interested gadgets set it
+ * @use_webusb: false by default, interested gadgets set it
  * @os_desc_config: the configuration to be used with OS descriptors
  * @setup_pending: true when setup request is queued but not completed
  * @os_desc_pending: true when os_desc request is queued but not completed
index 094c77eaf455165c435baa1679e56860ca39413e..0c7eff91adf4ecac8d783daa33d3ed4c4f895c4b 100644 (file)
@@ -501,6 +501,11 @@ void *hcd_buffer_alloc(struct usb_bus *bus, size_t size,
 void hcd_buffer_free(struct usb_bus *bus, size_t size,
        void *addr, dma_addr_t dma);
 
+void *hcd_buffer_alloc_pages(struct usb_hcd *hcd,
+               size_t size, gfp_t mem_flags, dma_addr_t *dma);
+void hcd_buffer_free_pages(struct usb_hcd *hcd,
+               size_t size, void *addr, dma_addr_t dma);
+
 /* generic bus glue, needed for host controllers that don't use PCI */
 extern irqreturn_t usb_hcd_irq(int irq, void *__hcd);
 
index 2847f5a18a861e2268ce8d0a8b899511cd43ed80..8afa8c3a097308854b50f2fdde6ba727e20b162b 100644 (file)
 
 #ifdef CONFIG_USER_EVENTS
 struct user_event_mm {
-       struct list_head        link;
+       struct list_head        mms_link;
        struct list_head        enablers;
        struct mm_struct        *mm;
+       /* Used for one-shot lists, protected by event_mutex */
        struct user_event_mm    *next;
        refcount_t              refcnt;
        refcount_t              tasks;
index e7c44870f20de4972a66c1ecab380cacb7f62d16..367d5381217b58091ee54446097f2e02b25846c1 100644 (file)
@@ -686,7 +686,10 @@ struct dtv_frontend_properties {
  * @id:                        Frontend ID
  * @exit:              Used to inform the DVB core that the frontend
  *                     thread should exit (usually, means that the hardware
- *                     got disconnected.
+ *                     got disconnected).
+ * @remove_mutex:      mutex that avoids a race condition between a callback
+ *                     called when the hardware is disconnected and the
+ *                     file_operations of dvb_frontend.
  */
 
 struct dvb_frontend {
@@ -704,6 +707,7 @@ struct dvb_frontend {
        int (*callback)(void *adapter_priv, int component, int cmd, int arg);
        int id;
        unsigned int exit;
+       struct mutex remove_mutex;
 };
 
 /**
index 9980b1dd750b34b878223e7ad227f197571a2d6a..4a921ea96091c1cfa169925a71913f3ae6c91458 100644 (file)
@@ -39,6 +39,9 @@ struct net_device;
  * @exit:              flag to indicate when the device is being removed.
  * @demux:             pointer to &struct dmx_demux.
  * @ioctl_mutex:       protect access to this struct.
+ * @remove_mutex:      mutex that avoids a race condition between a callback
+ *                     called when the hardware is disconnected and the
+ *                     file_operations of dvb_net.
  *
  * Currently, the core supports up to %DVB_NET_DEVICES_MAX (10) network
  * devices.
@@ -51,6 +54,7 @@ struct dvb_net {
        unsigned int exit:1;
        struct dmx_demux *demux;
        struct mutex ioctl_mutex;
+       struct mutex remove_mutex;
 };
 
 /**
index 29d25c8a6f13fa09d7f0b1a48b2dab299d90ba7d..8958e5e2fc5b77b46ef84c5026cd581e55812cce 100644 (file)
@@ -193,6 +193,21 @@ struct dvb_device {
        void *priv;
 };
 
+/**
+ * struct dvbdevfops_node - fops nodes registered in dvbdevfops_list
+ *
+ * @fops:              Dynamically allocated fops for ->owner registration
+ * @type:              type of dvb_device
+ * @template:          dvb_device used for registration
+ * @list_head:         list_head for dvbdevfops_list
+ */
+struct dvbdevfops_node {
+       struct file_operations *fops;
+       enum dvb_device_type type;
+       const struct dvb_device *template;
+       struct list_head list_head;
+};
+
 /**
  * dvb_device_get - Increase dvb_device reference
  *
index cfd19e72d0fc455ee0a0784c47d78f733d7d9482..b325df0d54d6190089f8a20ed6ef5ee1def80ea2 100644 (file)
@@ -1119,6 +1119,7 @@ struct v4l2_subdev {
  * @vfh: pointer to &struct v4l2_fh
  * @state: pointer to &struct v4l2_subdev_state
  * @owner: module pointer to the owner of this file handle
+ * @client_caps: bitmask of ``V4L2_SUBDEV_CLIENT_CAP_*``
  */
 struct v4l2_subdev_fh {
        struct v4l2_fh vfh;
index a6c8aee2f256c600f9d4f3eca7811a8d0471206d..8baf346399397e5f0de123c5a19de71679c94d66 100644 (file)
@@ -1327,7 +1327,7 @@ int hci_le_create_cis(struct hci_conn *conn);
 
 struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
                              u8 role);
-int hci_conn_del(struct hci_conn *conn);
+void hci_conn_del(struct hci_conn *conn);
 void hci_conn_hash_flush(struct hci_dev *hdev);
 void hci_conn_check_pending(struct hci_dev *hdev);
 
index a60a24923b559972d72320588fe05de50ca4195e..59955ac3315787139f8e543851e5945dffc4aebe 100644 (file)
@@ -221,6 +221,7 @@ struct bonding {
        struct   bond_up_slave __rcu *usable_slaves;
        struct   bond_up_slave __rcu *all_slaves;
        bool     force_primary;
+       bool     notifier_ctx;
        s32      slave_cnt; /* never change this value outside the attach/detach wrappers */
        int     (*recv_probe)(const struct sk_buff *, struct bonding *,
                              struct slave *);
@@ -233,7 +234,7 @@ struct bonding {
         */
        spinlock_t mode_lock;
        spinlock_t stats_lock;
-       u      send_peer_notif;
+       u32      send_peer_notif;
        u8       igmp_retrans;
 #ifdef CONFIG_PROC_FS
        struct   proc_dir_entry *proc_entry;
index 3352b1ab43b35163391cf872d1577bbe810dbc21..2e26e436e85f566699af91401a36c44dc445b84d 100644 (file)
@@ -24,6 +24,7 @@ struct tls_handshake_args {
        struct socket           *ta_sock;
        tls_done_func_t         ta_done;
        void                    *ta_data;
+       const char              *ta_peername;
        unsigned int            ta_timeout_ms;
        key_serial_t            ta_keyring;
        key_serial_t            ta_my_cert;
index c3fffaa92d6e034be07c7b2624e06e42207ea44b..acec504c469a0fdb48e8d09de8c895e93576e004 100644 (file)
@@ -76,6 +76,7 @@ struct ipcm_cookie {
        __be32                  addr;
        int                     oif;
        struct ip_options_rcu   *opt;
+       __u8                    protocol;
        __u8                    ttl;
        __s16                   tos;
        char                    priority;
@@ -96,6 +97,7 @@ static inline void ipcm_init_sk(struct ipcm_cookie *ipcm,
        ipcm->sockc.tsflags = inet->sk.sk_tsflags;
        ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if);
        ipcm->addr = inet->inet_saddr;
+       ipcm->protocol = inet->inet_num;
 }
 
 #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
index cd386aa7c7cc328d7226ac1c44362e46926eb363..9eef199728454ba03eba291f5e1e61f8399ef57e 100644 (file)
@@ -347,10 +347,8 @@ struct mana_tx_qp {
 struct mana_ethtool_stats {
        u64 stop_queue;
        u64 wake_queue;
-       u64 tx_cqes;
        u64 tx_cqe_err;
        u64 tx_cqe_unknown_type;
-       u64 rx_cqes;
        u64 rx_coalesced_err;
        u64 rx_cqe_unknown_type;
 };
index 9fa291a046211e4fc1c7ae56094a124c4ce0a516..2b12725de9c094f6ac89831576a2556d5dad5e64 100644 (file)
@@ -497,29 +497,6 @@ static inline struct fib6_nh *nexthop_fib6_nh(struct nexthop *nh)
        return NULL;
 }
 
-/* Variant of nexthop_fib6_nh().
- * Caller should either hold rcu_read_lock(), or RTNL.
- */
-static inline struct fib6_nh *nexthop_fib6_nh_bh(struct nexthop *nh)
-{
-       struct nh_info *nhi;
-
-       if (nh->is_group) {
-               struct nh_group *nh_grp;
-
-               nh_grp = rcu_dereference_rtnl(nh->nh_grp);
-               nh = nexthop_mpath_select(nh_grp, 0);
-               if (!nh)
-                       return NULL;
-       }
-
-       nhi = rcu_dereference_rtnl(nh->nh_info);
-       if (nhi->family == AF_INET6)
-               return &nhi->fib6_nh;
-
-       return NULL;
-}
-
 static inline struct net_device *fib6_info_nh_dev(struct fib6_info *f6i)
 {
        struct fib6_nh *fib6_nh;
index c8ec2f34722be5484ddaa25bc01d359bdd715d89..126f9e294389ae1100b2e760e962cfb7445580f5 100644 (file)
@@ -399,22 +399,4 @@ static inline void page_pool_nid_changed(struct page_pool *pool, int new_nid)
                page_pool_update_nid(pool, new_nid);
 }
 
-static inline void page_pool_ring_lock(struct page_pool *pool)
-       __acquires(&pool->ring.producer_lock)
-{
-       if (in_softirq())
-               spin_lock(&pool->ring.producer_lock);
-       else
-               spin_lock_bh(&pool->ring.producer_lock);
-}
-
-static inline void page_pool_ring_unlock(struct page_pool *pool)
-       __releases(&pool->ring.producer_lock)
-{
-       if (in_softirq())
-               spin_unlock(&pool->ring.producer_lock);
-       else
-               spin_unlock_bh(&pool->ring.producer_lock);
-}
-
 #endif /* _NET_PAGE_POOL_H */
index 8b7ed7167243db4eeb13793a8c465c9392623888..b418425d7230c8cee81df34fcc66d771ea5085e9 100644 (file)
@@ -336,6 +336,7 @@ struct sk_filter;
   *    @sk_cgrp_data: cgroup data for this cgroup
   *    @sk_memcg: this socket's memory cgroup association
   *    @sk_write_pending: a write to stream socket waits to start
+  *    @sk_wait_pending: number of threads blocked on this socket
   *    @sk_state_change: callback to indicate change in the state of the sock
   *    @sk_data_ready: callback to indicate there is data to be processed
   *    @sk_write_space: callback to indicate there is bf sending space available
@@ -428,6 +429,7 @@ struct sock {
        unsigned int            sk_napi_id;
 #endif
        int                     sk_rcvbuf;
+       int                     sk_wait_pending;
 
        struct sk_filter __rcu  *sk_filter;
        union {
@@ -1174,6 +1176,7 @@ static inline void sock_rps_reset_rxhash(struct sock *sk)
 
 #define sk_wait_event(__sk, __timeo, __condition, __wait)              \
        ({      int __rc;                                               \
+               __sk->sk_wait_pending++;                                \
                release_sock(__sk);                                     \
                __rc = __condition;                                     \
                if (!__rc) {                                            \
@@ -1183,6 +1186,7 @@ static inline void sock_rps_reset_rxhash(struct sock *sk)
                }                                                       \
                sched_annotate_sleep();                                 \
                lock_sock(__sk);                                        \
+               __sk->sk_wait_pending--;                                \
                __rc = __condition;                                     \
                __rc;                                                   \
        })
@@ -2718,7 +2722,7 @@ static inline void sock_recv_cmsgs(struct msghdr *msg, struct sock *sk,
                __sock_recv_cmsgs(msg, sk, skb);
        else if (unlikely(sock_flag(sk, SOCK_TIMESTAMP)))
                sock_write_timestamp(sk, skb->tstamp);
-       else if (unlikely(sk->sk_stamp == SK_DEFAULT_STAMP))
+       else if (unlikely(sock_read_timestamp(sk) == SK_DEFAULT_STAMP))
                sock_write_timestamp(sk, 0);
 }
 
index 04a31643cda388199133d908ccc4b48f051ef5dd..5066e4586cf09dbabfa053dce32fc4d31b98e324 100644 (file)
@@ -632,6 +632,7 @@ void tcp_reset(struct sock *sk, struct sk_buff *skb);
 void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, struct sk_buff *skb);
 void tcp_fin(struct sock *sk);
 void tcp_check_space(struct sock *sk);
+void tcp_sack_compress_send_ack(struct sock *sk);
 
 /* tcp_timer.c */
 void tcp_init_xmit_timers(struct sock *);
@@ -1470,6 +1471,8 @@ static inline void tcp_adjust_rcv_ssthresh(struct sock *sk)
 }
 
 void tcp_cleanup_rbuf(struct sock *sk, int copied);
+void __tcp_cleanup_rbuf(struct sock *sk, int copied);
+
 
 /* We provision sk_rcvbuf around 200% of sk_rcvlowat.
  * If 87.5 % (7/8) of the space has been consumed, we want to override
@@ -2326,6 +2329,14 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore);
 void tcp_bpf_clone(const struct sock *sk, struct sock *newsk);
 #endif /* CONFIG_BPF_SYSCALL */
 
+#ifdef CONFIG_INET
+void tcp_eat_skb(struct sock *sk, struct sk_buff *skb);
+#else
+static inline void tcp_eat_skb(struct sock *sk, struct sk_buff *skb)
+{
+}
+#endif
+
 int tcp_bpf_sendmsg_redir(struct sock *sk, bool ingress,
                          struct sk_msg *msg, u32 bytes, int flags);
 #endif /* CONFIG_NET_SOCK_MSG */
index 6056ce5a2aa5fb666b395f8f21f7b501f2ef2dc3..596595c4b1af28bbf2e1e5a470f5143115b19e1a 100644 (file)
@@ -126,6 +126,7 @@ struct tls_strparser {
        u32 mark : 8;
        u32 stopped : 1;
        u32 copy_mode : 1;
+       u32 mixed_decrypted : 1;
        u32 msg_ready : 1;
 
        struct strp_msg stm;
index dbc47af081357ca4ec5c57e6285dbb0aaa69930c..4f44f0bd538866f62babe7b32a6761d68381a460 100644 (file)
@@ -44,6 +44,9 @@ int hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink);
 
 int hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num);
 
+int hdac_bus_eml_sdw_map_stream_ch(struct hdac_bus *bus, int sublink, int y,
+                                  int channel_mask, int stream_id, int dir);
+
 void hda_bus_ml_put_all(struct hdac_bus *bus);
 void hda_bus_ml_reset_losidv(struct hdac_bus *bus);
 int hda_bus_ml_resume(struct hdac_bus *bus);
@@ -51,6 +54,7 @@ int hda_bus_ml_suspend(struct hdac_bus *bus);
 
 struct hdac_ext_link *hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus);
 struct hdac_ext_link *hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus);
+struct hdac_ext_link *hdac_bus_eml_sdw_get_hlink(struct hdac_bus *bus);
 
 struct mutex *hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid);
 
@@ -144,6 +148,13 @@ hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink) { return
 static inline int
 hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num) { return 0; }
 
+static inline int
+hdac_bus_eml_sdw_map_stream_ch(struct hdac_bus *bus, int sublink, int y,
+                              int channel_mask, int stream_id, int dir)
+{
+       return 0;
+}
+
 static inline void hda_bus_ml_put_all(struct hdac_bus *bus) { }
 static inline void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { }
 static inline int hda_bus_ml_resume(struct hdac_bus *bus) { return 0; }
@@ -155,6 +166,9 @@ hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus) { return NULL; }
 static inline struct hdac_ext_link *
 hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus) { return NULL; }
 
+static inline struct hdac_ext_link *
+hdac_bus_eml_sdw_get_hlink(struct hdac_bus *bus) { return NULL; }
+
 static inline struct mutex *
 hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid) { return NULL; }
 
index b38fd25c57295a8e10809fdaa74272b90892c81b..528279056b3ab96eb062111774163d431a09afe2 100644 (file)
@@ -170,6 +170,7 @@ struct snd_soc_acpi_link_adr {
 /* Descriptor for SST ASoC machine driver */
 struct snd_soc_acpi_mach {
        u8 id[ACPI_ID_LEN];
+       const char *uid;
        const struct snd_soc_acpi_codecs *comp_ids;
        const u32 link_mask;
        const struct snd_soc_acpi_link_adr *links;
index 4d6ac7699833d878b56deba30292af81dcc14669..ebd24753dd000b5aa0685a89ab61d6ccf6c0ce7c 100644 (file)
@@ -122,6 +122,10 @@ int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
 int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
                struct snd_soc_pcm_runtime *be, int stream);
 
+/* can this BE perform prepare */
+int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe,
+                                struct snd_soc_pcm_runtime *be, int stream);
+
 /* is the current PCM operation for this FE ? */
 int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream);
 
index 229118156a1f65042eef7015ee9634949de3d6ad..4c15420e8965d25bdadf2aeb81716dba10fd1d28 100644 (file)
@@ -562,12 +562,13 @@ struct iscsit_conn {
 #define LOGIN_FLAGS_READ_ACTIVE                2
 #define LOGIN_FLAGS_WRITE_ACTIVE       3
 #define LOGIN_FLAGS_CLOSED             4
+#define LOGIN_FLAGS_WORKER_RUNNING     5
        unsigned long           login_flags;
        struct delayed_work     login_work;
        struct iscsi_login      *login;
        struct timer_list       nopin_timer;
        struct timer_list       nopin_response_timer;
-       struct timer_list       transport_timer;
+       struct timer_list       login_timer;
        struct task_struct      *login_kworker;
        /* Spinlock used for add/deleting cmd's from conn_cmd_list */
        spinlock_t              cmd_lock;
@@ -576,6 +577,8 @@ struct iscsit_conn {
        spinlock_t              nopin_timer_lock;
        spinlock_t              response_queue_lock;
        spinlock_t              state_lock;
+       spinlock_t              login_timer_lock;
+       spinlock_t              login_worker_lock;
        /* libcrypto RX and TX contexts for crc32c */
        struct ahash_request    *conn_rx_hash;
        struct ahash_request    *conn_tx_hash;
@@ -792,7 +795,6 @@ struct iscsi_np {
        enum np_thread_state_table np_thread_state;
        bool                    enabled;
        atomic_t                np_reset_count;
-       enum iscsi_timer_flags_table np_login_timer_flags;
        u32                     np_exports;
        enum np_flags_table     np_flags;
        spinlock_t              np_thread_lock;
@@ -800,7 +802,6 @@ struct iscsi_np {
        struct socket           *np_socket;
        struct sockaddr_storage np_sockaddr;
        struct task_struct      *np_thread;
-       struct timer_list       np_login_timer;
        void                    *np_context;
        struct iscsit_transport *np_transport;
        struct list_head        np_list;
index 8ab12d731e3bde08ebcae105a3715e11a20b1283..fc248ef00e8683c2ba29a31d2315e770f0e945e0 100644 (file)
@@ -127,6 +127,12 @@ enum counter_count_mode {
        COUNTER_COUNT_MODE_RANGE_LIMIT,
        COUNTER_COUNT_MODE_NON_RECYCLE,
        COUNTER_COUNT_MODE_MODULO_N,
+       COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT,
+       COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT,
+       COUNTER_COUNT_MODE_RATE_GENERATOR,
+       COUNTER_COUNT_MODE_SQUARE_WAVE_MODE,
+       COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE,
+       COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE,
 };
 
 /* Count function values */
index 1de4d0b95325b836b135425037436191b5ffbdba..3d7ea58778c9689e8f626f26874bb40f9546b096 100644 (file)
@@ -44,6 +44,7 @@ enum {
        HANDSHAKE_A_ACCEPT_AUTH_MODE,
        HANDSHAKE_A_ACCEPT_PEER_IDENTITY,
        HANDSHAKE_A_ACCEPT_CERTIFICATE,
+       HANDSHAKE_A_ACCEPT_PEERNAME,
 
        __HANDSHAKE_A_ACCEPT_MAX,
        HANDSHAKE_A_ACCEPT_MAX = (__HANDSHAKE_A_ACCEPT_MAX - 1)
index 4b7f2df66b995ba82203b468d73b7bbc2a7dbc47..e682ab628dfa66bcbc10f9b4adc08f2a61db377b 100644 (file)
@@ -163,6 +163,7 @@ struct in_addr {
 #define IP_MULTICAST_ALL               49
 #define IP_UNICAST_IF                  50
 #define IP_LOCAL_PORT_RANGE            51
+#define IP_PROTOCOL                    52
 
 #define MCAST_EXCLUDE  0
 #define MCAST_INCLUDE  1
diff --git a/include/uapi/linux/tps6594_pfsm.h b/include/uapi/linux/tps6594_pfsm.h
new file mode 100644 (file)
index 0000000..c69569e
--- /dev/null
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Userspace ABI for TPS6594 PMIC Pre-configurable Finite State Machine
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#ifndef __TPS6594_PFSM_H
+#define __TPS6594_PFSM_H
+
+#include <linux/const.h>
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/**
+ * struct pmic_state_opt - PMIC state options
+ * @gpio_retention: if enabled, power rails associated with GPIO retention remain active
+ * @ddr_retention: if enabled, power rails associated with DDR retention remain active
+ * @mcu_only_startup_dest: if enabled, startup destination state is MCU_ONLY
+ */
+struct pmic_state_opt {
+       __u8 gpio_retention;
+       __u8 ddr_retention;
+       __u8 mcu_only_startup_dest;
+};
+
+/* Commands */
+#define PMIC_BASE                      'P'
+
+#define PMIC_GOTO_STANDBY              _IO(PMIC_BASE, 0)
+#define PMIC_GOTO_LP_STANDBY           _IO(PMIC_BASE, 1)
+#define PMIC_UPDATE_PGM                        _IO(PMIC_BASE, 2)
+#define PMIC_SET_ACTIVE_STATE          _IO(PMIC_BASE, 3)
+#define PMIC_SET_MCU_ONLY_STATE                _IOW(PMIC_BASE, 4, struct pmic_state_opt)
+#define PMIC_SET_RETENTION_STATE       _IOW(PMIC_BASE, 5, struct pmic_state_opt)
+
+#endif /*  __TPS6594_PFSM_H */
index f29899b179a62ce280f8e8ab0eafc239490e5267..4bf9c4f9add8ae204757089cbd73d75f7e1c1dae 100644 (file)
@@ -66,7 +66,8 @@ enum skl_ch_cfg {
        SKL_CH_CFG_DUAL_MONO = 9,
        SKL_CH_CFG_I2S_DUAL_STEREO_0 = 10,
        SKL_CH_CFG_I2S_DUAL_STEREO_1 = 11,
-       SKL_CH_CFG_4_CHANNEL = 12,
+       SKL_CH_CFG_7_1 = 12,
+       SKL_CH_CFG_4_CHANNEL = SKL_CH_CFG_7_1,
        SKL_CH_CFG_INVALID
 };
 
index bbc37877aaff551493bd17c493c8cc532d7068d5..e9ec7e4eb982330c95cac9d701475be15f9e2a1d 100644 (file)
 #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_INTERLEAVING_STYLE        1906
 #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_FMT_CFG   1907
 #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_SAMPLE_TYPE       1908
-#define SOF_TKN_CAVS_AUDIO_FORMAT_PIN_INDEX            1909
+#define SOF_TKN_CAVS_AUDIO_FORMAT_INPUT_PIN_INDEX      1909
 /* intentional token numbering discontinuity, reserved for future use */
 #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_RATE     1930
 #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_BIT_DEPTH        1931
 #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_INTERLEAVING_STYLE       1936
 #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_FMT_CFG  1937
 #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_SAMPLE_TYPE      1938
+#define SOF_TKN_CAVS_AUDIO_FORMAT_OUTPUT_PIN_INDEX     1939
 /* intentional token numbering discontinuity, reserved for future use */
 #define SOF_TKN_CAVS_AUDIO_FORMAT_IBS          1970
 #define SOF_TKN_CAVS_AUDIO_FORMAT_OBS          1971
index f7553293ba98bd0bd6f592216826f99f26ed076a..df1d04f7a54246b885a2b686aa9524ff9541a2c1 100644 (file)
@@ -1133,7 +1133,7 @@ static inline size_t ufshcd_sg_entry_size(const struct ufs_hba *hba)
        ({ (void)(hba); BUILD_BUG_ON(sg_entry_size != sizeof(struct ufshcd_sg_entry)); })
 #endif
 
-static inline size_t sizeof_utp_transfer_cmd_desc(const struct ufs_hba *hba)
+static inline size_t ufshcd_get_ucd_size(const struct ufs_hba *hba)
 {
        return sizeof(struct utp_transfer_cmd_desc) + SG_ALL * ufshcd_sg_entry_size(hba);
 }
index 9aa74d2c80bc4eefa4d975b829d3b6fb080d33f2..89bff2068a190950014755969355386a122a1227 100644 (file)
@@ -25,10 +25,6 @@ int io_epoll_ctl_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_epoll *epoll = io_kiocb_to_cmd(req, struct io_epoll);
 
-       pr_warn_once("%s: epoll_ctl support in io_uring is deprecated and will "
-                    "be removed in a future Linux kernel version.\n",
-                    current->comm);
-
        if (sqe->buf_index || sqe->splice_fd_in)
                return -EINVAL;
 
index 9db4bc1f521a3162d3480000cdc82e9a1aacfe62..5e329e3cd4706196fb6ce643ce35fbf9ad097360 100644 (file)
@@ -255,9 +255,13 @@ static int io_sq_thread(void *data)
                        sqt_spin = true;
 
                if (sqt_spin || !time_after(jiffies, timeout)) {
-                       cond_resched();
                        if (sqt_spin)
                                timeout = jiffies + sqd->sq_thread_idle;
+                       if (unlikely(need_resched())) {
+                               mutex_unlock(&sqd->lock);
+                               cond_resched();
+                               mutex_lock(&sqd->lock);
+                       }
                        continue;
                }
 
index 00c253b84bf534d923362ad0b7c00c02d24a1aef..9901efee4339d8592f34c820a5a26a6c85e34de1 100644 (file)
@@ -1215,7 +1215,7 @@ static long htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value
 
        ret = htab_lock_bucket(htab, b, hash, &flags);
        if (ret)
-               return ret;
+               goto err_lock_bucket;
 
        l_old = lookup_elem_raw(head, hash, key, key_size);
 
@@ -1236,6 +1236,7 @@ static long htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value
 err:
        htab_unlock_bucket(htab, b, hash, flags);
 
+err_lock_bucket:
        if (ret)
                htab_lru_push_free(htab, l_new);
        else if (l_old)
@@ -1338,7 +1339,7 @@ static long __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
 
        ret = htab_lock_bucket(htab, b, hash, &flags);
        if (ret)
-               return ret;
+               goto err_lock_bucket;
 
        l_old = lookup_elem_raw(head, hash, key, key_size);
 
@@ -1361,6 +1362,7 @@ static long __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
        ret = 0;
 err:
        htab_unlock_bucket(htab, b, hash, flags);
+err_lock_bucket:
        if (l_new)
                bpf_lru_push_free(&htab->lru, &l_new->lru_node);
        return ret;
index d9c9f45e3529c1b2f6a7965ab2f8ef4135c12dc9..8a26cd8814c1b65cd84895cf3ca759c52e46097c 100644 (file)
@@ -859,4 +859,4 @@ static int __init bpf_offload_init(void)
        return rhashtable_init(&offdevs, &offdevs_params);
 }
 
-late_initcall(bpf_offload_init);
+core_initcall(bpf_offload_init);
index fbcf5a4e2fcd49cc8a8242e447929a35fbc54ca4..5871aa78d01aefc370b021b286540668ad83e897 100644 (file)
@@ -17033,7 +17033,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
                                        insn_buf[cnt++] = BPF_ALU64_IMM(BPF_RSH,
                                                                        insn->dst_reg,
                                                                        shift);
-                               insn_buf[cnt++] = BPF_ALU64_IMM(BPF_AND, insn->dst_reg,
+                               insn_buf[cnt++] = BPF_ALU32_IMM(BPF_AND, insn->dst_reg,
                                                                (1ULL << size * 8) - 1);
                        }
                }
index 68baa8194d9f8b30694238d0db88d8ece579efb9..db016e4189319936b1042a336b6ad76046398eee 100644 (file)
@@ -10150,8 +10150,20 @@ void perf_tp_event(u16 event_type, u64 count, void *record, int entry_size,
        perf_trace_buf_update(record, event_type);
 
        hlist_for_each_entry_rcu(event, head, hlist_entry) {
-               if (perf_tp_event_match(event, &data, regs))
+               if (perf_tp_event_match(event, &data, regs)) {
                        perf_swevent_event(event, count, &data, regs);
+
+                       /*
+                        * Here use the same on-stack perf_sample_data,
+                        * some members in data are event-specific and
+                        * need to be re-computed for different sweveents.
+                        * Re-initialize data->sample_flags safely to avoid
+                        * the problem that next event skips preparing data
+                        * because data->sample_flags is set.
+                        */
+                       perf_sample_data_init(&data, 0, 0);
+                       perf_sample_save_raw_data(&data, &raw);
+               }
        }
 
        /*
index 34b90e2e7cf7f07620f8f80b8abb72737eca1d54..edb50b4c99728e568108ee943f8ff2f5fdba928b 100644 (file)
@@ -411,7 +411,10 @@ static void coredump_task_exit(struct task_struct *tsk)
        tsk->flags |= PF_POSTCOREDUMP;
        core_state = tsk->signal->core_state;
        spin_unlock_irq(&tsk->sighand->siglock);
-       if (core_state) {
+
+       /* The vhost_worker does not particpate in coredumps */
+       if (core_state &&
+           ((tsk->flags & (PF_IO_WORKER | PF_USER_WORKER)) != PF_USER_WORKER)) {
                struct core_thread self;
 
                self.task = current;
index ed4e01daccaa008ed0ef98c1a011aa5a4dddab36..81cba91f30bbe915f0746060c5285dd025245ba5 100644 (file)
@@ -2336,16 +2336,16 @@ __latent_entropy struct task_struct *copy_process(
        p->flags &= ~PF_KTHREAD;
        if (args->kthread)
                p->flags |= PF_KTHREAD;
-       if (args->user_worker)
-               p->flags |= PF_USER_WORKER;
-       if (args->io_thread) {
+       if (args->user_worker) {
                /*
-                * Mark us an IO worker, and block any signal that isn't
+                * Mark us a user worker, and block any signal that isn't
                 * fatal or STOP
                 */
-               p->flags |= PF_IO_WORKER;
+               p->flags |= PF_USER_WORKER;
                siginitsetinv(&p->blocked, sigmask(SIGKILL)|sigmask(SIGSTOP));
        }
+       if (args->io_thread)
+               p->flags |= PF_IO_WORKER;
 
        if (args->name)
                strscpy_pad(p->comm, args->name, sizeof(p->comm));
@@ -2517,9 +2517,6 @@ __latent_entropy struct task_struct *copy_process(
        if (retval)
                goto bad_fork_cleanup_io;
 
-       if (args->ignore_signals)
-               ignore_signals(p);
-
        stackleak_task_init(p);
 
        if (pid != &init_struct_pid) {
index 7a97bcb086bf39e92f9ac0cf6fb29c946631d2aa..b4c31a5c11473cc61ed6b12f57e90ca1c8bedc0e 100644 (file)
@@ -542,7 +542,7 @@ fail:
        return ret;
 }
 
-#ifdef CONFIG_PCI_MSI_ARCH_FALLBACKS
+#if defined(CONFIG_PCI_MSI_ARCH_FALLBACKS) || defined(CONFIG_PCI_XEN)
 /**
  * msi_device_populate_sysfs - Populate msi_irqs sysfs entries for a device
  * @dev:       The device (PCI, platform etc) which will get sysfs entries
@@ -574,7 +574,7 @@ void msi_device_destroy_sysfs(struct device *dev)
        msi_for_each_desc(desc, dev, MSI_DESC_ALL)
                msi_sysfs_remove_desc(dev, desc);
 }
-#endif /* CONFIG_PCI_MSI_ARCH_FALLBACK */
+#endif /* CONFIG_PCI_MSI_ARCH_FALLBACK || CONFIG_PCI_XEN */
 #else /* CONFIG_SYSFS */
 static inline int msi_sysfs_create_group(struct device *dev) { return 0; }
 static inline int msi_sysfs_populate_desc(struct device *dev, struct msi_desc *desc) { return 0; }
index dcd1d5bfc1e077a57da1253d0eaab90e61100bd2..4dfd2f3e09b2e39dcfed49bef95fea4d7d04ae94 100644 (file)
@@ -2263,6 +2263,9 @@ static inline bool usage_match(struct lock_list *entry, void *mask)
 
 static inline bool usage_skip(struct lock_list *entry, void *mask)
 {
+       if (entry->class->lock_type == LD_LOCK_NORMAL)
+               return false;
+
        /*
         * Skip local_lock() for irq inversion detection.
         *
@@ -2289,14 +2292,16 @@ static inline bool usage_skip(struct lock_list *entry, void *mask)
         * As a result, we will skip local_lock(), when we search for irq
         * inversion bugs.
         */
-       if (entry->class->lock_type == LD_LOCK_PERCPU) {
-               if (DEBUG_LOCKS_WARN_ON(entry->class->wait_type_inner < LD_WAIT_CONFIG))
-                       return false;
+       if (entry->class->lock_type == LD_LOCK_PERCPU &&
+           DEBUG_LOCKS_WARN_ON(entry->class->wait_type_inner < LD_WAIT_CONFIG))
+               return false;
 
-               return true;
-       }
+       /*
+        * Skip WAIT_OVERRIDE for irq inversion detection -- it's not actually
+        * a lock and only used to override the wait_type.
+        */
 
-       return false;
+       return true;
 }
 
 /*
@@ -4768,7 +4773,8 @@ static int check_wait_context(struct task_struct *curr, struct held_lock *next)
 
        for (; depth < curr->lockdep_depth; depth++) {
                struct held_lock *prev = curr->held_locks + depth;
-               u8 prev_inner = hlock_class(prev)->wait_type_inner;
+               struct lock_class *class = hlock_class(prev);
+               u8 prev_inner = class->wait_type_inner;
 
                if (prev_inner) {
                        /*
@@ -4778,6 +4784,14 @@ static int check_wait_context(struct task_struct *curr, struct held_lock *next)
                         * Also due to trylocks.
                         */
                        curr_inner = min(curr_inner, prev_inner);
+
+                       /*
+                        * Allow override for annotations -- this is typically
+                        * only valid/needed for code that only exists when
+                        * CONFIG_PREEMPT_RT=n.
+                        */
+                       if (unlikely(class->lock_type == LD_LOCK_WAIT_OVERRIDE))
+                               curr_inner = prev_inner;
                }
        }
 
index acb5a50309a1869db3d4ea009a0403c57eab2720..9eabd585ce7afa121f36b84eb90fc58f475505f4 100644 (file)
@@ -1240,7 +1240,7 @@ static struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem)
 /*
  * lock for reading
  */
-static inline int __down_read_common(struct rw_semaphore *sem, int state)
+static __always_inline int __down_read_common(struct rw_semaphore *sem, int state)
 {
        int ret = 0;
        long count;
@@ -1258,17 +1258,17 @@ out:
        return ret;
 }
 
-static inline void __down_read(struct rw_semaphore *sem)
+static __always_inline void __down_read(struct rw_semaphore *sem)
 {
        __down_read_common(sem, TASK_UNINTERRUPTIBLE);
 }
 
-static inline int __down_read_interruptible(struct rw_semaphore *sem)
+static __always_inline int __down_read_interruptible(struct rw_semaphore *sem)
 {
        return __down_read_common(sem, TASK_INTERRUPTIBLE);
 }
 
-static inline int __down_read_killable(struct rw_semaphore *sem)
+static __always_inline int __down_read_killable(struct rw_semaphore *sem)
 {
        return __down_read_common(sem, TASK_KILLABLE);
 }
index e97232b125ebc0cd4313101bf70ac69aa673453a..8a5d6d63b06cb94d3ef4cc6bc8d34143233456f0 100644 (file)
@@ -257,7 +257,7 @@ static ssize_t module_zstd_decompress(struct load_info *info,
        do {
                struct page *page = module_get_next_page(info);
 
-               if (!IS_ERR(page)) {
+               if (IS_ERR(page)) {
                        retval = PTR_ERR(page);
                        goto out;
                }
index 044aa2c9e3cb06c45a6c1822cf3ea7e564390677..4e2cf784cf8ceb66b2bac78b21272145a685f59a 100644 (file)
@@ -1521,14 +1521,14 @@ static void __layout_sections(struct module *mod, struct load_info *info, bool i
                MOD_RODATA,
                MOD_RO_AFTER_INIT,
                MOD_DATA,
-               MOD_INVALID,    /* This is needed to match the masks array */
+               MOD_DATA,
        };
        static const int init_m_to_mem_type[] = {
                MOD_INIT_TEXT,
                MOD_INIT_RODATA,
                MOD_INVALID,
                MOD_INIT_DATA,
-               MOD_INVALID,    /* This is needed to match the masks array */
+               MOD_INIT_DATA,
        };
 
        for (m = 0; m < ARRAY_SIZE(masks); ++m) {
index ad7b6ada29f2f5e809d20318945c61914adf8070..6ab2c94d6bc32fc3d61f1e812ef14983386b2472 100644 (file)
@@ -276,6 +276,7 @@ static ssize_t read_file_mod_stats(struct file *file, char __user *user_buf,
        struct mod_fail_load *mod_fail;
        unsigned int len, size, count_failed = 0;
        char *buf;
+       int ret;
        u32 live_mod_count, fkreads, fdecompress, fbecoming, floads;
        unsigned long total_size, text_size, ikread_bytes, ibecoming_bytes,
                idecompress_bytes, imod_bytes, total_virtual_lost;
@@ -390,8 +391,9 @@ static ssize_t read_file_mod_stats(struct file *file, char __user *user_buf,
 out_unlock:
        mutex_unlock(&module_mutex);
 out:
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
        kfree(buf);
-        return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       return ret;
 }
 #undef MAX_PREAMBLE
 #undef MAX_FAILED_MOD_PRINT
index 944c3ae39861cf68d344787a5487a81e92b1f9b0..a68d1276bab00640d57de1e67727464d86b5e7fc 100644 (file)
@@ -11492,7 +11492,7 @@ void call_trace_sched_update_nr_running(struct rq *rq, int count)
 
 #ifdef CONFIG_SCHED_MM_CID
 
-/**
+/*
  * @cid_lock: Guarantee forward-progress of cid allocation.
  *
  * Concurrency ID allocation within a bitmap is mostly lock-free. The cid_lock
@@ -11501,7 +11501,7 @@ void call_trace_sched_update_nr_running(struct rq *rq, int count)
  */
 DEFINE_RAW_SPINLOCK(cid_lock);
 
-/**
+/*
  * @use_cid_lock: Select cid allocation behavior: lock-free vs spinlock.
  *
  * When @use_cid_lock is 0, the cid allocation is lock-free. When contention is
index 8f6330f0e9ca35856088c0d6dafe445dfc72686f..2547fa73bde51eb4973c8a2c4e7af946108fe1bb 100644 (file)
@@ -1368,7 +1368,9 @@ int zap_other_threads(struct task_struct *p)
 
        while_each_thread(p, t) {
                task_clear_jobctl_pending(t, JOBCTL_PENDING_MASK);
-               count++;
+               /* Don't require de_thread to wait for the vhost_worker */
+               if ((t->flags & (PF_IO_WORKER | PF_USER_WORKER)) != PF_USER_WORKER)
+                       count++;
 
                /* Don't bother with already dead threads */
                if (t->exit_state)
@@ -2861,11 +2863,11 @@ relock:
                }
 
                /*
-                * PF_IO_WORKER threads will catch and exit on fatal signals
+                * PF_USER_WORKER threads will catch and exit on fatal signals
                 * themselves. They have cleanup that must be performed, so
                 * we cannot call do_exit() on their behalf.
                 */
-               if (current->flags & PF_IO_WORKER)
+               if (current->flags & PF_USER_WORKER)
                        goto out;
 
                /*
index 93bf2b4e47e5699868adb6bd4dd49ec46c7fa9d7..771d1e040303b583cdb622025084e7dbd61115de 100644 (file)
@@ -35,14 +35,15 @@ static __cacheline_aligned_in_smp DEFINE_RAW_SPINLOCK(tick_broadcast_lock);
 #ifdef CONFIG_TICK_ONESHOT
 static DEFINE_PER_CPU(struct clock_event_device *, tick_oneshot_wakeup_device);
 
-static void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
+static void tick_broadcast_setup_oneshot(struct clock_event_device *bc, bool from_periodic);
 static void tick_broadcast_clear_oneshot(int cpu);
 static void tick_resume_broadcast_oneshot(struct clock_event_device *bc);
 # ifdef CONFIG_HOTPLUG_CPU
 static void tick_broadcast_oneshot_offline(unsigned int cpu);
 # endif
 #else
-static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); }
+static inline void
+tick_broadcast_setup_oneshot(struct clock_event_device *bc, bool from_periodic) { BUG(); }
 static inline void tick_broadcast_clear_oneshot(int cpu) { }
 static inline void tick_resume_broadcast_oneshot(struct clock_event_device *bc) { }
 # ifdef CONFIG_HOTPLUG_CPU
@@ -264,7 +265,7 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
                if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
                        tick_broadcast_start_periodic(bc);
                else
-                       tick_broadcast_setup_oneshot(bc);
+                       tick_broadcast_setup_oneshot(bc, false);
                ret = 1;
        } else {
                /*
@@ -500,7 +501,7 @@ void tick_broadcast_control(enum tick_broadcast_mode mode)
                        if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
                                tick_broadcast_start_periodic(bc);
                        else
-                               tick_broadcast_setup_oneshot(bc);
+                               tick_broadcast_setup_oneshot(bc, false);
                }
        }
 out:
@@ -1020,48 +1021,101 @@ static inline ktime_t tick_get_next_period(void)
 /**
  * tick_broadcast_setup_oneshot - setup the broadcast device
  */
-static void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
+static void tick_broadcast_setup_oneshot(struct clock_event_device *bc,
+                                        bool from_periodic)
 {
        int cpu = smp_processor_id();
+       ktime_t nexttick = 0;
 
        if (!bc)
                return;
 
-       /* Set it up only once ! */
-       if (bc->event_handler != tick_handle_oneshot_broadcast) {
-               int was_periodic = clockevent_state_periodic(bc);
-
-               bc->event_handler = tick_handle_oneshot_broadcast;
-
+       /*
+        * When the broadcast device was switched to oneshot by the first
+        * CPU handling the NOHZ change, the other CPUs will reach this
+        * code via hrtimer_run_queues() -> tick_check_oneshot_change()
+        * too. Set up the broadcast device only once!
+        */
+       if (bc->event_handler == tick_handle_oneshot_broadcast) {
                /*
-                * We must be careful here. There might be other CPUs
-                * waiting for periodic broadcast. We need to set the
-                * oneshot_mask bits for those and program the
-                * broadcast device to fire.
+                * The CPU which switched from periodic to oneshot mode
+                * set the broadcast oneshot bit for all other CPUs which
+                * are in the general (periodic) broadcast mask to ensure
+                * that CPUs which wait for the periodic broadcast are
+                * woken up.
+                *
+                * Clear the bit for the local CPU as the set bit would
+                * prevent the first tick_broadcast_enter() after this CPU
+                * switched to oneshot state to program the broadcast
+                * device.
+                *
+                * This code can also be reached via tick_broadcast_control(),
+                * but this cannot avoid the tick_broadcast_clear_oneshot()
+                * as that would break the periodic to oneshot transition of
+                * secondary CPUs. But that's harmless as the below only
+                * clears already cleared bits.
                 */
+               tick_broadcast_clear_oneshot(cpu);
+               return;
+       }
+
+
+       bc->event_handler = tick_handle_oneshot_broadcast;
+       bc->next_event = KTIME_MAX;
+
+       /*
+        * When the tick mode is switched from periodic to oneshot it must
+        * be ensured that CPUs which are waiting for periodic broadcast
+        * get their wake-up at the next tick.  This is achieved by ORing
+        * tick_broadcast_mask into tick_broadcast_oneshot_mask.
+        *
+        * For other callers, e.g. broadcast device replacement,
+        * tick_broadcast_oneshot_mask must not be touched as this would
+        * set bits for CPUs which are already NOHZ, but not idle. Their
+        * next tick_broadcast_enter() would observe the bit set and fail
+        * to update the expiry time and the broadcast event device.
+        */
+       if (from_periodic) {
                cpumask_copy(tmpmask, tick_broadcast_mask);
+               /* Remove the local CPU as it is obviously not idle */
                cpumask_clear_cpu(cpu, tmpmask);
-               cpumask_or(tick_broadcast_oneshot_mask,
-                          tick_broadcast_oneshot_mask, tmpmask);
+               cpumask_or(tick_broadcast_oneshot_mask, tick_broadcast_oneshot_mask, tmpmask);
 
-               if (was_periodic && !cpumask_empty(tmpmask)) {
-                       ktime_t nextevt = tick_get_next_period();
+               /*
+                * Ensure that the oneshot broadcast handler will wake the
+                * CPUs which are still waiting for periodic broadcast.
+                */
+               nexttick = tick_get_next_period();
+               tick_broadcast_init_next_event(tmpmask, nexttick);
 
-                       clockevents_switch_state(bc, CLOCK_EVT_STATE_ONESHOT);
-                       tick_broadcast_init_next_event(tmpmask, nextevt);
-                       tick_broadcast_set_event(bc, cpu, nextevt);
-               } else
-                       bc->next_event = KTIME_MAX;
-       } else {
                /*
-                * The first cpu which switches to oneshot mode sets
-                * the bit for all other cpus which are in the general
-                * (periodic) broadcast mask. So the bit is set and
-                * would prevent the first broadcast enter after this
-                * to program the bc device.
+                * If the underlying broadcast clock event device is
+                * already in oneshot state, then there is nothing to do.
+                * The device was already armed for the next tick
+                * in tick_handle_broadcast_periodic()
                 */
-               tick_broadcast_clear_oneshot(cpu);
+               if (clockevent_state_oneshot(bc))
+                       return;
        }
+
+       /*
+        * When switching from periodic to oneshot mode arm the broadcast
+        * device for the next tick.
+        *
+        * If the broadcast device has been replaced in oneshot mode and
+        * the oneshot broadcast mask is not empty, then arm it to expire
+        * immediately in order to reevaluate the next expiring timer.
+        * @nexttick is 0 and therefore in the past which will cause the
+        * clockevent code to force an event.
+        *
+        * For both cases the programming can be avoided when the oneshot
+        * broadcast mask is empty.
+        *
+        * tick_broadcast_set_event() implicitly switches the broadcast
+        * device to oneshot state.
+        */
+       if (!cpumask_empty(tick_broadcast_oneshot_mask))
+               tick_broadcast_set_event(bc, cpu, nexttick);
 }
 
 /*
@@ -1070,14 +1124,16 @@ static void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
 void tick_broadcast_switch_to_oneshot(void)
 {
        struct clock_event_device *bc;
+       enum tick_device_mode oldmode;
        unsigned long flags;
 
        raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 
+       oldmode = tick_broadcast_device.mode;
        tick_broadcast_device.mode = TICKDEV_MODE_ONESHOT;
        bc = tick_broadcast_device.evtdev;
        if (bc)
-               tick_broadcast_setup_oneshot(bc);
+               tick_broadcast_setup_oneshot(bc, oldmode == TICKDEV_MODE_PERIODIC);
 
        raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
index 9abb3905bc8e1701b81dca9545bc416b31cc7dfd..18d36842faf575d2057439aa22f5b8b4064858af 100644 (file)
 struct fprobe_rethook_node {
        struct rethook_node node;
        unsigned long entry_ip;
+       unsigned long entry_parent_ip;
        char data[];
 };
 
-static void fprobe_handler(unsigned long ip, unsigned long parent_ip,
-                          struct ftrace_ops *ops, struct ftrace_regs *fregs)
+static inline void __fprobe_handler(unsigned long ip, unsigned long parent_ip,
+                       struct ftrace_ops *ops, struct ftrace_regs *fregs)
 {
        struct fprobe_rethook_node *fpr;
        struct rethook_node *rh = NULL;
        struct fprobe *fp;
        void *entry_data = NULL;
-       int bit, ret;
+       int ret = 0;
 
        fp = container_of(ops, struct fprobe, ops);
-       if (fprobe_disabled(fp))
-               return;
-
-       bit = ftrace_test_recursion_trylock(ip, parent_ip);
-       if (bit < 0) {
-               fp->nmissed++;
-               return;
-       }
 
        if (fp->exit_handler) {
                rh = rethook_try_get(fp->rethook);
                if (!rh) {
                        fp->nmissed++;
-                       goto out;
+                       return;
                }
                fpr = container_of(rh, struct fprobe_rethook_node, node);
                fpr->entry_ip = ip;
+               fpr->entry_parent_ip = parent_ip;
                if (fp->entry_data_size)
                        entry_data = fpr->data;
        }
@@ -61,23 +55,60 @@ static void fprobe_handler(unsigned long ip, unsigned long parent_ip,
                else
                        rethook_hook(rh, ftrace_get_regs(fregs), true);
        }
-out:
+}
+
+static void fprobe_handler(unsigned long ip, unsigned long parent_ip,
+               struct ftrace_ops *ops, struct ftrace_regs *fregs)
+{
+       struct fprobe *fp;
+       int bit;
+
+       fp = container_of(ops, struct fprobe, ops);
+       if (fprobe_disabled(fp))
+               return;
+
+       /* recursion detection has to go before any traceable function and
+        * all functions before this point should be marked as notrace
+        */
+       bit = ftrace_test_recursion_trylock(ip, parent_ip);
+       if (bit < 0) {
+               fp->nmissed++;
+               return;
+       }
+       __fprobe_handler(ip, parent_ip, ops, fregs);
        ftrace_test_recursion_unlock(bit);
+
 }
 NOKPROBE_SYMBOL(fprobe_handler);
 
 static void fprobe_kprobe_handler(unsigned long ip, unsigned long parent_ip,
                                  struct ftrace_ops *ops, struct ftrace_regs *fregs)
 {
-       struct fprobe *fp = container_of(ops, struct fprobe, ops);
+       struct fprobe *fp;
+       int bit;
+
+       fp = container_of(ops, struct fprobe, ops);
+       if (fprobe_disabled(fp))
+               return;
+
+       /* recursion detection has to go before any traceable function and
+        * all functions called before this point should be marked as notrace
+        */
+       bit = ftrace_test_recursion_trylock(ip, parent_ip);
+       if (bit < 0) {
+               fp->nmissed++;
+               return;
+       }
 
        if (unlikely(kprobe_running())) {
                fp->nmissed++;
                return;
        }
+
        kprobe_busy_begin();
-       fprobe_handler(ip, parent_ip, ops, fregs);
+       __fprobe_handler(ip, parent_ip, ops, fregs);
        kprobe_busy_end();
+       ftrace_test_recursion_unlock(bit);
 }
 
 static void fprobe_exit_handler(struct rethook_node *rh, void *data,
@@ -85,14 +116,26 @@ static void fprobe_exit_handler(struct rethook_node *rh, void *data,
 {
        struct fprobe *fp = (struct fprobe *)data;
        struct fprobe_rethook_node *fpr;
+       int bit;
 
        if (!fp || fprobe_disabled(fp))
                return;
 
        fpr = container_of(rh, struct fprobe_rethook_node, node);
 
+       /*
+        * we need to assure no calls to traceable functions in-between the
+        * end of fprobe_handler and the beginning of fprobe_exit_handler.
+        */
+       bit = ftrace_test_recursion_trylock(fpr->entry_ip, fpr->entry_parent_ip);
+       if (bit < 0) {
+               fp->nmissed++;
+               return;
+       }
+
        fp->exit_handler(fp, fpr->entry_ip, regs,
                         fp->entry_data_size ? (void *)fpr->data : NULL);
+       ftrace_test_recursion_unlock(bit);
 }
 NOKPROBE_SYMBOL(fprobe_exit_handler);
 
index 32c3dfdb4d6a74b9bba4dffb57914f9d71e5a591..60f6cb2b486bf466227ca2ac68070349e07556e7 100644 (file)
@@ -288,7 +288,7 @@ unsigned long rethook_trampoline_handler(struct pt_regs *regs,
         * These loops must be protected from rethook_free_rcu() because those
         * are accessing 'rhn->rethook'.
         */
-       preempt_disable();
+       preempt_disable_notrace();
 
        /*
         * Run the handler on the shadow stack. Do not unlink the list here because
@@ -321,7 +321,7 @@ unsigned long rethook_trampoline_handler(struct pt_regs *regs,
                first = first->next;
                rethook_recycle(rhn);
        }
-       preempt_enable();
+       preempt_enable_notrace();
 
        return correct_ret_addr;
 }
index ebc59781456a2188afe16ad0d92c4af6b466b913..64a4dde073ef6599ed8f340067ae0bb351f178dc 100644 (file)
@@ -60,6 +60,7 @@
  */
 bool ring_buffer_expanded;
 
+#ifdef CONFIG_FTRACE_STARTUP_TEST
 /*
  * We need to change this state when a selftest is running.
  * A selftest will lurk into the ring-buffer to count the
@@ -75,7 +76,6 @@ static bool __read_mostly tracing_selftest_running;
  */
 bool __read_mostly tracing_selftest_disabled;
 
-#ifdef CONFIG_FTRACE_STARTUP_TEST
 void __init disable_tracing_selftest(const char *reason)
 {
        if (!tracing_selftest_disabled) {
@@ -83,6 +83,9 @@ void __init disable_tracing_selftest(const char *reason)
                pr_info("Ftrace startup test is disabled due to %s\n", reason);
        }
 }
+#else
+#define tracing_selftest_running       0
+#define tracing_selftest_disabled      0
 #endif
 
 /* Pipe tracepoints to printk */
@@ -1051,7 +1054,10 @@ int __trace_array_puts(struct trace_array *tr, unsigned long ip,
        if (!(tr->trace_flags & TRACE_ITER_PRINTK))
                return 0;
 
-       if (unlikely(tracing_selftest_running || tracing_disabled))
+       if (unlikely(tracing_selftest_running && tr == &global_trace))
+               return 0;
+
+       if (unlikely(tracing_disabled))
                return 0;
 
        alloc = sizeof(*entry) + size + 2; /* possible \n added */
@@ -2041,6 +2047,24 @@ static int run_tracer_selftest(struct tracer *type)
        return 0;
 }
 
+static int do_run_tracer_selftest(struct tracer *type)
+{
+       int ret;
+
+       /*
+        * Tests can take a long time, especially if they are run one after the
+        * other, as does happen during bootup when all the tracers are
+        * registered. This could cause the soft lockup watchdog to trigger.
+        */
+       cond_resched();
+
+       tracing_selftest_running = true;
+       ret = run_tracer_selftest(type);
+       tracing_selftest_running = false;
+
+       return ret;
+}
+
 static __init int init_trace_selftests(void)
 {
        struct trace_selftests *p, *n;
@@ -2092,6 +2116,10 @@ static inline int run_tracer_selftest(struct tracer *type)
 {
        return 0;
 }
+static inline int do_run_tracer_selftest(struct tracer *type)
+{
+       return 0;
+}
 #endif /* CONFIG_FTRACE_STARTUP_TEST */
 
 static void add_tracer_options(struct trace_array *tr, struct tracer *t);
@@ -2127,8 +2155,6 @@ int __init register_tracer(struct tracer *type)
 
        mutex_lock(&trace_types_lock);
 
-       tracing_selftest_running = true;
-
        for (t = trace_types; t; t = t->next) {
                if (strcmp(type->name, t->name) == 0) {
                        /* already found */
@@ -2157,7 +2183,7 @@ int __init register_tracer(struct tracer *type)
        /* store the tracer for __set_tracer_option */
        type->flags->trace = type;
 
-       ret = run_tracer_selftest(type);
+       ret = do_run_tracer_selftest(type);
        if (ret < 0)
                goto out;
 
@@ -2166,7 +2192,6 @@ int __init register_tracer(struct tracer *type)
        add_tracer_options(&global_trace, type);
 
  out:
-       tracing_selftest_running = false;
        mutex_unlock(&trace_types_lock);
 
        if (ret || !default_bootup_tracer)
@@ -3490,7 +3515,7 @@ __trace_array_vprintk(struct trace_buffer *buffer,
        unsigned int trace_ctx;
        char *tbuffer;
 
-       if (tracing_disabled || tracing_selftest_running)
+       if (tracing_disabled)
                return 0;
 
        /* Don't pollute graph traces with trace_vprintk internals */
@@ -3538,6 +3563,9 @@ __printf(3, 0)
 int trace_array_vprintk(struct trace_array *tr,
                        unsigned long ip, const char *fmt, va_list args)
 {
+       if (tracing_selftest_running && tr == &global_trace)
+               return 0;
+
        return __trace_array_vprintk(tr->array_buffer.buffer, ip, fmt, args);
 }
 
@@ -5752,7 +5780,7 @@ static const char readme_msg[] =
        "\t    table using the key(s) and value(s) named, and the value of a\n"
        "\t    sum called 'hitcount' is incremented.  Keys and values\n"
        "\t    correspond to fields in the event's format description.  Keys\n"
-       "\t    can be any field, or the special string 'stacktrace'.\n"
+       "\t    can be any field, or the special string 'common_stacktrace'.\n"
        "\t    Compound keys consisting of up to two fields can be specified\n"
        "\t    by the 'keys' keyword.  Values must correspond to numeric\n"
        "\t    fields.  Sort keys consisting of up to two fields can be\n"
index 654ffa40457aac27ce253b02d34d22ce8e6c69b8..57e539d4798908f94a78f9d697a4ffbebdba44e2 100644 (file)
@@ -194,6 +194,8 @@ static int trace_define_generic_fields(void)
        __generic_field(int, common_cpu, FILTER_CPU);
        __generic_field(char *, COMM, FILTER_COMM);
        __generic_field(char *, comm, FILTER_COMM);
+       __generic_field(char *, stacktrace, FILTER_STACKTRACE);
+       __generic_field(char *, STACKTRACE, FILTER_STACKTRACE);
 
        return ret;
 }
index 486cca3c2b75450f23f8b680045421cf234d232f..b97d3ad832f1a4354fc59918b2ce6a12b18ce484 100644 (file)
@@ -1364,7 +1364,7 @@ static const char *hist_field_name(struct hist_field *field,
                if (field->field)
                        field_name = field->field->name;
                else
-                       field_name = "stacktrace";
+                       field_name = "common_stacktrace";
        } else if (field->flags & HIST_FIELD_FL_HITCOUNT)
                field_name = "hitcount";
 
@@ -2367,7 +2367,7 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,
                hist_data->enable_timestamps = true;
                if (*flags & HIST_FIELD_FL_TIMESTAMP_USECS)
                        hist_data->attrs->ts_in_usecs = true;
-       } else if (strcmp(field_name, "stacktrace") == 0) {
+       } else if (strcmp(field_name, "common_stacktrace") == 0) {
                *flags |= HIST_FIELD_FL_STACKTRACE;
        } else if (strcmp(field_name, "common_cpu") == 0)
                *flags |= HIST_FIELD_FL_CPU;
@@ -2378,11 +2378,15 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,
                if (!field || !field->size) {
                        /*
                         * For backward compatibility, if field_name
-                        * was "cpu", then we treat this the same as
-                        * common_cpu. This also works for "CPU".
+                        * was "cpu" or "stacktrace", then we treat this
+                        * the same as common_cpu and common_stacktrace
+                        * respectively. This also works for "CPU", and
+                        * "STACKTRACE".
                         */
                        if (field && field->filter_type == FILTER_CPU) {
                                *flags |= HIST_FIELD_FL_CPU;
+                       } else if (field && field->filter_type == FILTER_STACKTRACE) {
+                               *flags |= HIST_FIELD_FL_STACKTRACE;
                        } else {
                                hist_err(tr, HIST_ERR_FIELD_NOT_FOUND,
                                         errpos(field_name));
@@ -4238,13 +4242,19 @@ static int __create_val_field(struct hist_trigger_data *hist_data,
                goto out;
        }
 
-       /* Some types cannot be a value */
-       if (hist_field->flags & (HIST_FIELD_FL_GRAPH | HIST_FIELD_FL_PERCENT |
-                                HIST_FIELD_FL_BUCKET | HIST_FIELD_FL_LOG2 |
-                                HIST_FIELD_FL_SYM | HIST_FIELD_FL_SYM_OFFSET |
-                                HIST_FIELD_FL_SYSCALL | HIST_FIELD_FL_STACKTRACE)) {
-               hist_err(file->tr, HIST_ERR_BAD_FIELD_MODIFIER, errpos(field_str));
-               ret = -EINVAL;
+       /* values and variables should not have some modifiers */
+       if (hist_field->flags & HIST_FIELD_FL_VAR) {
+               /* Variable */
+               if (hist_field->flags & (HIST_FIELD_FL_GRAPH | HIST_FIELD_FL_PERCENT |
+                                        HIST_FIELD_FL_BUCKET | HIST_FIELD_FL_LOG2))
+                       goto err;
+       } else {
+               /* Value */
+               if (hist_field->flags & (HIST_FIELD_FL_GRAPH | HIST_FIELD_FL_PERCENT |
+                                        HIST_FIELD_FL_BUCKET | HIST_FIELD_FL_LOG2 |
+                                        HIST_FIELD_FL_SYM | HIST_FIELD_FL_SYM_OFFSET |
+                                        HIST_FIELD_FL_SYSCALL | HIST_FIELD_FL_STACKTRACE))
+                       goto err;
        }
 
        hist_data->fields[val_idx] = hist_field;
@@ -4256,6 +4266,9 @@ static int __create_val_field(struct hist_trigger_data *hist_data,
                ret = -EINVAL;
  out:
        return ret;
+ err:
+       hist_err(file->tr, HIST_ERR_BAD_FIELD_MODIFIER, errpos(field_str));
+       return -EINVAL;
 }
 
 static int create_val_field(struct hist_trigger_data *hist_data,
@@ -5385,7 +5398,7 @@ static void hist_trigger_print_key(struct seq_file *m,
                        if (key_field->field)
                                seq_printf(m, "%s.stacktrace", key_field->field->name);
                        else
-                               seq_puts(m, "stacktrace:\n");
+                               seq_puts(m, "common_stacktrace:\n");
                        hist_trigger_stacktrace_print(m,
                                                      key + key_field->offset,
                                                      HIST_STACKTRACE_DEPTH);
@@ -5968,7 +5981,7 @@ static int event_hist_trigger_print(struct seq_file *m,
                        if (field->field)
                                seq_printf(m, "%s.stacktrace", field->field->name);
                        else
-                               seq_puts(m, "stacktrace");
+                               seq_puts(m, "common_stacktrace");
                } else
                        hist_field_print(m, field);
        }
index b1ecd7677642728f3945eb125e987aaef091cd6c..dbb14705d0d36e5aa5f5c56a3486a41b4fc24efa 100644 (file)
@@ -96,12 +96,12 @@ struct user_event {
  * these to track enablement sites that are tied to an event.
  */
 struct user_event_enabler {
-       struct list_head        link;
+       struct list_head        mm_enablers_link;
        struct user_event       *event;
        unsigned long           addr;
 
        /* Track enable bit, flags, etc. Aligned for bitops. */
-       unsigned int            values;
+       unsigned long           values;
 };
 
 /* Bits 0-5 are for the bit to update upon enable/disable (0-63 allowed) */
@@ -116,7 +116,9 @@ struct user_event_enabler {
 /* Only duplicate the bit value */
 #define ENABLE_VAL_DUP_MASK ENABLE_VAL_BIT_MASK
 
-#define ENABLE_BITOPS(e) ((unsigned long *)&(e)->values)
+#define ENABLE_BITOPS(e) (&(e)->values)
+
+#define ENABLE_BIT(e) ((int)((e)->values & ENABLE_VAL_BIT_MASK))
 
 /* Used for asynchronous faulting in of pages */
 struct user_event_enabler_fault {
@@ -153,7 +155,7 @@ struct user_event_file_info {
 #define VALIDATOR_REL (1 << 1)
 
 struct user_event_validator {
-       struct list_head        link;
+       struct list_head        user_event_link;
        int                     offset;
        int                     flags;
 };
@@ -259,7 +261,7 @@ error:
 
 static void user_event_enabler_destroy(struct user_event_enabler *enabler)
 {
-       list_del_rcu(&enabler->link);
+       list_del_rcu(&enabler->mm_enablers_link);
 
        /* No longer tracking the event via the enabler */
        refcount_dec(&enabler->event->refcnt);
@@ -423,9 +425,9 @@ static int user_event_enabler_write(struct user_event_mm *mm,
 
        /* Update bit atomically, user tracers must be atomic as well */
        if (enabler->event && enabler->event->status)
-               set_bit(enabler->values & ENABLE_VAL_BIT_MASK, ptr);
+               set_bit(ENABLE_BIT(enabler), ptr);
        else
-               clear_bit(enabler->values & ENABLE_VAL_BIT_MASK, ptr);
+               clear_bit(ENABLE_BIT(enabler), ptr);
 
        kunmap_local(kaddr);
        unpin_user_pages_dirty_lock(&page, 1, true);
@@ -437,11 +439,9 @@ static bool user_event_enabler_exists(struct user_event_mm *mm,
                                      unsigned long uaddr, unsigned char bit)
 {
        struct user_event_enabler *enabler;
-       struct user_event_enabler *next;
 
-       list_for_each_entry_safe(enabler, next, &mm->enablers, link) {
-               if (enabler->addr == uaddr &&
-                   (enabler->values & ENABLE_VAL_BIT_MASK) == bit)
+       list_for_each_entry(enabler, &mm->enablers, mm_enablers_link) {
+               if (enabler->addr == uaddr && ENABLE_BIT(enabler) == bit)
                        return true;
        }
 
@@ -451,23 +451,36 @@ static bool user_event_enabler_exists(struct user_event_mm *mm,
 static void user_event_enabler_update(struct user_event *user)
 {
        struct user_event_enabler *enabler;
-       struct user_event_mm *mm = user_event_mm_get_all(user);
        struct user_event_mm *next;
+       struct user_event_mm *mm;
        int attempt;
 
+       lockdep_assert_held(&event_mutex);
+
+       /*
+        * We need to build a one-shot list of all the mms that have an
+        * enabler for the user_event passed in. This list is only valid
+        * while holding the event_mutex. The only reason for this is due
+        * to the global mm list being RCU protected and we use methods
+        * which can wait (mmap_read_lock and pin_user_pages_remote).
+        *
+        * NOTE: user_event_mm_get_all() increments the ref count of each
+        * mm that is added to the list to prevent removal timing windows.
+        * We must always put each mm after they are used, which may wait.
+        */
+       mm = user_event_mm_get_all(user);
+
        while (mm) {
                next = mm->next;
                mmap_read_lock(mm->mm);
-               rcu_read_lock();
 
-               list_for_each_entry_rcu(enabler, &mm->enablers, link) {
+               list_for_each_entry(enabler, &mm->enablers, mm_enablers_link) {
                        if (enabler->event == user) {
                                attempt = 0;
                                user_event_enabler_write(mm, enabler, true, &attempt);
                        }
                }
 
-               rcu_read_unlock();
                mmap_read_unlock(mm->mm);
                user_event_mm_put(mm);
                mm = next;
@@ -495,7 +508,9 @@ static bool user_event_enabler_dup(struct user_event_enabler *orig,
        enabler->values = orig->values & ENABLE_VAL_DUP_MASK;
 
        refcount_inc(&enabler->event->refcnt);
-       list_add_rcu(&enabler->link, &mm->enablers);
+
+       /* Enablers not exposed yet, RCU not required */
+       list_add(&enabler->mm_enablers_link, &mm->enablers);
 
        return true;
 }
@@ -513,6 +528,14 @@ static struct user_event_mm *user_event_mm_get_all(struct user_event *user)
        struct user_event_enabler *enabler;
        struct user_event_mm *mm;
 
+       /*
+        * We use the mm->next field to build a one-shot list from the global
+        * RCU protected list. To build this list the event_mutex must be held.
+        * This lets us build a list without requiring allocs that could fail
+        * when user based events are most wanted for diagnostics.
+        */
+       lockdep_assert_held(&event_mutex);
+
        /*
         * We do not want to block fork/exec while enablements are being
         * updated, so we use RCU to walk the current tasks that have used
@@ -525,23 +548,24 @@ static struct user_event_mm *user_event_mm_get_all(struct user_event *user)
         */
        rcu_read_lock();
 
-       list_for_each_entry_rcu(mm, &user_event_mms, link)
-               list_for_each_entry_rcu(enabler, &mm->enablers, link)
+       list_for_each_entry_rcu(mm, &user_event_mms, mms_link) {
+               list_for_each_entry_rcu(enabler, &mm->enablers, mm_enablers_link) {
                        if (enabler->event == user) {
                                mm->next = found;
                                found = user_event_mm_get(mm);
                                break;
                        }
+               }
+       }
 
        rcu_read_unlock();
 
        return found;
 }
 
-static struct user_event_mm *user_event_mm_create(struct task_struct *t)
+static struct user_event_mm *user_event_mm_alloc(struct task_struct *t)
 {
        struct user_event_mm *user_mm;
-       unsigned long flags;
 
        user_mm = kzalloc(sizeof(*user_mm), GFP_KERNEL_ACCOUNT);
 
@@ -553,12 +577,6 @@ static struct user_event_mm *user_event_mm_create(struct task_struct *t)
        refcount_set(&user_mm->refcnt, 1);
        refcount_set(&user_mm->tasks, 1);
 
-       spin_lock_irqsave(&user_event_mms_lock, flags);
-       list_add_rcu(&user_mm->link, &user_event_mms);
-       spin_unlock_irqrestore(&user_event_mms_lock, flags);
-
-       t->user_event_mm = user_mm;
-
        /*
         * The lifetime of the memory descriptor can slightly outlast
         * the task lifetime if a ref to the user_event_mm is taken
@@ -572,6 +590,17 @@ static struct user_event_mm *user_event_mm_create(struct task_struct *t)
        return user_mm;
 }
 
+static void user_event_mm_attach(struct user_event_mm *user_mm, struct task_struct *t)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&user_event_mms_lock, flags);
+       list_add_rcu(&user_mm->mms_link, &user_event_mms);
+       spin_unlock_irqrestore(&user_event_mms_lock, flags);
+
+       t->user_event_mm = user_mm;
+}
+
 static struct user_event_mm *current_user_event_mm(void)
 {
        struct user_event_mm *user_mm = current->user_event_mm;
@@ -579,10 +608,12 @@ static struct user_event_mm *current_user_event_mm(void)
        if (user_mm)
                goto inc;
 
-       user_mm = user_event_mm_create(current);
+       user_mm = user_event_mm_alloc(current);
 
        if (!user_mm)
                goto error;
+
+       user_event_mm_attach(user_mm, current);
 inc:
        refcount_inc(&user_mm->refcnt);
 error:
@@ -593,7 +624,7 @@ static void user_event_mm_destroy(struct user_event_mm *mm)
 {
        struct user_event_enabler *enabler, *next;
 
-       list_for_each_entry_safe(enabler, next, &mm->enablers, link)
+       list_for_each_entry_safe(enabler, next, &mm->enablers, mm_enablers_link)
                user_event_enabler_destroy(enabler);
 
        mmdrop(mm->mm);
@@ -630,7 +661,7 @@ void user_event_mm_remove(struct task_struct *t)
 
        /* Remove the mm from the list, so it can no longer be enabled */
        spin_lock_irqsave(&user_event_mms_lock, flags);
-       list_del_rcu(&mm->link);
+       list_del_rcu(&mm->mms_link);
        spin_unlock_irqrestore(&user_event_mms_lock, flags);
 
        /*
@@ -670,7 +701,7 @@ void user_event_mm_remove(struct task_struct *t)
 
 void user_event_mm_dup(struct task_struct *t, struct user_event_mm *old_mm)
 {
-       struct user_event_mm *mm = user_event_mm_create(t);
+       struct user_event_mm *mm = user_event_mm_alloc(t);
        struct user_event_enabler *enabler;
 
        if (!mm)
@@ -678,16 +709,18 @@ void user_event_mm_dup(struct task_struct *t, struct user_event_mm *old_mm)
 
        rcu_read_lock();
 
-       list_for_each_entry_rcu(enabler, &old_mm->enablers, link)
+       list_for_each_entry_rcu(enabler, &old_mm->enablers, mm_enablers_link) {
                if (!user_event_enabler_dup(enabler, mm))
                        goto error;
+       }
 
        rcu_read_unlock();
 
+       user_event_mm_attach(mm, t);
        return;
 error:
        rcu_read_unlock();
-       user_event_mm_remove(t);
+       user_event_mm_destroy(mm);
 }
 
 static bool current_user_event_enabler_exists(unsigned long uaddr,
@@ -748,7 +781,7 @@ retry:
         */
        if (!*write_result) {
                refcount_inc(&enabler->event->refcnt);
-               list_add_rcu(&enabler->link, &user_mm->enablers);
+               list_add_rcu(&enabler->mm_enablers_link, &user_mm->enablers);
        }
 
        mutex_unlock(&event_mutex);
@@ -904,8 +937,8 @@ static void user_event_destroy_validators(struct user_event *user)
        struct user_event_validator *validator, *next;
        struct list_head *head = &user->validators;
 
-       list_for_each_entry_safe(validator, next, head, link) {
-               list_del(&validator->link);
+       list_for_each_entry_safe(validator, next, head, user_event_link) {
+               list_del(&validator->user_event_link);
                kfree(validator);
        }
 }
@@ -959,7 +992,7 @@ add_validator:
        validator->offset = offset;
 
        /* Want sequential access when validating */
-       list_add_tail(&validator->link, &user->validators);
+       list_add_tail(&validator->user_event_link, &user->validators);
 
 add_field:
        field->type = type;
@@ -1349,7 +1382,7 @@ static int user_event_validate(struct user_event *user, void *data, int len)
        void *pos, *end = data + len;
        u32 loc, offset, size;
 
-       list_for_each_entry(validator, head, link) {
+       list_for_each_entry(validator, head, user_event_link) {
                pos = data + validator->offset;
 
                /* Already done min_size check, no bounds check here */
@@ -2270,9 +2303,9 @@ static long user_events_ioctl_unreg(unsigned long uarg)
         */
        mutex_lock(&event_mutex);
 
-       list_for_each_entry_safe(enabler, next, &mm->enablers, link)
+       list_for_each_entry_safe(enabler, next, &mm->enablers, mm_enablers_link) {
                if (enabler->addr == reg.disable_addr &&
-                   (enabler->values & ENABLE_VAL_BIT_MASK) == reg.disable_bit) {
+                   ENABLE_BIT(enabler) == reg.disable_bit) {
                        set_bit(ENABLE_VAL_FREEING_BIT, ENABLE_BITOPS(enabler));
 
                        if (!test_bit(ENABLE_VAL_FAULTING_BIT, ENABLE_BITOPS(enabler)))
@@ -2281,6 +2314,7 @@ static long user_events_ioctl_unreg(unsigned long uarg)
                        /* Removed at least one */
                        ret = 0;
                }
+       }
 
        mutex_unlock(&event_mutex);
 
index efbbec2caff832898f45e6f250c5bc43e26f04e9..e97e3fa5cbed0ae0ed36e60106194a60b1fa07ba 100644 (file)
@@ -1652,6 +1652,8 @@ static enum hrtimer_restart timerlat_irq(struct hrtimer *timer)
                        osnoise_stop_tracing();
                        notify_new_max_latency(diff);
 
+                       wake_up_process(tlat->kthread);
+
                        return HRTIMER_NORESTART;
                }
        }
index ef8ed3b65d0550bfd87b74c39b4657b7fc5044f4..6a4ecfb1da438743d4b8fc3c0182b22bd135c134 100644 (file)
@@ -308,7 +308,7 @@ trace_probe_primary_from_call(struct trace_event_call *call)
 {
        struct trace_probe_event *tpe = trace_probe_event_from_call(call);
 
-       return list_first_entry(&tpe->probes, struct trace_probe, list);
+       return list_first_entry_or_null(&tpe->probes, struct trace_probe, list);
 }
 
 static inline struct list_head *trace_probe_probe_list(struct trace_probe *tp)
index a931d9aaea2617a8a3f053e5943f31949a5319dc..529590499b1fa6b5877232aa82bead760813d2ac 100644 (file)
@@ -848,6 +848,12 @@ trace_selftest_startup_function_graph(struct tracer *trace,
        }
 
 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+       /*
+        * These tests can take some time to run. Make sure on non PREEMPT
+        * kernels, we do not trigger the softlockup detector.
+        */
+       cond_resched();
+
        tracing_reset_online_cpus(&tr->array_buffer);
        set_graph_array(tr);
 
@@ -869,6 +875,8 @@ trace_selftest_startup_function_graph(struct tracer *trace,
        if (ret)
                goto out;
 
+       cond_resched();
+
        ret = register_ftrace_graph(&fgraph_ops);
        if (ret) {
                warn_failed_init_tracer(trace, ret);
@@ -891,6 +899,8 @@ trace_selftest_startup_function_graph(struct tracer *trace,
        if (ret)
                goto out;
 
+       cond_resched();
+
        tracing_start();
 
        if (!ret && !count) {
index b7cbd66f889ea9033a20edf36ac6ed36e0bb6888..f80d5c51ae67106c0bd72eb19efd39f4b834e147 100644 (file)
@@ -12,58 +12,88 @@ enum vhost_task_flags {
        VHOST_TASK_FLAGS_STOP,
 };
 
+struct vhost_task {
+       bool (*fn)(void *data);
+       void *data;
+       struct completion exited;
+       unsigned long flags;
+       struct task_struct *task;
+};
+
 static int vhost_task_fn(void *data)
 {
        struct vhost_task *vtsk = data;
-       int ret;
+       bool dead = false;
+
+       for (;;) {
+               bool did_work;
+
+               /* mb paired w/ vhost_task_stop */
+               if (test_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags))
+                       break;
+
+               if (!dead && signal_pending(current)) {
+                       struct ksignal ksig;
+                       /*
+                        * Calling get_signal will block in SIGSTOP,
+                        * or clear fatal_signal_pending, but remember
+                        * what was set.
+                        *
+                        * This thread won't actually exit until all
+                        * of the file descriptors are closed, and
+                        * the release function is called.
+                        */
+                       dead = get_signal(&ksig);
+                       if (dead)
+                               clear_thread_flag(TIF_SIGPENDING);
+               }
+
+               did_work = vtsk->fn(vtsk->data);
+               if (!did_work) {
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       schedule();
+               }
+       }
 
-       ret = vtsk->fn(vtsk->data);
        complete(&vtsk->exited);
-       do_exit(ret);
+       do_exit(0);
+}
+
+/**
+ * vhost_task_wake - wakeup the vhost_task
+ * @vtsk: vhost_task to wake
+ *
+ * wake up the vhost_task worker thread
+ */
+void vhost_task_wake(struct vhost_task *vtsk)
+{
+       wake_up_process(vtsk->task);
 }
+EXPORT_SYMBOL_GPL(vhost_task_wake);
 
 /**
  * vhost_task_stop - stop a vhost_task
  * @vtsk: vhost_task to stop
  *
- * Callers must call vhost_task_should_stop and return from their worker
- * function when it returns true;
+ * vhost_task_fn ensures the worker thread exits after
+ * VHOST_TASK_FLAGS_SOP becomes true.
  */
 void vhost_task_stop(struct vhost_task *vtsk)
 {
-       pid_t pid = vtsk->task->pid;
-
        set_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags);
-       wake_up_process(vtsk->task);
+       vhost_task_wake(vtsk);
        /*
         * Make sure vhost_task_fn is no longer accessing the vhost_task before
-        * freeing it below. If userspace crashed or exited without closing,
-        * then the vhost_task->task could already be marked dead so
-        * kernel_wait will return early.
+        * freeing it below.
         */
        wait_for_completion(&vtsk->exited);
-       /*
-        * If we are just closing/removing a device and the parent process is
-        * not exiting then reap the task.
-        */
-       kernel_wait4(pid, NULL, __WCLONE, NULL);
        kfree(vtsk);
 }
 EXPORT_SYMBOL_GPL(vhost_task_stop);
 
 /**
- * vhost_task_should_stop - should the vhost task return from the work function
- * @vtsk: vhost_task to stop
- */
-bool vhost_task_should_stop(struct vhost_task *vtsk)
-{
-       return test_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags);
-}
-EXPORT_SYMBOL_GPL(vhost_task_should_stop);
-
-/**
- * vhost_task_create - create a copy of a process to be used by the kernel
- * @fn: thread stack
+ * vhost_task_create - create a copy of a task to be used by the kernel
+ * @fn: vhost worker function
  * @arg: data to be passed to fn
  * @name: the thread's name
  *
@@ -71,17 +101,17 @@ EXPORT_SYMBOL_GPL(vhost_task_should_stop);
  * failure. The returned task is inactive, and the caller must fire it up
  * through vhost_task_start().
  */
-struct vhost_task *vhost_task_create(int (*fn)(void *), void *arg,
+struct vhost_task *vhost_task_create(bool (*fn)(void *), void *arg,
                                     const char *name)
 {
        struct kernel_clone_args args = {
-               .flags          = CLONE_FS | CLONE_UNTRACED | CLONE_VM,
+               .flags          = CLONE_FS | CLONE_UNTRACED | CLONE_VM |
+                                 CLONE_THREAD | CLONE_SIGHAND,
                .exit_signal    = 0,
                .fn             = vhost_task_fn,
                .name           = name,
                .user_worker    = 1,
                .no_files       = 1,
-               .ignore_signals = 1,
        };
        struct vhost_task *vtsk;
        struct task_struct *tsk;
index 003edc5ebd6730feede2d4999372b6d339ec7d65..984985c39c9b00855ea601562223548e085ced61 100644 (file)
@@ -126,7 +126,7 @@ static const char *obj_states[ODEBUG_STATE_MAX] = {
 
 static void fill_pool(void)
 {
-       gfp_t gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;
+       gfp_t gfp = __GFP_HIGH | __GFP_NOWARN;
        struct debug_obj *obj;
        unsigned long flags;
 
@@ -591,10 +591,21 @@ static void debug_objects_fill_pool(void)
 {
        /*
         * On RT enabled kernels the pool refill must happen in preemptible
-        * context:
+        * context -- for !RT kernels we rely on the fact that spinlock_t and
+        * raw_spinlock_t are basically the same type and this lock-type
+        * inversion works just fine.
         */
-       if (!IS_ENABLED(CONFIG_PREEMPT_RT) || preemptible())
+       if (!IS_ENABLED(CONFIG_PREEMPT_RT) || preemptible()) {
+               /*
+                * Annotate away the spinlock_t inside raw_spinlock_t warning
+                * by temporarily raising the wait-type to WAIT_SLEEP, matching
+                * the preemptible() condition above.
+                */
+               static DEFINE_WAIT_OVERRIDE_MAP(fill_pool_map, LD_WAIT_SLEEP);
+               lock_map_acquire_try(&fill_pool_map);
                fill_pool();
+               lock_map_release(&fill_pool_map);
+       }
 }
 
 static void
index 38045d6d05381ebb89d73369b0c60766505ef9be..e89aaf07bde502ec4def08d1775f925c62de7838 100644 (file)
@@ -54,7 +54,7 @@ void dim_park_tired(struct dim *dim)
 }
 EXPORT_SYMBOL(dim_park_tired);
 
-void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
+bool dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
                    struct dim_stats *curr_stats)
 {
        /* u32 holds up to 71 minutes, should be enough */
@@ -66,7 +66,7 @@ void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
                             start->comp_ctr);
 
        if (!delta_us)
-               return;
+               return false;
 
        curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us);
        curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us);
@@ -79,5 +79,6 @@ void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
        else
                curr_stats->cpe_ratio = 0;
 
+       return true;
 }
 EXPORT_SYMBOL(dim_calc_stats);
index 53f6b9c6e9366200906c8e49a98d2e37161fa51b..4e32f7aaac86ca81c46188a1aeb1320b020fc215 100644 (file)
@@ -227,7 +227,8 @@ void net_dim(struct dim *dim, struct dim_sample end_sample)
                                  dim->start_sample.event_ctr);
                if (nevents < DIM_NEVENTS)
                        break;
-               dim_calc_stats(&dim->start_sample, &end_sample, &curr_stats);
+               if (!dim_calc_stats(&dim->start_sample, &end_sample, &curr_stats))
+                       break;
                if (net_dim_decision(&curr_stats, dim)) {
                        dim->state = DIM_APPLY_NEW_PROFILE;
                        schedule_work(&dim->work);
index 15462d54758d3b77c66cf6e6e1afe6d3fca2f9f2..88f77948670782327b6fd717108e070ef33042ed 100644 (file)
@@ -88,7 +88,8 @@ void rdma_dim(struct dim *dim, u64 completions)
                nevents = curr_sample->event_ctr - dim->start_sample.event_ctr;
                if (nevents < DIM_NEVENTS)
                        break;
-               dim_calc_stats(&dim->start_sample, curr_sample, &curr_stats);
+               if (!dim_calc_stats(&dim->start_sample, curr_sample, &curr_stats))
+                       break;
                if (rdma_dim_decision(&curr_stats, dim)) {
                        dim->state = DIM_APPLY_NEW_PROFILE;
                        schedule_work(&dim->work);
index 110a36479dced7f5e061d0562eb9e40bf89cdf15..8ebc43d4cc8c58824308c7ef8362f9c1e01cfa9b 100644 (file)
@@ -5317,15 +5317,9 @@ int mas_empty_area(struct ma_state *mas, unsigned long min,
 
        mt = mte_node_type(mas->node);
        pivots = ma_pivots(mas_mn(mas), mt);
-       if (offset)
-               mas->min = pivots[offset - 1] + 1;
-
-       if (offset < mt_pivots[mt])
-               mas->max = pivots[offset];
-
-       if (mas->index < mas->min)
-               mas->index = mas->min;
-
+       min = mas_safe_min(mas, pivots, offset);
+       if (mas->index < min)
+               mas->index = min;
        mas->last = mas->index + size - 1;
        return 0;
 }
index 05ed84c2fc4cec918eb462678d7b68143ae5302f..add4699fc6cd4577c693e1473db3b1b9b2003d9f 100644 (file)
@@ -45,6 +45,7 @@ struct test_batched_req {
        bool sent;
        const struct firmware *fw;
        const char *name;
+       const char *fw_buf;
        struct completion completion;
        struct task_struct *task;
        struct device *dev;
@@ -175,8 +176,14 @@ static void __test_release_all_firmware(void)
 
        for (i = 0; i < test_fw_config->num_requests; i++) {
                req = &test_fw_config->reqs[i];
-               if (req->fw)
+               if (req->fw) {
+                       if (req->fw_buf) {
+                               kfree_const(req->fw_buf);
+                               req->fw_buf = NULL;
+                       }
                        release_firmware(req->fw);
+                       req->fw = NULL;
+               }
        }
 
        vfree(test_fw_config->reqs);
@@ -207,7 +214,7 @@ static int __kstrncpy(char **dst, const char *name, size_t count, gfp_t gfp)
 {
        *dst = kstrndup(name, count, gfp);
        if (!*dst)
-               return -ENOSPC;
+               return -ENOMEM;
        return count;
 }
 
@@ -353,16 +360,26 @@ static ssize_t config_test_show_str(char *dst,
        return len;
 }
 
-static intest_dev_config_update_bool(const char *buf, size_t size,
+static inline int __test_dev_config_update_bool(const char *buf, size_t size,
                                       bool *cfg)
 {
        int ret;
 
-       mutex_lock(&test_fw_mutex);
        if (kstrtobool(buf, cfg) < 0)
                ret = -EINVAL;
        else
                ret = size;
+
+       return ret;
+}
+
+static int test_dev_config_update_bool(const char *buf, size_t size,
+                                      bool *cfg)
+{
+       int ret;
+
+       mutex_lock(&test_fw_mutex);
+       ret = __test_dev_config_update_bool(buf, size, cfg);
        mutex_unlock(&test_fw_mutex);
 
        return ret;
@@ -373,7 +390,8 @@ static ssize_t test_dev_config_show_bool(char *buf, bool val)
        return snprintf(buf, PAGE_SIZE, "%d\n", val);
 }
 
-static int test_dev_config_update_size_t(const char *buf,
+static int __test_dev_config_update_size_t(
+                                        const char *buf,
                                         size_t size,
                                         size_t *cfg)
 {
@@ -384,9 +402,7 @@ static int test_dev_config_update_size_t(const char *buf,
        if (ret)
                return ret;
 
-       mutex_lock(&test_fw_mutex);
        *(size_t *)cfg = new;
-       mutex_unlock(&test_fw_mutex);
 
        /* Always return full write size even if we didn't consume all */
        return size;
@@ -402,7 +418,7 @@ static ssize_t test_dev_config_show_int(char *buf, int val)
        return snprintf(buf, PAGE_SIZE, "%d\n", val);
 }
 
-static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg)
+static int __test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg)
 {
        u8 val;
        int ret;
@@ -411,14 +427,23 @@ static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg)
        if (ret)
                return ret;
 
-       mutex_lock(&test_fw_mutex);
        *(u8 *)cfg = val;
-       mutex_unlock(&test_fw_mutex);
 
        /* Always return full write size even if we didn't consume all */
        return size;
 }
 
+static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg)
+{
+       int ret;
+
+       mutex_lock(&test_fw_mutex);
+       ret = __test_dev_config_update_u8(buf, size, cfg);
+       mutex_unlock(&test_fw_mutex);
+
+       return ret;
+}
+
 static ssize_t test_dev_config_show_u8(char *buf, u8 val)
 {
        return snprintf(buf, PAGE_SIZE, "%u\n", val);
@@ -471,10 +496,10 @@ static ssize_t config_num_requests_store(struct device *dev,
                mutex_unlock(&test_fw_mutex);
                goto out;
        }
-       mutex_unlock(&test_fw_mutex);
 
-       rc = test_dev_config_update_u8(buf, count,
-                                      &test_fw_config->num_requests);
+       rc = __test_dev_config_update_u8(buf, count,
+                                        &test_fw_config->num_requests);
+       mutex_unlock(&test_fw_mutex);
 
 out:
        return rc;
@@ -518,10 +543,10 @@ static ssize_t config_buf_size_store(struct device *dev,
                mutex_unlock(&test_fw_mutex);
                goto out;
        }
-       mutex_unlock(&test_fw_mutex);
 
-       rc = test_dev_config_update_size_t(buf, count,
-                                          &test_fw_config->buf_size);
+       rc = __test_dev_config_update_size_t(buf, count,
+                                            &test_fw_config->buf_size);
+       mutex_unlock(&test_fw_mutex);
 
 out:
        return rc;
@@ -548,10 +573,10 @@ static ssize_t config_file_offset_store(struct device *dev,
                mutex_unlock(&test_fw_mutex);
                goto out;
        }
-       mutex_unlock(&test_fw_mutex);
 
-       rc = test_dev_config_update_size_t(buf, count,
-                                          &test_fw_config->file_offset);
+       rc = __test_dev_config_update_size_t(buf, count,
+                                            &test_fw_config->file_offset);
+       mutex_unlock(&test_fw_mutex);
 
 out:
        return rc;
@@ -646,12 +671,14 @@ static ssize_t trigger_request_store(struct device *dev,
 
        name = kstrndup(buf, count, GFP_KERNEL);
        if (!name)
-               return -ENOSPC;
+               return -ENOMEM;
 
        pr_info("loading '%s'\n", name);
 
        mutex_lock(&test_fw_mutex);
        release_firmware(test_firmware);
+       if (test_fw_config->reqs)
+               __test_release_all_firmware();
        test_firmware = NULL;
        rc = request_firmware(&test_firmware, name, dev);
        if (rc) {
@@ -692,7 +719,7 @@ static ssize_t trigger_request_platform_store(struct device *dev,
 
        name = kstrndup(buf, count, GFP_KERNEL);
        if (!name)
-               return -ENOSPC;
+               return -ENOMEM;
 
        pr_info("inserting test platform fw '%s'\n", name);
        efi_embedded_fw.name = name;
@@ -745,13 +772,15 @@ static ssize_t trigger_async_request_store(struct device *dev,
 
        name = kstrndup(buf, count, GFP_KERNEL);
        if (!name)
-               return -ENOSPC;
+               return -ENOMEM;
 
        pr_info("loading '%s'\n", name);
 
        mutex_lock(&test_fw_mutex);
        release_firmware(test_firmware);
        test_firmware = NULL;
+       if (test_fw_config->reqs)
+               __test_release_all_firmware();
        rc = request_firmware_nowait(THIS_MODULE, 1, name, dev, GFP_KERNEL,
                                     NULL, trigger_async_request_cb);
        if (rc) {
@@ -788,12 +817,14 @@ static ssize_t trigger_custom_fallback_store(struct device *dev,
 
        name = kstrndup(buf, count, GFP_KERNEL);
        if (!name)
-               return -ENOSPC;
+               return -ENOMEM;
 
        pr_info("loading '%s' using custom fallback mechanism\n", name);
 
        mutex_lock(&test_fw_mutex);
        release_firmware(test_firmware);
+       if (test_fw_config->reqs)
+               __test_release_all_firmware();
        test_firmware = NULL;
        rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOUEVENT, name,
                                     dev, GFP_KERNEL, NULL,
@@ -837,7 +868,7 @@ static int test_fw_run_batch_request(void *data)
 
                test_buf = kzalloc(TEST_FIRMWARE_BUF_SIZE, GFP_KERNEL);
                if (!test_buf)
-                       return -ENOSPC;
+                       return -ENOMEM;
 
                if (test_fw_config->partial)
                        req->rc = request_partial_firmware_into_buf
@@ -856,6 +887,8 @@ static int test_fw_run_batch_request(void *data)
                                                 test_fw_config->buf_size);
                if (!req->fw)
                        kfree(test_buf);
+               else
+                       req->fw_buf = test_buf;
        } else {
                req->rc = test_fw_config->req_firmware(&req->fw,
                                                       req->name,
@@ -895,6 +928,11 @@ static ssize_t trigger_batched_requests_store(struct device *dev,
 
        mutex_lock(&test_fw_mutex);
 
+       if (test_fw_config->reqs) {
+               rc = -EBUSY;
+               goto out_bail;
+       }
+
        test_fw_config->reqs =
                vzalloc(array3_size(sizeof(struct test_batched_req),
                                    test_fw_config->num_requests, 2));
@@ -911,6 +949,7 @@ static ssize_t trigger_batched_requests_store(struct device *dev,
                req->fw = NULL;
                req->idx = i;
                req->name = test_fw_config->name;
+               req->fw_buf = NULL;
                req->dev = dev;
                init_completion(&req->completion);
                req->task = kthread_run(test_fw_run_batch_request, req,
@@ -993,6 +1032,11 @@ ssize_t trigger_batched_requests_async_store(struct device *dev,
 
        mutex_lock(&test_fw_mutex);
 
+       if (test_fw_config->reqs) {
+               rc = -EBUSY;
+               goto out_bail;
+       }
+
        test_fw_config->reqs =
                vzalloc(array3_size(sizeof(struct test_batched_req),
                                    test_fw_config->num_requests, 2));
@@ -1010,6 +1054,7 @@ ssize_t trigger_batched_requests_async_store(struct device *dev,
        for (i = 0; i < test_fw_config->num_requests; i++) {
                req = &test_fw_config->reqs[i];
                req->name = test_fw_config->name;
+               req->fw_buf = NULL;
                req->fw = NULL;
                req->idx = i;
                init_completion(&req->completion);
index a925415b4d1097661fd4d2425c513c5526bce164..018a5bd2f576defbaabaff287d835e29b8222be5 100644 (file)
@@ -98,6 +98,7 @@ config PAGE_OWNER
 config PAGE_TABLE_CHECK
        bool "Check for invalid mappings in user page tables"
        depends on ARCH_SUPPORTS_PAGE_TABLE_CHECK
+       depends on EXCLUSIVE_SYSTEM_RAM
        select PAGE_EXTENSION
        help
          Check that anonymous page is not being mapped twice with read write
index 2aafc46a4aaf1b7e627214e2a69b4864aaf78eeb..392fb273e7bd92487a15ebec4f9bd9c1bbc8eecf 100644 (file)
@@ -29,7 +29,7 @@
  * canary of every 8 bytes is the same. 64-bit memory can be filled and checked
  * at a time instead of byte by byte to improve performance.
  */
-#define KFENCE_CANARY_PATTERN_U64 ((u64)0xaaaaaaaaaaaaaaaa ^ (u64)(0x0706050403020100))
+#define KFENCE_CANARY_PATTERN_U64 ((u64)0xaaaaaaaaaaaaaaaa ^ (u64)(le64_to_cpu(0x0706050403020100)))
 
 /* Maximum stack depth for reports. */
 #define KFENCE_STACK_DEPTH 64
index 25d8610c00429c415990f68cac7c6a1250349857..f2baf97d5f38904f4313fdfcf748436fb66e253e 100644 (file)
@@ -71,6 +71,8 @@ static void page_table_check_clear(struct mm_struct *mm, unsigned long addr,
 
        page = pfn_to_page(pfn);
        page_ext = page_ext_get(page);
+
+       BUG_ON(PageSlab(page));
        anon = PageAnon(page);
 
        for (i = 0; i < pgcnt; i++) {
@@ -107,6 +109,8 @@ static void page_table_check_set(struct mm_struct *mm, unsigned long addr,
 
        page = pfn_to_page(pfn);
        page_ext = page_ext_get(page);
+
+       BUG_ON(PageSlab(page));
        anon = PageAnon(page);
 
        for (i = 0; i < pgcnt; i++) {
@@ -133,6 +137,8 @@ void __page_table_check_zero(struct page *page, unsigned int order)
        struct page_ext *page_ext;
        unsigned long i;
 
+       BUG_ON(PageSlab(page));
+
        page_ext = page_ext_get(page);
        BUG_ON(!page_ext);
        for (i = 0; i < (1ul << order); i++) {
index 3f83b10c5031c09e8ac24b3e0605477753fc5651..fe10436d99114ef7be4ade6edc4cf0bd08e5a2d0 100644 (file)
@@ -237,7 +237,8 @@ int shrinker_debugfs_rename(struct shrinker *shrinker, const char *fmt, ...)
 }
 EXPORT_SYMBOL(shrinker_debugfs_rename);
 
-struct dentry *shrinker_debugfs_remove(struct shrinker *shrinker)
+struct dentry *shrinker_debugfs_detach(struct shrinker *shrinker,
+                                      int *debugfs_id)
 {
        struct dentry *entry = shrinker->debugfs_entry;
 
@@ -246,14 +247,18 @@ struct dentry *shrinker_debugfs_remove(struct shrinker *shrinker)
        kfree_const(shrinker->name);
        shrinker->name = NULL;
 
-       if (entry) {
-               ida_free(&shrinker_debugfs_ida, shrinker->debugfs_id);
-               shrinker->debugfs_entry = NULL;
-       }
+       *debugfs_id = entry ? shrinker->debugfs_id : -1;
+       shrinker->debugfs_entry = NULL;
 
        return entry;
 }
 
+void shrinker_debugfs_remove(struct dentry *debugfs_entry, int debugfs_id)
+{
+       debugfs_remove_recursive(debugfs_entry);
+       ida_free(&shrinker_debugfs_ida, debugfs_id);
+}
+
 static int __init shrinker_debugfs_init(void)
 {
        struct shrinker *shrinker;
index d257916f39e50027dc7c06aa38c19430ee9dc4ee..6d0cd2840cf080616e61002463aad87420af0259 100644 (file)
@@ -805,6 +805,7 @@ EXPORT_SYMBOL(register_shrinker);
 void unregister_shrinker(struct shrinker *shrinker)
 {
        struct dentry *debugfs_entry;
+       int debugfs_id;
 
        if (!(shrinker->flags & SHRINKER_REGISTERED))
                return;
@@ -814,13 +815,13 @@ void unregister_shrinker(struct shrinker *shrinker)
        shrinker->flags &= ~SHRINKER_REGISTERED;
        if (shrinker->flags & SHRINKER_MEMCG_AWARE)
                unregister_memcg_shrinker(shrinker);
-       debugfs_entry = shrinker_debugfs_remove(shrinker);
+       debugfs_entry = shrinker_debugfs_detach(shrinker, &debugfs_id);
        mutex_unlock(&shrinker_mutex);
 
        atomic_inc(&shrinker_srcu_generation);
        synchronize_srcu(&shrinker_srcu);
 
-       debugfs_remove_recursive(debugfs_entry);
+       shrinker_debugfs_remove(debugfs_entry, debugfs_id);
 
        kfree(shrinker->nr_deferred);
        shrinker->nr_deferred = NULL;
index 44ddaf5d601e95a2284e0e21c4858d2153dc81f1..02f7f414aade05570661eba0c3da7cc78976386b 100644 (file)
@@ -1331,31 +1331,6 @@ void *zs_map_object(struct zs_pool *pool, unsigned long handle,
        obj_to_location(obj, &page, &obj_idx);
        zspage = get_zspage(page);
 
-#ifdef CONFIG_ZPOOL
-       /*
-        * Move the zspage to front of pool's LRU.
-        *
-        * Note that this is swap-specific, so by definition there are no ongoing
-        * accesses to the memory while the page is swapped out that would make
-        * it "hot". A new entry is hot, then ages to the tail until it gets either
-        * written back or swaps back in.
-        *
-        * Furthermore, map is also called during writeback. We must not put an
-        * isolated page on the LRU mid-reclaim.
-        *
-        * As a result, only update the LRU when the page is mapped for write
-        * when it's first instantiated.
-        *
-        * This is a deviation from the other backends, which perform this update
-        * in the allocation function (zbud_alloc, z3fold_alloc).
-        */
-       if (mm == ZS_MM_WO) {
-               if (!list_empty(&zspage->lru))
-                       list_del(&zspage->lru);
-               list_add(&zspage->lru, &pool->lru);
-       }
-#endif
-
        /*
         * migration cannot move any zpages in this zspage. Here, pool->lock
         * is too heavy since callers would take some time until they calls
@@ -1525,9 +1500,8 @@ unsigned long zs_malloc(struct zs_pool *pool, size_t size, gfp_t gfp)
                fix_fullness_group(class, zspage);
                record_obj(handle, obj);
                class_stat_inc(class, ZS_OBJS_INUSE, 1);
-               spin_unlock(&pool->lock);
 
-               return handle;
+               goto out;
        }
 
        spin_unlock(&pool->lock);
@@ -1550,6 +1524,14 @@ unsigned long zs_malloc(struct zs_pool *pool, size_t size, gfp_t gfp)
 
        /* We completely set up zspage so mark them as movable */
        SetZsPageMovable(pool, zspage);
+out:
+#ifdef CONFIG_ZPOOL
+       /* Add/move zspage to beginning of LRU */
+       if (!list_empty(&zspage->lru))
+               list_del(&zspage->lru);
+       list_add(&zspage->lru, &pool->lru);
+#endif
+
        spin_unlock(&pool->lock);
 
        return handle;
index e1e621d0b6a0289b6e7ef5193b108e7b15a80bc0..59da2a415fbb668c1127a496f68eac26cf5d64bf 100644 (file)
@@ -1020,6 +1020,22 @@ static int zswap_writeback_entry(struct zpool *pool, unsigned long handle)
                goto fail;
 
        case ZSWAP_SWAPCACHE_NEW: /* page is locked */
+               /*
+                * Having a local reference to the zswap entry doesn't exclude
+                * swapping from invalidating and recycling the swap slot. Once
+                * the swapcache is secured against concurrent swapping to and
+                * from the slot, recheck that the entry is still current before
+                * writing.
+                */
+               spin_lock(&tree->lock);
+               if (zswap_rb_search(&tree->rbroot, entry->offset) != entry) {
+                       spin_unlock(&tree->lock);
+                       delete_from_swap_cache(page_folio(page));
+                       ret = -ENOMEM;
+                       goto fail;
+               }
+               spin_unlock(&tree->lock);
+
                /* decompress */
                acomp_ctx = raw_cpu_ptr(entry->pool->acomp_ctx);
                dlen = PAGE_SIZE;
index 870e4935d6e6e117eec652b6867fc4c53b94350c..b90781b9ece6402664552295e1f07b2fd97c2465 100644 (file)
@@ -109,8 +109,8 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,
         * NOTE: THIS ASSUMES DIX ETHERNET, SPECIFICALLY NOT SUPPORTING
         * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs...
         */
-       if (veth->h_vlan_proto != vlan->vlan_proto ||
-           vlan->flags & VLAN_FLAG_REORDER_HDR) {
+       if (vlan->flags & VLAN_FLAG_REORDER_HDR ||
+           veth->h_vlan_proto != vlan->vlan_proto) {
                u16 vlan_tci;
                vlan_tci = vlan->vlan_id;
                vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb->priority);
index 2b2d33eeaf200309485ef846c597ad2d39b5f100..995d29e7fb138cb566e8a722bd490d5d062417fb 100644 (file)
@@ -400,6 +400,7 @@ done:
        return error;
 }
 
+#ifdef CONFIG_PROC_FS
 void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos)
 {
        mutex_lock(&atm_dev_mutex);
@@ -415,3 +416,4 @@ void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
        return seq_list_next(v, &atm_devs, pos);
 }
+#endif
index 640b951bf40a1149357357ae198c0b7b3bb0ba94..f75ef12f18f774b7eef16175d430a70275275855 100644 (file)
@@ -1083,8 +1083,28 @@ static void hci_conn_unlink(struct hci_conn *conn)
        if (!conn->parent) {
                struct hci_link *link, *t;
 
-               list_for_each_entry_safe(link, t, &conn->link_list, list)
-                       hci_conn_unlink(link->conn);
+               list_for_each_entry_safe(link, t, &conn->link_list, list) {
+                       struct hci_conn *child = link->conn;
+
+                       hci_conn_unlink(child);
+
+                       /* If hdev is down it means
+                        * hci_dev_close_sync/hci_conn_hash_flush is in progress
+                        * and links don't need to be cleanup as all connections
+                        * would be cleanup.
+                        */
+                       if (!test_bit(HCI_UP, &hdev->flags))
+                               continue;
+
+                       /* Due to race, SCO connection might be not established
+                        * yet at this point. Delete it now, otherwise it is
+                        * possible for it to be stuck and can't be deleted.
+                        */
+                       if ((child->type == SCO_LINK ||
+                            child->type == ESCO_LINK) &&
+                           child->handle == HCI_CONN_HANDLE_UNSET)
+                               hci_conn_del(child);
+               }
 
                return;
        }
@@ -1092,35 +1112,30 @@ static void hci_conn_unlink(struct hci_conn *conn)
        if (!conn->link)
                return;
 
-       hci_conn_put(conn->parent);
-       conn->parent = NULL;
-
        list_del_rcu(&conn->link->list);
        synchronize_rcu();
 
+       hci_conn_drop(conn->parent);
+       hci_conn_put(conn->parent);
+       conn->parent = NULL;
+
        kfree(conn->link);
        conn->link = NULL;
-
-       /* Due to race, SCO connection might be not established
-        * yet at this point. Delete it now, otherwise it is
-        * possible for it to be stuck and can't be deleted.
-        */
-       if (conn->handle == HCI_CONN_HANDLE_UNSET)
-               hci_conn_del(conn);
 }
 
-int hci_conn_del(struct hci_conn *conn)
+void hci_conn_del(struct hci_conn *conn)
 {
        struct hci_dev *hdev = conn->hdev;
 
        BT_DBG("%s hcon %p handle %d", hdev->name, conn, conn->handle);
 
+       hci_conn_unlink(conn);
+
        cancel_delayed_work_sync(&conn->disc_work);
        cancel_delayed_work_sync(&conn->auto_accept_work);
        cancel_delayed_work_sync(&conn->idle_work);
 
        if (conn->type == ACL_LINK) {
-               hci_conn_unlink(conn);
                /* Unacked frames */
                hdev->acl_cnt += conn->sent;
        } else if (conn->type == LE_LINK) {
@@ -1131,13 +1146,6 @@ int hci_conn_del(struct hci_conn *conn)
                else
                        hdev->acl_cnt += conn->sent;
        } else {
-               struct hci_conn *acl = conn->parent;
-
-               if (acl) {
-                       hci_conn_unlink(conn);
-                       hci_conn_drop(acl);
-               }
-
                /* Unacked ISO frames */
                if (conn->type == ISO_LINK) {
                        if (hdev->iso_pkts)
@@ -1160,8 +1168,6 @@ int hci_conn_del(struct hci_conn *conn)
         * rest of hci_conn_del.
         */
        hci_conn_cleanup(conn);
-
-       return 0;
 }
 
 struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src, uint8_t src_type)
@@ -2462,22 +2468,21 @@ timer:
 /* Drop all connection on the device */
 void hci_conn_hash_flush(struct hci_dev *hdev)
 {
-       struct hci_conn_hash *h = &hdev->conn_hash;
-       struct hci_conn *c, *n;
+       struct list_head *head = &hdev->conn_hash.list;
+       struct hci_conn *conn;
 
        BT_DBG("hdev %s", hdev->name);
 
-       list_for_each_entry_safe(c, n, &h->list, list) {
-               c->state = BT_CLOSED;
-
-               hci_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM);
-
-               /* Unlink before deleting otherwise it is possible that
-                * hci_conn_del removes the link which may cause the list to
-                * contain items already freed.
-                */
-               hci_conn_unlink(c);
-               hci_conn_del(c);
+       /* We should not traverse the list here, because hci_conn_del
+        * can remove extra links, which may cause the list traversal
+        * to hit items that have already been released.
+        */
+       while ((conn = list_first_entry_or_null(head,
+                                               struct hci_conn,
+                                               list)) != NULL) {
+               conn->state = BT_CLOSED;
+               hci_disconn_cfm(conn, HCI_ERROR_LOCAL_HOST_TERM);
+               hci_conn_del(conn);
        }
 }
 
index 57744704ff692ae4dd573ec025cf29935785900e..84d6dd5e5b1a23a2fddad3e0573ebf7b1924204c 100644 (file)
@@ -42,7 +42,7 @@ int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb
            eth_type_vlan(skb->protocol)) {
                int depth;
 
-               if (!__vlan_get_protocol(skb, skb->protocol, &depth))
+               if (!vlan_get_protocol_and_depth(skb, skb->protocol, &depth))
                        goto drop;
 
                skb_set_network_header(skb, depth);
index 2b053289f01665b2eda36cd397a8479f22083dbe..efb096025151a55c23e73267a9853a88c39d50b6 100644 (file)
@@ -27,6 +27,10 @@ int br_process_vlan_tunnel_info(const struct net_bridge *br,
 int br_get_vlan_tunnel_info_size(struct net_bridge_vlan_group *vg);
 int br_fill_vlan_tunnel_info(struct sk_buff *skb,
                             struct net_bridge_vlan_group *vg);
+bool vlan_tunid_inrange(const struct net_bridge_vlan *v_curr,
+                       const struct net_bridge_vlan *v_last);
+int br_vlan_tunnel_info(const struct net_bridge_port *p, int cmd,
+                       u16 vid, u32 tun_id, bool *changed);
 
 #ifdef CONFIG_BRIDGE_VLAN_FILTERING
 /* br_vlan_tunnel.c */
@@ -43,10 +47,6 @@ void br_handle_ingress_vlan_tunnel(struct sk_buff *skb,
                                   struct net_bridge_vlan_group *vg);
 int br_handle_egress_vlan_tunnel(struct sk_buff *skb,
                                 struct net_bridge_vlan *vlan);
-bool vlan_tunid_inrange(const struct net_bridge_vlan *v_curr,
-                       const struct net_bridge_vlan *v_last);
-int br_vlan_tunnel_info(const struct net_bridge_port *p, int cmd,
-                       u16 vid, u32 tun_id, bool *changed);
 #else
 static inline int vlan_tunnel_init(struct net_bridge_vlan_group *vg)
 {
index a750259cb79c4fb93cfc6d7b50193d585831cca7..84f9aba029017c47349aaed84639228a538fece1 100644 (file)
@@ -1139,7 +1139,7 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
        struct isotp_sock *so = isotp_sk(sk);
        int ret = 0;
 
-       if (flags & ~(MSG_DONTWAIT | MSG_TRUNC | MSG_PEEK))
+       if (flags & ~(MSG_DONTWAIT | MSG_TRUNC | MSG_PEEK | MSG_CMSG_COMPAT))
                return -EINVAL;
 
        if (!so->bound)
index 7e90f9e61d9bc5bac7e903fed4c8a7eadc7a8906..1790469b25808a8357e92ee3e42ffef9c06c0422 100644 (file)
@@ -798,7 +798,7 @@ static int j1939_sk_recvmsg(struct socket *sock, struct msghdr *msg,
        struct j1939_sk_buff_cb *skcb;
        int ret = 0;
 
-       if (flags & ~(MSG_DONTWAIT | MSG_ERRQUEUE))
+       if (flags & ~(MSG_DONTWAIT | MSG_ERRQUEUE | MSG_CMSG_COMPAT))
                return -EINVAL;
 
        if (flags & MSG_ERRQUEUE)
index 5662dff3d381a92b271d9cba38a28a6a8478c114..176eb58347461b160890ce2d6b2d3cbc7412e321 100644 (file)
@@ -807,18 +807,21 @@ __poll_t datagram_poll(struct file *file, struct socket *sock,
 {
        struct sock *sk = sock->sk;
        __poll_t mask;
+       u8 shutdown;
 
        sock_poll_wait(file, sock, wait);
        mask = 0;
 
        /* exceptional events? */
-       if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
+       if (READ_ONCE(sk->sk_err) ||
+           !skb_queue_empty_lockless(&sk->sk_error_queue))
                mask |= EPOLLERR |
                        (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
 
-       if (sk->sk_shutdown & RCV_SHUTDOWN)
+       shutdown = READ_ONCE(sk->sk_shutdown);
+       if (shutdown & RCV_SHUTDOWN)
                mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
-       if (sk->sk_shutdown == SHUTDOWN_MASK)
+       if (shutdown == SHUTDOWN_MASK)
                mask |= EPOLLHUP;
 
        /* readable? */
@@ -827,10 +830,12 @@ __poll_t datagram_poll(struct file *file, struct socket *sock,
 
        /* Connection-based need to check for termination and startup */
        if (connection_based(sk)) {
-               if (sk->sk_state == TCP_CLOSE)
+               int state = READ_ONCE(sk->sk_state);
+
+               if (state == TCP_CLOSE)
                        mask |= EPOLLHUP;
                /* connection hasn't started yet? */
-               if (sk->sk_state == TCP_SYN_SENT)
+               if (state == TCP_SYN_SENT)
                        return mask;
        }
 
index 735096d42c1d13999597a882370ca439e9389e24..b3c13e0419356b943e90b1f46dd7e035c6ec1a9c 100644 (file)
@@ -3335,7 +3335,7 @@ __be16 skb_network_protocol(struct sk_buff *skb, int *depth)
                type = eth->h_proto;
        }
 
-       return __vlan_get_protocol(skb, type, depth);
+       return vlan_get_protocol_and_depth(skb, type, depth);
 }
 
 /* openvswitch calls this on rx path, so we need a different check.
index e212e9d7edcb816f1c302ab2af76a5005a86137c..a3e12a61d456c4f5ded8b6cb4506e64dda46198c 100644 (file)
@@ -134,6 +134,29 @@ EXPORT_SYMBOL(page_pool_ethtool_stats_get);
 #define recycle_stat_add(pool, __stat, val)
 #endif
 
+static bool page_pool_producer_lock(struct page_pool *pool)
+       __acquires(&pool->ring.producer_lock)
+{
+       bool in_softirq = in_softirq();
+
+       if (in_softirq)
+               spin_lock(&pool->ring.producer_lock);
+       else
+               spin_lock_bh(&pool->ring.producer_lock);
+
+       return in_softirq;
+}
+
+static void page_pool_producer_unlock(struct page_pool *pool,
+                                     bool in_softirq)
+       __releases(&pool->ring.producer_lock)
+{
+       if (in_softirq)
+               spin_unlock(&pool->ring.producer_lock);
+       else
+               spin_unlock_bh(&pool->ring.producer_lock);
+}
+
 static int page_pool_init(struct page_pool *pool,
                          const struct page_pool_params *params)
 {
@@ -617,6 +640,7 @@ void page_pool_put_page_bulk(struct page_pool *pool, void **data,
                             int count)
 {
        int i, bulk_len = 0;
+       bool in_softirq;
 
        for (i = 0; i < count; i++) {
                struct page *page = virt_to_head_page(data[i]);
@@ -635,7 +659,7 @@ void page_pool_put_page_bulk(struct page_pool *pool, void **data,
                return;
 
        /* Bulk producer into ptr_ring page_pool cache */
-       page_pool_ring_lock(pool);
+       in_softirq = page_pool_producer_lock(pool);
        for (i = 0; i < bulk_len; i++) {
                if (__ptr_ring_produce(&pool->ring, data[i])) {
                        /* ring full */
@@ -644,7 +668,7 @@ void page_pool_put_page_bulk(struct page_pool *pool, void **data,
                }
        }
        recycle_stat_add(pool, ring, i);
-       page_pool_ring_unlock(pool);
+       page_pool_producer_unlock(pool, in_softirq);
 
        /* Hopefully all pages was return into ptr_ring */
        if (likely(i == bulk_len))
index 653901a1bf750d79caacc2f4003b963ba22d9fcc..41de3a2f29e15a1db04c9fd7f0b723c501fa0256 100644 (file)
@@ -2385,6 +2385,37 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[],
                if (tb[IFLA_BROADCAST] &&
                    nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
                        return -EINVAL;
+
+               if (tb[IFLA_GSO_MAX_SIZE] &&
+                   nla_get_u32(tb[IFLA_GSO_MAX_SIZE]) > dev->tso_max_size) {
+                       NL_SET_ERR_MSG(extack, "too big gso_max_size");
+                       return -EINVAL;
+               }
+
+               if (tb[IFLA_GSO_MAX_SEGS] &&
+                   (nla_get_u32(tb[IFLA_GSO_MAX_SEGS]) > GSO_MAX_SEGS ||
+                    nla_get_u32(tb[IFLA_GSO_MAX_SEGS]) > dev->tso_max_segs)) {
+                       NL_SET_ERR_MSG(extack, "too big gso_max_segs");
+                       return -EINVAL;
+               }
+
+               if (tb[IFLA_GRO_MAX_SIZE] &&
+                   nla_get_u32(tb[IFLA_GRO_MAX_SIZE]) > GRO_MAX_SIZE) {
+                       NL_SET_ERR_MSG(extack, "too big gro_max_size");
+                       return -EINVAL;
+               }
+
+               if (tb[IFLA_GSO_IPV4_MAX_SIZE] &&
+                   nla_get_u32(tb[IFLA_GSO_IPV4_MAX_SIZE]) > dev->tso_max_size) {
+                       NL_SET_ERR_MSG(extack, "too big gso_ipv4_max_size");
+                       return -EINVAL;
+               }
+
+               if (tb[IFLA_GRO_IPV4_MAX_SIZE] &&
+                   nla_get_u32(tb[IFLA_GRO_IPV4_MAX_SIZE]) > GRO_MAX_SIZE) {
+                       NL_SET_ERR_MSG(extack, "too big gro_ipv4_max_size");
+                       return -EINVAL;
+               }
        }
 
        if (tb[IFLA_AF_SPEC]) {
@@ -2858,11 +2889,6 @@ static int do_setlink(const struct sk_buff *skb,
        if (tb[IFLA_GSO_MAX_SIZE]) {
                u32 max_size = nla_get_u32(tb[IFLA_GSO_MAX_SIZE]);
 
-               if (max_size > dev->tso_max_size) {
-                       err = -EINVAL;
-                       goto errout;
-               }
-
                if (dev->gso_max_size ^ max_size) {
                        netif_set_gso_max_size(dev, max_size);
                        status |= DO_SETLINK_MODIFIED;
@@ -2872,11 +2898,6 @@ static int do_setlink(const struct sk_buff *skb,
        if (tb[IFLA_GSO_MAX_SEGS]) {
                u32 max_segs = nla_get_u32(tb[IFLA_GSO_MAX_SEGS]);
 
-               if (max_segs > GSO_MAX_SEGS || max_segs > dev->tso_max_segs) {
-                       err = -EINVAL;
-                       goto errout;
-               }
-
                if (dev->gso_max_segs ^ max_segs) {
                        netif_set_gso_max_segs(dev, max_segs);
                        status |= DO_SETLINK_MODIFIED;
@@ -2895,11 +2916,6 @@ static int do_setlink(const struct sk_buff *skb,
        if (tb[IFLA_GSO_IPV4_MAX_SIZE]) {
                u32 max_size = nla_get_u32(tb[IFLA_GSO_IPV4_MAX_SIZE]);
 
-               if (max_size > dev->tso_max_size) {
-                       err = -EINVAL;
-                       goto errout;
-               }
-
                if (dev->gso_ipv4_max_size ^ max_size) {
                        netif_set_gso_ipv4_max_size(dev, max_size);
                        status |= DO_SETLINK_MODIFIED;
@@ -3285,6 +3301,7 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname,
        struct net_device *dev;
        unsigned int num_tx_queues = 1;
        unsigned int num_rx_queues = 1;
+       int err;
 
        if (tb[IFLA_NUM_TX_QUEUES])
                num_tx_queues = nla_get_u32(tb[IFLA_NUM_TX_QUEUES]);
@@ -3320,13 +3337,18 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname,
        if (!dev)
                return ERR_PTR(-ENOMEM);
 
+       err = validate_linkmsg(dev, tb, extack);
+       if (err < 0) {
+               free_netdev(dev);
+               return ERR_PTR(err);
+       }
+
        dev_net_set(dev, net);
        dev->rtnl_link_ops = ops;
        dev->rtnl_link_state = RTNL_LINK_INITIALIZING;
 
        if (tb[IFLA_MTU]) {
                u32 mtu = nla_get_u32(tb[IFLA_MTU]);
-               int err;
 
                err = dev_validate_mtu(dev, mtu, extack);
                if (err) {
index 26a586007d8b1ae39ab7a09eecf8575e04dadfeb..cea28d30abb550c4d1526a26f5dade1ff9d7bbea 100644 (file)
@@ -5224,8 +5224,10 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
        } else {
                skb = skb_clone(orig_skb, GFP_ATOMIC);
 
-               if (skb_orphan_frags_rx(skb, GFP_ATOMIC))
+               if (skb_orphan_frags_rx(skb, GFP_ATOMIC)) {
+                       kfree_skb(skb);
                        return;
+               }
        }
        if (!skb)
                return;
@@ -5298,7 +5300,7 @@ bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off)
        u32 csum_end = (u32)start + (u32)off + sizeof(__sum16);
        u32 csum_start = skb_headroom(skb) + (u32)start;
 
-       if (unlikely(csum_start > U16_MAX || csum_end > skb_headlen(skb))) {
+       if (unlikely(csum_start >= U16_MAX || csum_end > skb_headlen(skb))) {
                net_warn_ratelimited("bad partial csum: csum=%u/%u headroom=%u headlen=%u\n",
                                     start, off, skb_headroom(skb), skb_headlen(skb));
                return false;
@@ -5306,7 +5308,7 @@ bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off)
        skb->ip_summed = CHECKSUM_PARTIAL;
        skb->csum_start = csum_start;
        skb->csum_offset = off;
-       skb_set_transport_header(skb, start);
+       skb->transport_header = csum_start;
        return true;
 }
 EXPORT_SYMBOL_GPL(skb_partial_csum_set);
index f81883759d381c14d70f126d7281404e786259f9..a9060e1f0e4378fa47cfd375b4729b5b0a9f54ec 100644 (file)
@@ -481,8 +481,6 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
                msg_rx = sk_psock_peek_msg(psock);
        }
 out:
-       if (psock->work_state.skb && copied > 0)
-               schedule_work(&psock->work);
        return copied;
 }
 EXPORT_SYMBOL_GPL(sk_msg_recvmsg);
@@ -624,42 +622,33 @@ static int sk_psock_handle_skb(struct sk_psock *psock, struct sk_buff *skb,
 
 static void sk_psock_skb_state(struct sk_psock *psock,
                               struct sk_psock_work_state *state,
-                              struct sk_buff *skb,
                               int len, int off)
 {
        spin_lock_bh(&psock->ingress_lock);
        if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) {
-               state->skb = skb;
                state->len = len;
                state->off = off;
-       } else {
-               sock_drop(psock->sk, skb);
        }
        spin_unlock_bh(&psock->ingress_lock);
 }
 
 static void sk_psock_backlog(struct work_struct *work)
 {
-       struct sk_psock *psock = container_of(work, struct sk_psock, work);
+       struct delayed_work *dwork = to_delayed_work(work);
+       struct sk_psock *psock = container_of(dwork, struct sk_psock, work);
        struct sk_psock_work_state *state = &psock->work_state;
        struct sk_buff *skb = NULL;
+       u32 len = 0, off = 0;
        bool ingress;
-       u32 len, off;
        int ret;
 
        mutex_lock(&psock->work_mutex);
-       if (unlikely(state->skb)) {
-               spin_lock_bh(&psock->ingress_lock);
-               skb = state->skb;
+       if (unlikely(state->len)) {
                len = state->len;
                off = state->off;
-               state->skb = NULL;
-               spin_unlock_bh(&psock->ingress_lock);
        }
-       if (skb)
-               goto start;
 
-       while ((skb = skb_dequeue(&psock->ingress_skb))) {
+       while ((skb = skb_peek(&psock->ingress_skb))) {
                len = skb->len;
                off = 0;
                if (skb_bpf_strparser(skb)) {
@@ -668,7 +657,6 @@ static void sk_psock_backlog(struct work_struct *work)
                        off = stm->offset;
                        len = stm->full_len;
                }
-start:
                ingress = skb_bpf_ingress(skb);
                skb_bpf_redirect_clear(skb);
                do {
@@ -678,22 +666,28 @@ start:
                                                          len, ingress);
                        if (ret <= 0) {
                                if (ret == -EAGAIN) {
-                                       sk_psock_skb_state(psock, state, skb,
-                                                          len, off);
+                                       sk_psock_skb_state(psock, state, len, off);
+
+                                       /* Delay slightly to prioritize any
+                                        * other work that might be here.
+                                        */
+                                       if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED))
+                                               schedule_delayed_work(&psock->work, 1);
                                        goto end;
                                }
                                /* Hard errors break pipe and stop xmit. */
                                sk_psock_report_error(psock, ret ? -ret : EPIPE);
                                sk_psock_clear_state(psock, SK_PSOCK_TX_ENABLED);
-                               sock_drop(psock->sk, skb);
                                goto end;
                        }
                        off += ret;
                        len -= ret;
                } while (len);
 
-               if (!ingress)
+               skb = skb_dequeue(&psock->ingress_skb);
+               if (!ingress) {
                        kfree_skb(skb);
+               }
        }
 end:
        mutex_unlock(&psock->work_mutex);
@@ -734,7 +728,7 @@ struct sk_psock *sk_psock_init(struct sock *sk, int node)
        INIT_LIST_HEAD(&psock->link);
        spin_lock_init(&psock->link_lock);
 
-       INIT_WORK(&psock->work, sk_psock_backlog);
+       INIT_DELAYED_WORK(&psock->work, sk_psock_backlog);
        mutex_init(&psock->work_mutex);
        INIT_LIST_HEAD(&psock->ingress_msg);
        spin_lock_init(&psock->ingress_lock);
@@ -786,11 +780,6 @@ static void __sk_psock_zap_ingress(struct sk_psock *psock)
                skb_bpf_redirect_clear(skb);
                sock_drop(psock->sk, skb);
        }
-       kfree_skb(psock->work_state.skb);
-       /* We null the skb here to ensure that calls to sk_psock_backlog
-        * do not pick up the free'd skb.
-        */
-       psock->work_state.skb = NULL;
        __sk_psock_purge_ingress_msg(psock);
 }
 
@@ -809,7 +798,6 @@ void sk_psock_stop(struct sk_psock *psock)
        spin_lock_bh(&psock->ingress_lock);
        sk_psock_clear_state(psock, SK_PSOCK_TX_ENABLED);
        sk_psock_cork_free(psock);
-       __sk_psock_zap_ingress(psock);
        spin_unlock_bh(&psock->ingress_lock);
 }
 
@@ -823,7 +811,8 @@ static void sk_psock_destroy(struct work_struct *work)
 
        sk_psock_done_strp(psock);
 
-       cancel_work_sync(&psock->work);
+       cancel_delayed_work_sync(&psock->work);
+       __sk_psock_zap_ingress(psock);
        mutex_destroy(&psock->work_mutex);
 
        psock_progs_drop(&psock->progs);
@@ -938,7 +927,7 @@ static int sk_psock_skb_redirect(struct sk_psock *from, struct sk_buff *skb)
        }
 
        skb_queue_tail(&psock_other->ingress_skb, skb);
-       schedule_work(&psock_other->work);
+       schedule_delayed_work(&psock_other->work, 0);
        spin_unlock_bh(&psock_other->ingress_lock);
        return 0;
 }
@@ -990,10 +979,8 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,
                err = -EIO;
                sk_other = psock->sk;
                if (sock_flag(sk_other, SOCK_DEAD) ||
-                   !sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) {
-                       skb_bpf_redirect_clear(skb);
+                   !sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED))
                        goto out_free;
-               }
 
                skb_bpf_set_ingress(skb);
 
@@ -1018,22 +1005,23 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,
                        spin_lock_bh(&psock->ingress_lock);
                        if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) {
                                skb_queue_tail(&psock->ingress_skb, skb);
-                               schedule_work(&psock->work);
+                               schedule_delayed_work(&psock->work, 0);
                                err = 0;
                        }
                        spin_unlock_bh(&psock->ingress_lock);
-                       if (err < 0) {
-                               skb_bpf_redirect_clear(skb);
+                       if (err < 0)
                                goto out_free;
-                       }
                }
                break;
        case __SK_REDIRECT:
+               tcp_eat_skb(psock->sk, skb);
                err = sk_psock_skb_redirect(psock, skb);
                break;
        case __SK_DROP:
        default:
 out_free:
+               skb_bpf_redirect_clear(skb);
+               tcp_eat_skb(psock->sk, skb);
                sock_drop(psock->sk, skb);
        }
 
@@ -1049,7 +1037,7 @@ static void sk_psock_write_space(struct sock *sk)
        psock = sk_psock(sk);
        if (likely(psock)) {
                if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED))
-                       schedule_work(&psock->work);
+                       schedule_delayed_work(&psock->work, 0);
                write_space = psock->saved_write_space;
        }
        rcu_read_unlock();
@@ -1078,8 +1066,7 @@ static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb)
                skb_dst_drop(skb);
                skb_bpf_redirect_clear(skb);
                ret = bpf_prog_run_pin_on_cpu(prog, skb);
-               if (ret == SK_PASS)
-                       skb_bpf_set_strparser(skb);
+               skb_bpf_set_strparser(skb);
                ret = sk_psock_map_verd(ret, skb_bpf_redirect_fetch(skb));
                skb->sk = NULL;
        }
@@ -1183,12 +1170,11 @@ static int sk_psock_verdict_recv(struct sock *sk, struct sk_buff *skb)
        int ret = __SK_DROP;
        int len = skb->len;
 
-       skb_get(skb);
-
        rcu_read_lock();
        psock = sk_psock(sk);
        if (unlikely(!psock)) {
                len = 0;
+               tcp_eat_skb(sk, skb);
                sock_drop(sk, skb);
                goto out;
        }
@@ -1212,12 +1198,21 @@ out:
 static void sk_psock_verdict_data_ready(struct sock *sk)
 {
        struct socket *sock = sk->sk_socket;
+       int copied;
 
        trace_sk_data_ready(sk);
 
        if (unlikely(!sock || !sock->ops || !sock->ops->read_skb))
                return;
-       sock->ops->read_skb(sk, sk_psock_verdict_recv);
+       copied = sock->ops->read_skb(sk, sk_psock_verdict_recv);
+       if (copied >= 0) {
+               struct sk_psock *psock;
+
+               rcu_read_lock();
+               psock = sk_psock(sk);
+               psock->saved_data_ready(sk);
+               rcu_read_unlock();
+       }
 }
 
 void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock)
index 5440e67bcfe3b0874756fd87a9d79ded41c2e4a4..24f2761bdb1d86ac36f7964ad456864db461f20d 100644 (file)
@@ -2381,7 +2381,6 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
 {
        u32 max_segs = 1;
 
-       sk_dst_set(sk, dst);
        sk->sk_route_caps = dst->dev->features;
        if (sk_is_tcp(sk))
                sk->sk_route_caps |= NETIF_F_GSO;
@@ -2400,6 +2399,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
                }
        }
        sk->sk_gso_max_segs = max_segs;
+       sk_dst_set(sk, dst);
 }
 EXPORT_SYMBOL_GPL(sk_setup_caps);
 
index 7c189c2e2fbfd9dbf3268ff6a65908b8b14700ca..00afb66cd095010158c2d49a7bea5a8d88539973 100644 (file)
@@ -1644,9 +1644,10 @@ void sock_map_close(struct sock *sk, long timeout)
                rcu_read_unlock();
                sk_psock_stop(psock);
                release_sock(sk);
-               cancel_work_sync(&psock->work);
+               cancel_delayed_work_sync(&psock->work);
                sk_psock_put(sk, psock);
        }
+
        /* Make sure we do not recurse. This is a bug.
         * Leak the socket instead of crashing on a stack overflow.
         */
index 434446ab14c578b2d4c4c0ff8467c7129f7c66d8..f5c4e47df16505571d575ff367b31d9ef6998bd6 100644 (file)
@@ -73,8 +73,8 @@ int sk_stream_wait_connect(struct sock *sk, long *timeo_p)
                add_wait_queue(sk_sleep(sk), &wait);
                sk->sk_write_pending++;
                done = sk_wait_event(sk, timeo_p,
-                                    !sk->sk_err &&
-                                    !((1 << sk->sk_state) &
+                                    !READ_ONCE(sk->sk_err) &&
+                                    !((1 << READ_ONCE(sk->sk_state)) &
                                       ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)), &wait);
                remove_wait_queue(sk_sleep(sk), &wait);
                sk->sk_write_pending--;
@@ -87,9 +87,9 @@ EXPORT_SYMBOL(sk_stream_wait_connect);
  * sk_stream_closing - Return 1 if we still have things to send in our buffers.
  * @sk: socket to verify
  */
-static inline int sk_stream_closing(struct sock *sk)
+static int sk_stream_closing(const struct sock *sk)
 {
-       return (1 << sk->sk_state) &
+       return (1 << READ_ONCE(sk->sk_state)) &
               (TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_LAST_ACK);
 }
 
@@ -142,8 +142,8 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
 
                set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
                sk->sk_write_pending++;
-               sk_wait_event(sk, &current_timeo, sk->sk_err ||
-                                                 (sk->sk_shutdown & SEND_SHUTDOWN) ||
+               sk_wait_event(sk, &current_timeo, READ_ONCE(sk->sk_err) ||
+                                                 (READ_ONCE(sk->sk_shutdown) & SEND_SHUTDOWN) ||
                                                  (sk_stream_memory_free(sk) &&
                                                  !vm_wait), &wait);
                sk->sk_write_pending--;
index 777b091ef74dff37b14f60e977df077044cb4280..c23ebabadc526e742b7f27f4c383ac7e3f5d62f2 100644 (file)
@@ -204,11 +204,6 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
        if (ret < 0)
                goto err_xa_alloc;
 
-       devlink->netdevice_nb.notifier_call = devlink_port_netdevice_event;
-       ret = register_netdevice_notifier(&devlink->netdevice_nb);
-       if (ret)
-               goto err_register_netdevice_notifier;
-
        devlink->dev = dev;
        devlink->ops = ops;
        xa_init_flags(&devlink->ports, XA_FLAGS_ALLOC);
@@ -233,8 +228,6 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
 
        return devlink;
 
-err_register_netdevice_notifier:
-       xa_erase(&devlinks, devlink->index);
 err_xa_alloc:
        kfree(devlink);
        return NULL;
@@ -266,8 +259,6 @@ void devlink_free(struct devlink *devlink)
        xa_destroy(&devlink->params);
        xa_destroy(&devlink->ports);
 
-       WARN_ON_ONCE(unregister_netdevice_notifier(&devlink->netdevice_nb));
-
        xa_erase(&devlinks, devlink->index);
 
        devlink_put(devlink);
@@ -303,6 +294,10 @@ static struct pernet_operations devlink_pernet_ops __net_initdata = {
        .pre_exit = devlink_pernet_pre_exit,
 };
 
+static struct notifier_block devlink_port_netdevice_nb = {
+       .notifier_call = devlink_port_netdevice_event,
+};
+
 static int __init devlink_init(void)
 {
        int err;
@@ -311,6 +306,9 @@ static int __init devlink_init(void)
        if (err)
                goto out;
        err = register_pernet_subsys(&devlink_pernet_ops);
+       if (err)
+               goto out;
+       err = register_netdevice_notifier(&devlink_port_netdevice_nb);
 
 out:
        WARN_ON(err);
index e133f423294a22f34e15e166617d7b886543fa90..62921b2eb0d3fadd113847e38c9ef3152be7ed3b 100644 (file)
@@ -50,7 +50,6 @@ struct devlink {
        u8 reload_failed:1;
        refcount_t refcount;
        struct rcu_work rwork;
-       struct notifier_block netdevice_nb;
        char priv[] __aligned(NETDEV_ALIGN);
 };
 
index dffca2f9bfa7ff0a6982ba33b577e1e3f3d6c727..cd025496807677346798443d8036d08c029f6ba5 100644 (file)
@@ -7073,10 +7073,9 @@ int devlink_port_netdevice_event(struct notifier_block *nb,
        struct devlink_port *devlink_port = netdev->devlink_port;
        struct devlink *devlink;
 
-       devlink = container_of(nb, struct devlink, netdevice_nb);
-
-       if (!devlink_port || devlink_port->devlink != devlink)
+       if (!devlink_port)
                return NOTIFY_OK;
+       devlink = devlink_port->devlink;
 
        switch (event) {
        case NETDEV_POST_INIT:
index e6adc5dec11a72cdc893ebbda4c97f823a1fd9ee..6d37bab35c8fcc42e77d1fc081a87d61658751c3 100644 (file)
@@ -102,7 +102,7 @@ struct handshake_req_alloc_test_param handshake_req_alloc_params[] = {
        {
                .desc                   = "handshake_req_alloc excessive privsize",
                .proto                  = &handshake_req_alloc_proto_6,
-               .gfp                    = GFP_KERNEL,
+               .gfp                    = GFP_KERNEL | __GFP_NOWARN,
                .expect_success         = false,
        },
        {
@@ -209,6 +209,7 @@ static void handshake_req_submit_test4(struct kunit *test)
 {
        struct handshake_req *req, *result;
        struct socket *sock;
+       struct file *filp;
        int err;
 
        /* Arrange */
@@ -218,9 +219,10 @@ static void handshake_req_submit_test4(struct kunit *test)
        err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP,
                            &sock, 1);
        KUNIT_ASSERT_EQ(test, err, 0);
-       sock->file = sock_alloc_file(sock, O_NONBLOCK, NULL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sock->file);
+       filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp);
        KUNIT_ASSERT_NOT_NULL(test, sock->sk);
+       sock->file = filp;
 
        err = handshake_req_submit(sock, req, GFP_KERNEL);
        KUNIT_ASSERT_EQ(test, err, 0);
@@ -241,6 +243,7 @@ static void handshake_req_submit_test5(struct kunit *test)
        struct handshake_req *req;
        struct handshake_net *hn;
        struct socket *sock;
+       struct file *filp;
        struct net *net;
        int saved, err;
 
@@ -251,9 +254,10 @@ static void handshake_req_submit_test5(struct kunit *test)
        err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP,
                            &sock, 1);
        KUNIT_ASSERT_EQ(test, err, 0);
-       sock->file = sock_alloc_file(sock, O_NONBLOCK, NULL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sock->file);
+       filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp);
        KUNIT_ASSERT_NOT_NULL(test, sock->sk);
+       sock->file = filp;
 
        net = sock_net(sock->sk);
        hn = handshake_pernet(net);
@@ -276,6 +280,7 @@ static void handshake_req_submit_test6(struct kunit *test)
 {
        struct handshake_req *req1, *req2;
        struct socket *sock;
+       struct file *filp;
        int err;
 
        /* Arrange */
@@ -287,9 +292,10 @@ static void handshake_req_submit_test6(struct kunit *test)
        err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP,
                            &sock, 1);
        KUNIT_ASSERT_EQ(test, err, 0);
-       sock->file = sock_alloc_file(sock, O_NONBLOCK, NULL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sock->file);
+       filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp);
        KUNIT_ASSERT_NOT_NULL(test, sock->sk);
+       sock->file = filp;
 
        /* Act */
        err = handshake_req_submit(sock, req1, GFP_KERNEL);
@@ -307,6 +313,7 @@ static void handshake_req_cancel_test1(struct kunit *test)
 {
        struct handshake_req *req;
        struct socket *sock;
+       struct file *filp;
        bool result;
        int err;
 
@@ -318,8 +325,9 @@ static void handshake_req_cancel_test1(struct kunit *test)
                            &sock, 1);
        KUNIT_ASSERT_EQ(test, err, 0);
 
-       sock->file = sock_alloc_file(sock, O_NONBLOCK, NULL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sock->file);
+       filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp);
+       sock->file = filp;
 
        err = handshake_req_submit(sock, req, GFP_KERNEL);
        KUNIT_ASSERT_EQ(test, err, 0);
@@ -340,6 +348,7 @@ static void handshake_req_cancel_test2(struct kunit *test)
        struct handshake_req *req, *next;
        struct handshake_net *hn;
        struct socket *sock;
+       struct file *filp;
        struct net *net;
        bool result;
        int err;
@@ -352,8 +361,9 @@ static void handshake_req_cancel_test2(struct kunit *test)
                            &sock, 1);
        KUNIT_ASSERT_EQ(test, err, 0);
 
-       sock->file = sock_alloc_file(sock, O_NONBLOCK, NULL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sock->file);
+       filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp);
+       sock->file = filp;
 
        err = handshake_req_submit(sock, req, GFP_KERNEL);
        KUNIT_ASSERT_EQ(test, err, 0);
@@ -380,6 +390,7 @@ static void handshake_req_cancel_test3(struct kunit *test)
        struct handshake_req *req, *next;
        struct handshake_net *hn;
        struct socket *sock;
+       struct file *filp;
        struct net *net;
        bool result;
        int err;
@@ -392,8 +403,9 @@ static void handshake_req_cancel_test3(struct kunit *test)
                            &sock, 1);
        KUNIT_ASSERT_EQ(test, err, 0);
 
-       sock->file = sock_alloc_file(sock, O_NONBLOCK, NULL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sock->file);
+       filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp);
+       sock->file = filp;
 
        err = handshake_req_submit(sock, req, GFP_KERNEL);
        KUNIT_ASSERT_EQ(test, err, 0);
@@ -436,6 +448,7 @@ static void handshake_req_destroy_test1(struct kunit *test)
 {
        struct handshake_req *req;
        struct socket *sock;
+       struct file *filp;
        int err;
 
        /* Arrange */
@@ -448,8 +461,9 @@ static void handshake_req_destroy_test1(struct kunit *test)
                            &sock, 1);
        KUNIT_ASSERT_EQ(test, err, 0);
 
-       sock->file = sock_alloc_file(sock, O_NONBLOCK, NULL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sock->file);
+       filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp);
+       sock->file = filp;
 
        err = handshake_req_submit(sock, req, GFP_KERNEL);
        KUNIT_ASSERT_EQ(test, err, 0);
index 4dac965c99df0b65c92bf83a830d55c78e85ba9b..8aeaadca844fdc0de6fd1683d493907f5e6506b7 100644 (file)
@@ -31,6 +31,7 @@ struct handshake_req {
        struct list_head                hr_list;
        struct rhash_head               hr_rhash;
        unsigned long                   hr_flags;
+       struct file                     *hr_file;
        const struct handshake_proto    *hr_proto;
        struct sock                     *hr_sk;
        void                            (*hr_odestruct)(struct sock *sk);
index 35c9c445e0b850d8effb2f362f70306c7f1f2dd6..1086653e1fada1724f98ccbc81fbcf7741ef9bc9 100644 (file)
@@ -48,7 +48,7 @@ int handshake_genl_notify(struct net *net, const struct handshake_proto *proto,
                                proto->hp_handler_class))
                return -ESRCH;
 
-       msg = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
+       msg = genlmsg_new(GENLMSG_DEFAULT_SIZE, flags);
        if (!msg)
                return -ENOMEM;
 
@@ -99,9 +99,6 @@ static int handshake_dup(struct socket *sock)
        struct file *file;
        int newfd;
 
-       if (!sock->file)
-               return -EBADF;
-
        file = get_file(sock->file);
        newfd = get_unused_fd_flags(O_CLOEXEC);
        if (newfd < 0) {
@@ -142,15 +139,16 @@ int handshake_nl_accept_doit(struct sk_buff *skb, struct genl_info *info)
                goto out_complete;
        }
        err = req->hr_proto->hp_accept(req, info, fd);
-       if (err)
+       if (err) {
+               fput(sock->file);
                goto out_complete;
+       }
 
        trace_handshake_cmd_accept(net, req, req->hr_sk, fd);
        return 0;
 
 out_complete:
        handshake_complete(req, -EIO, NULL);
-       fput(sock->file);
 out_status:
        trace_handshake_cmd_accept_err(net, req, NULL, err);
        return err;
@@ -159,8 +157,8 @@ out_status:
 int handshake_nl_done_doit(struct sk_buff *skb, struct genl_info *info)
 {
        struct net *net = sock_net(skb->sk);
+       struct handshake_req *req = NULL;
        struct socket *sock = NULL;
-       struct handshake_req *req;
        int fd, status, err;
 
        if (GENL_REQ_ATTR_CHECK(info, HANDSHAKE_A_DONE_SOCKFD))
index 94d5cef3e048b7fec001c6bd32c917e778834e96..d78d41abb3d993b31f9a7e64e6efa17263ea132b 100644 (file)
@@ -239,6 +239,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
        }
        req->hr_odestruct = req->hr_sk->sk_destruct;
        req->hr_sk->sk_destruct = handshake_sk_destruct;
+       req->hr_file = sock->file;
 
        ret = -EOPNOTSUPP;
        net = sock_net(req->hr_sk);
@@ -334,6 +335,9 @@ bool handshake_req_cancel(struct sock *sk)
                return false;
        }
 
+       /* Request accepted and waiting for DONE */
+       fput(req->hr_file);
+
 out_true:
        trace_handshake_cancel(net, req, sk);
 
index fcbeb63b4eb16bd4345fc16170e0ad093deae803..b735f5cced2f5e68731072bcf30f050c5e5c52fc 100644 (file)
@@ -31,6 +31,7 @@ struct tls_handshake_req {
        int                     th_type;
        unsigned int            th_timeout_ms;
        int                     th_auth_mode;
+       const char              *th_peername;
        key_serial_t            th_keyring;
        key_serial_t            th_certificate;
        key_serial_t            th_privkey;
@@ -48,6 +49,7 @@ tls_handshake_req_init(struct handshake_req *req,
        treq->th_timeout_ms = args->ta_timeout_ms;
        treq->th_consumer_done = args->ta_done;
        treq->th_consumer_data = args->ta_data;
+       treq->th_peername = args->ta_peername;
        treq->th_keyring = args->ta_keyring;
        treq->th_num_peerids = 0;
        treq->th_certificate = TLS_NO_CERT;
@@ -214,6 +216,12 @@ static int tls_handshake_accept(struct handshake_req *req,
        ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_MESSAGE_TYPE, treq->th_type);
        if (ret < 0)
                goto out_cancel;
+       if (treq->th_peername) {
+               ret = nla_put_string(msg, HANDSHAKE_A_ACCEPT_PEERNAME,
+                                    treq->th_peername);
+               if (ret < 0)
+                       goto out_cancel;
+       }
        if (treq->th_timeout_ms) {
                ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_TIMEOUT, treq->th_timeout_ms);
                if (ret < 0)
index 940062e08f574fbfeed42f72fa8a4b5ce763110c..4a76ebf793b857f5e64d440870d3cca737d1dac2 100644 (file)
@@ -586,6 +586,7 @@ static long inet_wait_for_connect(struct sock *sk, long timeo, int writebias)
 
        add_wait_queue(sk_sleep(sk), &wait);
        sk->sk_write_pending += writebias;
+       sk->sk_wait_pending++;
 
        /* Basic assumption: if someone sets sk->sk_err, he _must_
         * change state of the socket from TCP_SYN_*.
@@ -601,6 +602,7 @@ static long inet_wait_for_connect(struct sock *sk, long timeo, int writebias)
        }
        remove_wait_queue(sk_sleep(sk), &wait);
        sk->sk_write_pending -= writebias;
+       sk->sk_wait_pending--;
        return timeo;
 }
 
@@ -894,7 +896,7 @@ int inet_shutdown(struct socket *sock, int how)
                   EPOLLHUP, even on eg. unconnected UDP sockets -- RR */
                fallthrough;
        default:
-               sk->sk_shutdown |= how;
+               WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | how);
                if (sk->sk_prot->shutdown)
                        sk->sk_prot->shutdown(sk, how);
                break;
index 65ad4251f6fd849c7aeb0d981dc337111fb246b0..1386787eaf1a53e2d1364f3782a68dd2206bde9d 100644 (file)
@@ -1142,6 +1142,7 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,
        if (newsk) {
                struct inet_connection_sock *newicsk = inet_csk(newsk);
 
+               newsk->sk_wait_pending = 0;
                inet_sk_set_state(newsk, TCP_SYN_RECV);
                newicsk->icsk_bind_hash = NULL;
                newicsk->icsk_bind2_hash = NULL;
index b511ff0adc0aa2f3eb6eac105f050fc1d46acb5c..8e97d8d4cc9d910a0cc29897be4820b53b019433 100644 (file)
@@ -317,7 +317,14 @@ int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc,
                        ipc->tos = val;
                        ipc->priority = rt_tos2priority(ipc->tos);
                        break;
-
+               case IP_PROTOCOL:
+                       if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)))
+                               return -EINVAL;
+                       val = *(int *)CMSG_DATA(cmsg);
+                       if (val < 1 || val > 255)
+                               return -EINVAL;
+                       ipc->protocol = val;
+                       break;
                default:
                        return -EINVAL;
                }
@@ -1761,6 +1768,9 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
        case IP_LOCAL_PORT_RANGE:
                val = inet->local_port_range.hi << 16 | inet->local_port_range.lo;
                break;
+       case IP_PROTOCOL:
+               val = inet_sk(sk)->inet_num;
+               break;
        default:
                sockopt_release_sock(sk);
                return -ENOPROTOOPT;
index ff712bf2a98d18289ec6b10482c2767d0ee19fbd..eadf1c9ef7e493e5466cfef2fb1f83df7bb088f5 100644 (file)
@@ -532,6 +532,9 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        }
 
        ipcm_init_sk(&ipc, inet);
+       /* Keep backward compat */
+       if (hdrincl)
+               ipc.protocol = IPPROTO_RAW;
 
        if (msg->msg_controllen) {
                err = ip_cmsg_send(sk, msg, &ipc, false);
@@ -599,7 +602,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
        flowi4_init_output(&fl4, ipc.oif, ipc.sockc.mark, tos,
                           RT_SCOPE_UNIVERSE,
-                          hdrincl ? IPPROTO_RAW : sk->sk_protocol,
+                          hdrincl ? ipc.protocol : sk->sk_protocol,
                           inet_sk_flowi_flags(sk) |
                            (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
                           daddr, saddr, 0, 0, sk->sk_uid);
index 20db115c38c492c010733d5a0a3efbb7dbbea13e..8d20d9221238cac81b84aa5c6267d20a13bc23a6 100644 (file)
@@ -498,6 +498,7 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
        __poll_t mask;
        struct sock *sk = sock->sk;
        const struct tcp_sock *tp = tcp_sk(sk);
+       u8 shutdown;
        int state;
 
        sock_poll_wait(file, sock, wait);
@@ -540,9 +541,10 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
         * NOTE. Check for TCP_CLOSE is added. The goal is to prevent
         * blocking on fresh not-connected or disconnected socket. --ANK
         */
-       if (sk->sk_shutdown == SHUTDOWN_MASK || state == TCP_CLOSE)
+       shutdown = READ_ONCE(sk->sk_shutdown);
+       if (shutdown == SHUTDOWN_MASK || state == TCP_CLOSE)
                mask |= EPOLLHUP;
-       if (sk->sk_shutdown & RCV_SHUTDOWN)
+       if (shutdown & RCV_SHUTDOWN)
                mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
 
        /* Connected or passive Fast Open socket? */
@@ -559,7 +561,7 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
                if (tcp_stream_is_readable(sk, target))
                        mask |= EPOLLIN | EPOLLRDNORM;
 
-               if (!(sk->sk_shutdown & SEND_SHUTDOWN)) {
+               if (!(shutdown & SEND_SHUTDOWN)) {
                        if (__sk_stream_is_writeable(sk, 1)) {
                                mask |= EPOLLOUT | EPOLLWRNORM;
                        } else {  /* send SIGIO later */
@@ -1569,7 +1571,7 @@ static int tcp_peek_sndq(struct sock *sk, struct msghdr *msg, int len)
  * calculation of whether or not we must ACK for the sake of
  * a window update.
  */
-static void __tcp_cleanup_rbuf(struct sock *sk, int copied)
+void __tcp_cleanup_rbuf(struct sock *sk, int copied)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        bool time_to_ack = false;
@@ -1771,7 +1773,6 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
                WARN_ON_ONCE(!skb_set_owner_sk_safe(skb, sk));
                tcp_flags = TCP_SKB_CB(skb)->tcp_flags;
                used = recv_actor(sk, skb);
-               consume_skb(skb);
                if (used < 0) {
                        if (!copied)
                                copied = used;
@@ -1785,14 +1786,6 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
                        break;
                }
        }
-       WRITE_ONCE(tp->copied_seq, seq);
-
-       tcp_rcv_space_adjust(sk);
-
-       /* Clean up data we have read: This will do ACK frames. */
-       if (copied > 0)
-               __tcp_cleanup_rbuf(sk, copied);
-
        return copied;
 }
 EXPORT_SYMBOL(tcp_read_skb);
@@ -2867,7 +2860,7 @@ void __tcp_close(struct sock *sk, long timeout)
        int data_was_unread = 0;
        int state;
 
-       sk->sk_shutdown = SHUTDOWN_MASK;
+       WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);
 
        if (sk->sk_state == TCP_LISTEN) {
                tcp_set_state(sk, TCP_CLOSE);
@@ -3088,6 +3081,12 @@ int tcp_disconnect(struct sock *sk, int flags)
        int old_state = sk->sk_state;
        u32 seq;
 
+       /* Deny disconnect if other threads are blocked in sk_wait_event()
+        * or inet_wait_for_connect().
+        */
+       if (sk->sk_wait_pending)
+               return -EBUSY;
+
        if (old_state != TCP_CLOSE)
                tcp_set_state(sk, TCP_CLOSE);
 
@@ -3119,7 +3118,7 @@ int tcp_disconnect(struct sock *sk, int flags)
 
        inet_bhash2_reset_saddr(sk);
 
-       sk->sk_shutdown = 0;
+       WRITE_ONCE(sk->sk_shutdown, 0);
        sock_reset_flag(sk, SOCK_DONE);
        tp->srtt_us = 0;
        tp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT);
@@ -4079,7 +4078,8 @@ int do_tcp_getsockopt(struct sock *sk, int level,
        switch (optname) {
        case TCP_MAXSEG:
                val = tp->mss_cache;
-               if (!val && ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)))
+               if (tp->rx_opt.user_mss &&
+                   ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)))
                        val = tp->rx_opt.user_mss;
                if (tp->repair)
                        val = tp->rx_opt.mss_clamp;
@@ -4649,7 +4649,7 @@ void tcp_done(struct sock *sk)
        if (req)
                reqsk_fastopen_remove(sk, req, false);
 
-       sk->sk_shutdown = SHUTDOWN_MASK;
+       WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);
 
        if (!sock_flag(sk, SOCK_DEAD))
                sk->sk_state_change(sk);
index ebf91751193706ccec1bb9cfac48be28b5e28337..5f93918c063c72435027055d95c70ca25432844e 100644 (file)
 #include <net/inet_common.h>
 #include <net/tls.h>
 
+void tcp_eat_skb(struct sock *sk, struct sk_buff *skb)
+{
+       struct tcp_sock *tcp;
+       int copied;
+
+       if (!skb || !skb->len || !sk_is_tcp(sk))
+               return;
+
+       if (skb_bpf_strparser(skb))
+               return;
+
+       tcp = tcp_sk(sk);
+       copied = tcp->copied_seq + skb->len;
+       WRITE_ONCE(tcp->copied_seq, copied);
+       tcp_rcv_space_adjust(sk);
+       __tcp_cleanup_rbuf(sk, skb->len);
+}
+
 static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock,
                           struct sk_msg *msg, u32 apply_bytes, int flags)
 {
@@ -168,20 +186,40 @@ static int tcp_msg_wait_data(struct sock *sk, struct sk_psock *psock,
        sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
        ret = sk_wait_event(sk, &timeo,
                            !list_empty(&psock->ingress_msg) ||
-                           !skb_queue_empty(&sk->sk_receive_queue), &wait);
+                           !skb_queue_empty_lockless(&sk->sk_receive_queue), &wait);
        sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
        remove_wait_queue(sk_sleep(sk), &wait);
        return ret;
 }
 
+static bool is_next_msg_fin(struct sk_psock *psock)
+{
+       struct scatterlist *sge;
+       struct sk_msg *msg_rx;
+       int i;
+
+       msg_rx = sk_psock_peek_msg(psock);
+       i = msg_rx->sg.start;
+       sge = sk_msg_elem(msg_rx, i);
+       if (!sge->length) {
+               struct sk_buff *skb = msg_rx->skb;
+
+               if (skb && TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
+                       return true;
+       }
+       return false;
+}
+
 static int tcp_bpf_recvmsg_parser(struct sock *sk,
                                  struct msghdr *msg,
                                  size_t len,
                                  int flags,
                                  int *addr_len)
 {
+       struct tcp_sock *tcp = tcp_sk(sk);
+       u32 seq = tcp->copied_seq;
        struct sk_psock *psock;
-       int copied;
+       int copied = 0;
 
        if (unlikely(flags & MSG_ERRQUEUE))
                return inet_recv_error(sk, msg, len, addr_len);
@@ -194,8 +232,43 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
                return tcp_recvmsg(sk, msg, len, flags, addr_len);
 
        lock_sock(sk);
+
+       /* We may have received data on the sk_receive_queue pre-accept and
+        * then we can not use read_skb in this context because we haven't
+        * assigned a sk_socket yet so have no link to the ops. The work-around
+        * is to check the sk_receive_queue and in these cases read skbs off
+        * queue again. The read_skb hook is not running at this point because
+        * of lock_sock so we avoid having multiple runners in read_skb.
+        */
+       if (unlikely(!skb_queue_empty(&sk->sk_receive_queue))) {
+               tcp_data_ready(sk);
+               /* This handles the ENOMEM errors if we both receive data
+                * pre accept and are already under memory pressure. At least
+                * let user know to retry.
+                */
+               if (unlikely(!skb_queue_empty(&sk->sk_receive_queue))) {
+                       copied = -EAGAIN;
+                       goto out;
+               }
+       }
+
 msg_bytes_ready:
        copied = sk_msg_recvmsg(sk, psock, msg, len, flags);
+       /* The typical case for EFAULT is the socket was gracefully
+        * shutdown with a FIN pkt. So check here the other case is
+        * some error on copy_page_to_iter which would be unexpected.
+        * On fin return correct return code to zero.
+        */
+       if (copied == -EFAULT) {
+               bool is_fin = is_next_msg_fin(psock);
+
+               if (is_fin) {
+                       copied = 0;
+                       seq++;
+                       goto out;
+               }
+       }
+       seq += copied;
        if (!copied) {
                long timeo;
                int data;
@@ -233,6 +306,10 @@ msg_bytes_ready:
                copied = -EAGAIN;
        }
 out:
+       WRITE_ONCE(tcp->copied_seq, seq);
+       tcp_rcv_space_adjust(sk);
+       if (copied > 0)
+               __tcp_cleanup_rbuf(sk, copied);
        release_sock(sk);
        sk_psock_put(sk, psock);
        return copied;
index a057330d6f59d693cdf634dbd22f1243f8171f58..bf8b22218dd468632ee39826f9be57abea5018dc 100644 (file)
@@ -4362,7 +4362,7 @@ void tcp_fin(struct sock *sk)
 
        inet_csk_schedule_ack(sk);
 
-       sk->sk_shutdown |= RCV_SHUTDOWN;
+       WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | RCV_SHUTDOWN);
        sock_set_flag(sk, SOCK_DONE);
 
        switch (sk->sk_state) {
@@ -4530,7 +4530,7 @@ static void tcp_sack_maybe_coalesce(struct tcp_sock *tp)
        }
 }
 
-static void tcp_sack_compress_send_ack(struct sock *sk)
+void tcp_sack_compress_send_ack(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
 
@@ -6599,7 +6599,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
                        break;
 
                tcp_set_state(sk, TCP_FIN_WAIT2);
-               sk->sk_shutdown |= SEND_SHUTDOWN;
+               WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | SEND_SHUTDOWN);
 
                sk_dst_confirm(sk);
 
index 39bda2b1066e1d607a59fb79c6305d0ca30cb28d..06d2573685ca993a3a0a89807f09d7b5c153cc72 100644 (file)
@@ -829,6 +829,9 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
                                   inet_twsk(sk)->tw_priority : sk->sk_priority;
                transmit_time = tcp_transmit_time(sk);
                xfrm_sk_clone_policy(ctl_sk, sk);
+       } else {
+               ctl_sk->sk_mark = 0;
+               ctl_sk->sk_priority = 0;
        }
        ip_send_unicast_reply(ctl_sk,
                              skb, &TCP_SKB_CB(skb)->header.h4.opt,
@@ -836,7 +839,6 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
                              &arg, arg.iov[0].iov_len,
                              transmit_time);
 
-       ctl_sk->sk_mark = 0;
        xfrm_sk_free_policy(ctl_sk);
        sock_net_set(ctl_sk, &init_net);
        __TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
@@ -935,7 +937,6 @@ static void tcp_v4_send_ack(const struct sock *sk,
                              &arg, arg.iov[0].iov_len,
                              transmit_time);
 
-       ctl_sk->sk_mark = 0;
        sock_net_set(ctl_sk, &init_net);
        __TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
        local_bh_enable();
index b839c2f91292f7346f33d6dcbf597594473a5aca..39eb947fe3920f7bb21385842089cbbbfbf6dbbd 100644 (file)
@@ -290,9 +290,19 @@ static int tcp_write_timeout(struct sock *sk)
 void tcp_delack_timer_handler(struct sock *sk)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
+       struct tcp_sock *tp = tcp_sk(sk);
 
-       if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) ||
-           !(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
+       if ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))
+               return;
+
+       /* Handling the sack compression case */
+       if (tp->compressed_ack) {
+               tcp_mstamp_refresh(tp);
+               tcp_sack_compress_send_ack(sk);
+               return;
+       }
+
+       if (!(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
                return;
 
        if (time_after(icsk->icsk_ack.timeout, jiffies)) {
@@ -312,7 +322,7 @@ void tcp_delack_timer_handler(struct sock *sk)
                        inet_csk_exit_pingpong_mode(sk);
                        icsk->icsk_ack.ato      = TCP_ATO_MIN;
                }
-               tcp_mstamp_refresh(tcp_sk(sk));
+               tcp_mstamp_refresh(tp);
                tcp_send_ack(sk);
                __NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKS);
        }
index aa32afd871ee50968f7bb8152401be60dece1454..9482def1f310379efde1a1a8c86999b4b826cf17 100644 (file)
@@ -1818,7 +1818,7 @@ EXPORT_SYMBOL(__skb_recv_udp);
 int udp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
 {
        struct sk_buff *skb;
-       int err, copied;
+       int err;
 
 try_again:
        skb = skb_recv_udp(sk, MSG_DONTWAIT, &err);
@@ -1837,10 +1837,7 @@ try_again:
        }
 
        WARN_ON_ONCE(!skb_set_owner_sk_safe(skb, sk));
-       copied = recv_actor(sk, skb);
-       kfree_skb(skb);
-
-       return copied;
+       return recv_actor(sk, skb);
 }
 EXPORT_SYMBOL(udp_read_skb);
 
index e0c9cc39b81e38df3f83d22a886b2f793c7b732b..56d94d23b9e0feb241bc58d80031cea50112f35a 100644 (file)
@@ -64,6 +64,8 @@ struct proto  udplite_prot = {
        .per_cpu_fw_alloc  = &udp_memory_per_cpu_fw_alloc,
 
        .sysctl_mem        = sysctl_udp_mem,
+       .sysctl_wmem_offset = offsetof(struct net, ipv4.sysctl_udp_wmem_min),
+       .sysctl_rmem_offset = offsetof(struct net, ipv4.sysctl_udp_rmem_min),
        .obj_size          = sizeof(struct udp_sock),
        .h.udp_table       = &udplite_table,
 };
index da46c42846765b1821f03519f7d57c7fdb0b9e69..49e31e4ae7b7f661d555e73e0515983e9584eec4 100644 (file)
@@ -143,6 +143,8 @@ int ipv6_find_tlv(const struct sk_buff *skb, int offset, int type)
                        optlen = 1;
                        break;
                default:
+                       if (len < 2)
+                               goto bad;
                        optlen = nh[offset + 1] + 2;
                        if (optlen > len)
                                goto bad;
index 2438da5ff6da810d9f612fc66df4d28510f50f10..bac768d36cc19fbaa2ac80be42c15388180bacb3 100644 (file)
@@ -2491,7 +2491,7 @@ static int ipv6_route_native_seq_show(struct seq_file *seq, void *v)
        const struct net_device *dev;
 
        if (rt->nh)
-               fib6_nh = nexthop_fib6_nh_bh(rt->nh);
+               fib6_nh = nexthop_fib6_nh(rt->nh);
 
        seq_printf(seq, "%pi6 %02x ", &rt->fib6_dst.addr, rt->fib6_dst.plen);
 
@@ -2556,14 +2556,14 @@ static struct fib6_table *ipv6_route_seq_next_table(struct fib6_table *tbl,
 
        if (tbl) {
                h = (tbl->tb6_id & (FIB6_TABLE_HASHSZ - 1)) + 1;
-               node = rcu_dereference_bh(hlist_next_rcu(&tbl->tb6_hlist));
+               node = rcu_dereference(hlist_next_rcu(&tbl->tb6_hlist));
        } else {
                h = 0;
                node = NULL;
        }
 
        while (!node && h < FIB6_TABLE_HASHSZ) {
-               node = rcu_dereference_bh(
+               node = rcu_dereference(
                        hlist_first_rcu(&net->ipv6.fib_table_hash[h++]));
        }
        return hlist_entry_safe(node, struct fib6_table, tb6_hlist);
@@ -2593,7 +2593,7 @@ static void *ipv6_route_seq_next(struct seq_file *seq, void *v, loff_t *pos)
        if (!v)
                goto iter_table;
 
-       n = rcu_dereference_bh(((struct fib6_info *)v)->fib6_next);
+       n = rcu_dereference(((struct fib6_info *)v)->fib6_next);
        if (n)
                return n;
 
@@ -2619,12 +2619,12 @@ iter_table:
 }
 
 static void *ipv6_route_seq_start(struct seq_file *seq, loff_t *pos)
-       __acquires(RCU_BH)
+       __acquires(RCU)
 {
        struct net *net = seq_file_net(seq);
        struct ipv6_route_iter *iter = seq->private;
 
-       rcu_read_lock_bh();
+       rcu_read_lock();
        iter->tbl = ipv6_route_seq_next_table(NULL, net);
        iter->skip = *pos;
 
@@ -2645,7 +2645,7 @@ static bool ipv6_route_iter_active(struct ipv6_route_iter *iter)
 }
 
 static void ipv6_route_native_seq_stop(struct seq_file *seq, void *v)
-       __releases(RCU_BH)
+       __releases(RCU)
 {
        struct net *net = seq_file_net(seq);
        struct ipv6_route_iter *iter = seq->private;
@@ -2653,7 +2653,7 @@ static void ipv6_route_native_seq_stop(struct seq_file *seq, void *v)
        if (ipv6_route_iter_active(iter))
                fib6_walker_unlink(net, &iter->w);
 
-       rcu_read_unlock_bh();
+       rcu_read_unlock();
 }
 
 #if IS_BUILTIN(CONFIG_IPV6) && defined(CONFIG_BPF_SYSCALL)
index a4ecfc9d25930967a6af7bd9de9aa52bfd08730d..da80974ad23aeb9751e325b28f0dc293f48bf6a1 100644 (file)
@@ -1015,12 +1015,14 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
                                            ntohl(tun_id),
                                            ntohl(md->u.index), truncate,
                                            false);
+                       proto = htons(ETH_P_ERSPAN);
                } else if (md->version == 2) {
                        erspan_build_header_v2(skb,
                                               ntohl(tun_id),
                                               md->u.md2.dir,
                                               get_hwid(&md->u.md2),
                                               truncate, false);
+                       proto = htons(ETH_P_ERSPAN2);
                } else {
                        goto tx_err;
                }
@@ -1043,24 +1045,25 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
                        break;
                }
 
-               if (t->parms.erspan_ver == 1)
+               if (t->parms.erspan_ver == 1) {
                        erspan_build_header(skb, ntohl(t->parms.o_key),
                                            t->parms.index,
                                            truncate, false);
-               else if (t->parms.erspan_ver == 2)
+                       proto = htons(ETH_P_ERSPAN);
+               } else if (t->parms.erspan_ver == 2) {
                        erspan_build_header_v2(skb, ntohl(t->parms.o_key),
                                               t->parms.dir,
                                               t->parms.hwid,
                                               truncate, false);
-               else
+                       proto = htons(ETH_P_ERSPAN2);
+               } else {
                        goto tx_err;
+               }
 
                fl6.daddr = t->parms.raddr;
        }
 
        /* Push GRE header. */
-       proto = (t->parms.erspan_ver == 1) ? htons(ETH_P_ERSPAN)
-                                          : htons(ETH_P_ERSPAN2);
        gre_build_header(skb, 8, TUNNEL_SEQ, proto, 0, htonl(atomic_fetch_inc(&t->o_seqno)));
 
        /* TooBig packet may have updated dst->dev's mtu */
index 7d0adb612bdd068d3e0543e2206be96209871847..44ee7a2e72ac27f7e4c52c944f0e3e9f63a9e37b 100644 (file)
@@ -793,7 +793,8 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
                if (!proto)
                        proto = inet->inet_num;
-               else if (proto != inet->inet_num)
+               else if (proto != inet->inet_num &&
+                        inet->inet_num != IPPROTO_RAW)
                        return -EINVAL;
 
                if (proto > 255)
index 67eaf3ca14cea71fad76d88414483c0d1d2321b9..3bab0cc1369770028b1b7ecae9bfab0957df1f83 100644 (file)
@@ -60,6 +60,8 @@ struct proto udplitev6_prot = {
        .per_cpu_fw_alloc  = &udp_memory_per_cpu_fw_alloc,
 
        .sysctl_mem        = sysctl_udp_mem,
+       .sysctl_wmem_offset = offsetof(struct net, ipv4.sysctl_udp_wmem_min),
+       .sysctl_rmem_offset = offsetof(struct net, ipv4.sysctl_udp_rmem_min),
        .obj_size          = sizeof(struct udp6_sock),
        .h.udp_table       = &udplite_table,
 };
index a815f5ab4c49a08a51f7ae5e1200e589621799e8..31ab12fd720aefdab9e3eced63d2a37d169516f9 100644 (file)
@@ -1940,7 +1940,8 @@ static u32 gen_reqid(struct net *net)
 }
 
 static int
-parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
+parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_policy *pol,
+                  struct sadb_x_ipsecrequest *rq)
 {
        struct net *net = xp_net(xp);
        struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr;
@@ -1958,9 +1959,12 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
        if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0)
                return -EINVAL;
        t->mode = mode;
-       if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE)
+       if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE) {
+               if ((mode == XFRM_MODE_TUNNEL || mode == XFRM_MODE_BEET) &&
+                   pol->sadb_x_policy_dir == IPSEC_DIR_OUTBOUND)
+                       return -EINVAL;
                t->optional = 1;
-       else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) {
+       else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) {
                t->reqid = rq->sadb_x_ipsecrequest_reqid;
                if (t->reqid > IPSEC_MANUAL_REQID_MAX)
                        t->reqid = 0;
@@ -2002,7 +2006,7 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol)
                    rq->sadb_x_ipsecrequest_len < sizeof(*rq))
                        return -EINVAL;
 
-               if ((err = parse_ipsecrequest(xp, rq)) < 0)
+               if ((err = parse_ipsecrequest(xp, pol, rq)) < 0)
                        return err;
                len -= rq->sadb_x_ipsecrequest_len;
                rq = (void*)((u8*)rq + rq->sadb_x_ipsecrequest_len);
index da7fe94bea2eb8b6d1fe84bfdb8d1fa7cf5f6879..9ffbc667be6cf4c13d2f731e003510efeed8ee29 100644 (file)
@@ -583,7 +583,8 @@ static int llc_ui_wait_for_disc(struct sock *sk, long timeout)
 
        add_wait_queue(sk_sleep(sk), &wait);
        while (1) {
-               if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE, &wait))
+               if (sk_wait_event(sk, &timeout,
+                                 READ_ONCE(sk->sk_state) == TCP_CLOSE, &wait))
                        break;
                rc = -ERESTARTSYS;
                if (signal_pending(current))
@@ -603,7 +604,8 @@ static bool llc_ui_wait_for_conn(struct sock *sk, long timeout)
 
        add_wait_queue(sk_sleep(sk), &wait);
        while (1) {
-               if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT, &wait))
+               if (sk_wait_event(sk, &timeout,
+                                 READ_ONCE(sk->sk_state) != TCP_SYN_SENT, &wait))
                        break;
                if (signal_pending(current) || !timeout)
                        break;
@@ -622,7 +624,7 @@ static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout)
        while (1) {
                rc = 0;
                if (sk_wait_event(sk, &timeout,
-                                 (sk->sk_shutdown & RCV_SHUTDOWN) ||
+                                 (READ_ONCE(sk->sk_shutdown) & RCV_SHUTDOWN) ||
                                  (!llc_data_accept_state(llc->state) &&
                                   !llc->remote_busy_flag &&
                                   !llc->p_flag), &wait))
index 7317e4a5d1ff0af2d1b79bd3fa4b0e79bf875a9b..86b2036d73ff90eaadf35885acffda8224baa740 100644 (file)
@@ -1578,9 +1578,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
                sdata_dereference(link->u.ap.unsol_bcast_probe_resp,
                                  sdata);
 
-       /* abort any running channel switch */
+       /* abort any running channel switch or color change */
        mutex_lock(&local->mtx);
        link_conf->csa_active = false;
+       link_conf->color_change_active = false;
        if (link->csa_block_tx) {
                ieee80211_wake_vif_queues(local, sdata,
                                          IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -3589,7 +3590,7 @@ void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif, bool block_t
 EXPORT_SYMBOL(ieee80211_channel_switch_disconnect);
 
 static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
-                                         u32 *changed)
+                                         u64 *changed)
 {
        int err;
 
@@ -3632,7 +3633,7 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
 static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_local *local = sdata->local;
-       u32 changed = 0;
+       u64 changed = 0;
        int err;
 
        sdata_assert_lock(sdata);
index dbc34fbe7c8f47141f985293d83481c3c76d05bf..77c90ed8f5d7da51dfc156fc1e9ea5495601cbd6 100644 (file)
@@ -258,7 +258,8 @@ ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata,
 
 static enum nl80211_chan_width
 ieee80211_get_chanctx_vif_max_required_bw(struct ieee80211_sub_if_data *sdata,
-                                         struct ieee80211_chanctx_conf *conf)
+                                         struct ieee80211_chanctx *ctx,
+                                         struct ieee80211_link_data *rsvd_for)
 {
        enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
        struct ieee80211_vif *vif = &sdata->vif;
@@ -267,13 +268,14 @@ ieee80211_get_chanctx_vif_max_required_bw(struct ieee80211_sub_if_data *sdata,
        rcu_read_lock();
        for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
                enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT;
-               struct ieee80211_bss_conf *link_conf =
-                       rcu_dereference(sdata->vif.link_conf[link_id]);
+               struct ieee80211_link_data *link =
+                       rcu_dereference(sdata->link[link_id]);
 
-               if (!link_conf)
+               if (!link)
                        continue;
 
-               if (rcu_access_pointer(link_conf->chanctx_conf) != conf)
+               if (link != rsvd_for &&
+                   rcu_access_pointer(link->conf->chanctx_conf) != &ctx->conf)
                        continue;
 
                switch (vif->type) {
@@ -287,7 +289,7 @@ ieee80211_get_chanctx_vif_max_required_bw(struct ieee80211_sub_if_data *sdata,
                         * point, so take the width from the chandef, but
                         * account also for TDLS peers
                         */
-                       width = max(link_conf->chandef.width,
+                       width = max(link->conf->chandef.width,
                                    ieee80211_get_max_required_bw(sdata, link_id));
                        break;
                case NL80211_IFTYPE_P2P_DEVICE:
@@ -296,7 +298,7 @@ ieee80211_get_chanctx_vif_max_required_bw(struct ieee80211_sub_if_data *sdata,
                case NL80211_IFTYPE_ADHOC:
                case NL80211_IFTYPE_MESH_POINT:
                case NL80211_IFTYPE_OCB:
-                       width = link_conf->chandef.width;
+                       width = link->conf->chandef.width;
                        break;
                case NL80211_IFTYPE_WDS:
                case NL80211_IFTYPE_UNSPECIFIED:
@@ -316,7 +318,8 @@ ieee80211_get_chanctx_vif_max_required_bw(struct ieee80211_sub_if_data *sdata,
 
 static enum nl80211_chan_width
 ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
-                                     struct ieee80211_chanctx_conf *conf)
+                                     struct ieee80211_chanctx *ctx,
+                                     struct ieee80211_link_data *rsvd_for)
 {
        struct ieee80211_sub_if_data *sdata;
        enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
@@ -328,7 +331,8 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
                if (!ieee80211_sdata_running(sdata))
                        continue;
 
-               width = ieee80211_get_chanctx_vif_max_required_bw(sdata, conf);
+               width = ieee80211_get_chanctx_vif_max_required_bw(sdata, ctx,
+                                                                 rsvd_for);
 
                max_bw = max(max_bw, width);
        }
@@ -336,8 +340,8 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
        /* use the configured bandwidth in case of monitor interface */
        sdata = rcu_dereference(local->monitor_sdata);
        if (sdata &&
-           rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == conf)
-               max_bw = max(max_bw, conf->def.width);
+           rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == &ctx->conf)
+               max_bw = max(max_bw, ctx->conf.def.width);
 
        rcu_read_unlock();
 
@@ -349,8 +353,10 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
  * the max of min required widths of all the interfaces bound to this
  * channel context.
  */
-static u32 _ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
-                                            struct ieee80211_chanctx *ctx)
+static u32
+_ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
+                                 struct ieee80211_chanctx *ctx,
+                                 struct ieee80211_link_data *rsvd_for)
 {
        enum nl80211_chan_width max_bw;
        struct cfg80211_chan_def min_def;
@@ -370,7 +376,7 @@ static u32 _ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
                return 0;
        }
 
-       max_bw = ieee80211_get_chanctx_max_required_bw(local, &ctx->conf);
+       max_bw = ieee80211_get_chanctx_max_required_bw(local, ctx, rsvd_for);
 
        /* downgrade chandef up to max_bw */
        min_def = ctx->conf.def;
@@ -448,9 +454,10 @@ static void ieee80211_chan_bw_change(struct ieee80211_local *local,
  * channel context.
  */
 void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
-                                     struct ieee80211_chanctx *ctx)
+                                     struct ieee80211_chanctx *ctx,
+                                     struct ieee80211_link_data *rsvd_for)
 {
-       u32 changed = _ieee80211_recalc_chanctx_min_def(local, ctx);
+       u32 changed = _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for);
 
        if (!changed)
                return;
@@ -464,10 +471,11 @@ void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
        ieee80211_chan_bw_change(local, ctx, false);
 }
 
-static void ieee80211_change_chanctx(struct ieee80211_local *local,
-                                    struct ieee80211_chanctx *ctx,
-                                    struct ieee80211_chanctx *old_ctx,
-                                    const struct cfg80211_chan_def *chandef)
+static void _ieee80211_change_chanctx(struct ieee80211_local *local,
+                                     struct ieee80211_chanctx *ctx,
+                                     struct ieee80211_chanctx *old_ctx,
+                                     const struct cfg80211_chan_def *chandef,
+                                     struct ieee80211_link_data *rsvd_for)
 {
        u32 changed;
 
@@ -492,7 +500,7 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local,
        ieee80211_chan_bw_change(local, old_ctx, true);
 
        if (cfg80211_chandef_identical(&ctx->conf.def, chandef)) {
-               ieee80211_recalc_chanctx_min_def(local, ctx);
+               ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for);
                return;
        }
 
@@ -502,7 +510,7 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local,
 
        /* check if min chanctx also changed */
        changed = IEEE80211_CHANCTX_CHANGE_WIDTH |
-                 _ieee80211_recalc_chanctx_min_def(local, ctx);
+                 _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for);
        drv_change_chanctx(local, ctx, changed);
 
        if (!local->use_chanctx) {
@@ -514,6 +522,14 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local,
        ieee80211_chan_bw_change(local, old_ctx, false);
 }
 
+static void ieee80211_change_chanctx(struct ieee80211_local *local,
+                                    struct ieee80211_chanctx *ctx,
+                                    struct ieee80211_chanctx *old_ctx,
+                                    const struct cfg80211_chan_def *chandef)
+{
+       _ieee80211_change_chanctx(local, ctx, old_ctx, chandef, NULL);
+}
+
 static struct ieee80211_chanctx *
 ieee80211_find_chanctx(struct ieee80211_local *local,
                       const struct cfg80211_chan_def *chandef,
@@ -638,7 +654,7 @@ ieee80211_alloc_chanctx(struct ieee80211_local *local,
        ctx->conf.rx_chains_dynamic = 1;
        ctx->mode = mode;
        ctx->conf.radar_enabled = false;
-       ieee80211_recalc_chanctx_min_def(local, ctx);
+       _ieee80211_recalc_chanctx_min_def(local, ctx, NULL);
 
        return ctx;
 }
@@ -855,6 +871,9 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link,
        }
 
        if (new_ctx) {
+               /* recalc considering the link we'll use it for now */
+               ieee80211_recalc_chanctx_min_def(local, new_ctx, link);
+
                ret = drv_assign_vif_chanctx(local, sdata, link->conf, new_ctx);
                if (ret)
                        goto out;
@@ -873,12 +892,12 @@ out:
                ieee80211_recalc_chanctx_chantype(local, curr_ctx);
                ieee80211_recalc_smps_chanctx(local, curr_ctx);
                ieee80211_recalc_radar_chanctx(local, curr_ctx);
-               ieee80211_recalc_chanctx_min_def(local, curr_ctx);
+               ieee80211_recalc_chanctx_min_def(local, curr_ctx, NULL);
        }
 
        if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) {
                ieee80211_recalc_txpower(sdata, false);
-               ieee80211_recalc_chanctx_min_def(local, new_ctx);
+               ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL);
        }
 
        if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
@@ -1270,7 +1289,7 @@ ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)
 
        ieee80211_link_update_chandef(link, &link->reserved_chandef);
 
-       ieee80211_change_chanctx(local, new_ctx, old_ctx, chandef);
+       _ieee80211_change_chanctx(local, new_ctx, old_ctx, chandef, link);
 
        vif_chsw[0].vif = &sdata->vif;
        vif_chsw[0].old_ctx = &old_ctx->conf;
@@ -1300,7 +1319,7 @@ ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)
        if (ieee80211_chanctx_refcount(local, old_ctx) == 0)
                ieee80211_free_chanctx(local, old_ctx);
 
-       ieee80211_recalc_chanctx_min_def(local, new_ctx);
+       ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL);
        ieee80211_recalc_smps_chanctx(local, new_ctx);
        ieee80211_recalc_radar_chanctx(local, new_ctx);
 
@@ -1665,7 +1684,7 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
                ieee80211_recalc_chanctx_chantype(local, ctx);
                ieee80211_recalc_smps_chanctx(local, ctx);
                ieee80211_recalc_radar_chanctx(local, ctx);
-               ieee80211_recalc_chanctx_min_def(local, ctx);
+               ieee80211_recalc_chanctx_min_def(local, ctx, NULL);
 
                list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
                                         reserved_chanctx_list) {
index a0a7839cb9614010e9ab4d892e08b20bf0255194..b0372e76f3739c49a71b3649a82f9b4062e49a86 100644 (file)
@@ -2537,7 +2537,8 @@ int ieee80211_chanctx_refcount(struct ieee80211_local *local,
 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
                                   struct ieee80211_chanctx *chanctx);
 void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
-                                     struct ieee80211_chanctx *ctx);
+                                     struct ieee80211_chanctx *ctx,
+                                     struct ieee80211_link_data *rsvd_for);
 bool ieee80211_is_radar_required(struct ieee80211_local *local);
 
 void ieee80211_dfs_cac_timer(unsigned long data);
index de5d69f21306f5edcff12553e0f6ac83edcecb8c..db0d0132c58c13157d9171e8c39924d70762a7ac 100644 (file)
@@ -67,7 +67,7 @@
                        __entry->min_freq_offset = (c)->chan ? (c)->chan->freq_offset : 0;      \
                        __entry->min_chan_width = (c)->width;                           \
                        __entry->min_center_freq1 = (c)->center_freq1;                  \
-                       __entry->freq1_offset = (c)->freq1_offset;                      \
+                       __entry->min_freq1_offset = (c)->freq1_offset;                  \
                        __entry->min_center_freq2 = (c)->center_freq2;
 #define MIN_CHANDEF_PR_FMT     " min_control:%d.%03d MHz min_width:%d min_center: %d.%03d/%d MHz"
 #define MIN_CHANDEF_PR_ARG     __entry->min_control_freq, __entry->min_freq_offset,    \
index 1a33274075525228d0384c1d8878405de282e1f6..0d9fbc8458fdfe4beb31a9813471cf825edc3c41 100644 (file)
@@ -3791,6 +3791,7 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
        ieee80211_tx_result r;
        struct ieee80211_vif *vif = txq->vif;
        int q = vif->hw_queue[txq->ac];
+       unsigned long flags;
        bool q_stopped;
 
        WARN_ON_ONCE(softirq_count() == 0);
@@ -3799,9 +3800,9 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
                return NULL;
 
 begin:
-       spin_lock(&local->queue_stop_reason_lock);
+       spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
        q_stopped = local->queue_stop_reasons[q];
-       spin_unlock(&local->queue_stop_reason_lock);
+       spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 
        if (unlikely(q_stopped)) {
                /* mark for waking later */
index 1527d6aafc143bb7309239594482551f91a73fab..4bf76150925d20e535119c86edea7a5969a2042f 100644 (file)
@@ -3015,7 +3015,7 @@ void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata,
 
                chanctx = container_of(chanctx_conf, struct ieee80211_chanctx,
                                       conf);
-               ieee80211_recalc_chanctx_min_def(local, chanctx);
+               ieee80211_recalc_chanctx_min_def(local, chanctx, NULL);
        }
  unlock:
        mutex_unlock(&local->chanctx_mtx);
index 08dc53f56bc23254e30e08fe82630c8e1cb4d15b..67311e7d5b21a3db044aade8981d4ed4afce9189 100644 (file)
@@ -90,8 +90,8 @@ static int __mptcp_socket_create(struct mptcp_sock *msk)
        if (err)
                return err;
 
-       msk->first = ssock->sk;
-       msk->subflow = ssock;
+       WRITE_ONCE(msk->first, ssock->sk);
+       WRITE_ONCE(msk->subflow, ssock);
        subflow = mptcp_subflow_ctx(ssock->sk);
        list_add(&subflow->node, &msk->conn_list);
        sock_hold(ssock->sk);
@@ -603,7 +603,7 @@ static bool mptcp_check_data_fin(struct sock *sk)
                WRITE_ONCE(msk->ack_seq, msk->ack_seq + 1);
                WRITE_ONCE(msk->rcv_data_fin, 0);
 
-               sk->sk_shutdown |= RCV_SHUTDOWN;
+               WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | RCV_SHUTDOWN);
                smp_mb__before_atomic(); /* SHUTDOWN must be visible first */
 
                switch (sk->sk_state) {
@@ -825,6 +825,13 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk)
        mptcp_data_unlock(sk);
 }
 
+static void mptcp_subflow_joined(struct mptcp_sock *msk, struct sock *ssk)
+{
+       mptcp_subflow_ctx(ssk)->map_seq = READ_ONCE(msk->ack_seq);
+       WRITE_ONCE(msk->allow_infinite_fallback, false);
+       mptcp_event(MPTCP_EVENT_SUB_ESTABLISHED, msk, ssk, GFP_ATOMIC);
+}
+
 static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
 {
        struct sock *sk = (struct sock *)msk;
@@ -839,6 +846,7 @@ static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
                mptcp_sock_graft(ssk, sk->sk_socket);
 
        mptcp_sockopt_sync_locked(msk, ssk);
+       mptcp_subflow_joined(msk, ssk);
        return true;
 }
 
@@ -910,7 +918,7 @@ static void mptcp_check_for_eof(struct mptcp_sock *msk)
                /* hopefully temporary hack: propagate shutdown status
                 * to msk, when all subflows agree on it
                 */
-               sk->sk_shutdown |= RCV_SHUTDOWN;
+               WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | RCV_SHUTDOWN);
 
                smp_mb__before_atomic(); /* SHUTDOWN must be visible first */
                sk->sk_data_ready(sk);
@@ -1702,7 +1710,6 @@ static int mptcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
 
        lock_sock(ssk);
        msg->msg_flags |= MSG_DONTWAIT;
-       msk->connect_flags = O_NONBLOCK;
        msk->fastopening = 1;
        ret = tcp_sendmsg_fastopen(ssk, msg, copied_syn, len, NULL);
        msk->fastopening = 0;
@@ -2283,7 +2290,7 @@ static void mptcp_dispose_initial_subflow(struct mptcp_sock *msk)
 {
        if (msk->subflow) {
                iput(SOCK_INODE(msk->subflow));
-               msk->subflow = NULL;
+               WRITE_ONCE(msk->subflow, NULL);
        }
 }
 
@@ -2420,7 +2427,7 @@ out_release:
        sock_put(ssk);
 
        if (ssk == msk->first)
-               msk->first = NULL;
+               WRITE_ONCE(msk->first, NULL);
 
 out:
        if (ssk == msk->last_snd)
@@ -2527,7 +2534,7 @@ static void mptcp_check_fastclose(struct mptcp_sock *msk)
        }
 
        inet_sk_state_store(sk, TCP_CLOSE);
-       sk->sk_shutdown = SHUTDOWN_MASK;
+       WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);
        smp_mb__before_atomic(); /* SHUTDOWN must be visible first */
        set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags);
 
@@ -2721,7 +2728,7 @@ static int __mptcp_init_sock(struct sock *sk)
        WRITE_ONCE(msk->rmem_released, 0);
        msk->timer_ival = TCP_RTO_MIN;
 
-       msk->first = NULL;
+       WRITE_ONCE(msk->first, NULL);
        inet_csk(sk)->icsk_sync_mss = mptcp_sync_mss;
        WRITE_ONCE(msk->csum_enabled, mptcp_is_checksum_enabled(sock_net(sk)));
        WRITE_ONCE(msk->allow_infinite_fallback, true);
@@ -2959,7 +2966,7 @@ bool __mptcp_close(struct sock *sk, long timeout)
        bool do_cancel_work = false;
        int subflows_alive = 0;
 
-       sk->sk_shutdown = SHUTDOWN_MASK;
+       WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);
 
        if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) {
                mptcp_listen_inuse_dec(sk);
@@ -3039,7 +3046,7 @@ static void mptcp_close(struct sock *sk, long timeout)
        sock_put(sk);
 }
 
-void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk)
+static void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk)
 {
 #if IS_ENABLED(CONFIG_MPTCP_IPV6)
        const struct ipv6_pinfo *ssk6 = inet6_sk(ssk);
@@ -3102,7 +3109,7 @@ static int mptcp_disconnect(struct sock *sk, int flags)
        mptcp_pm_data_reset(msk);
        mptcp_ca_reset(sk);
 
-       sk->sk_shutdown = 0;
+       WRITE_ONCE(sk->sk_shutdown, 0);
        sk_error_report(sk);
        return 0;
 }
@@ -3116,9 +3123,10 @@ static struct ipv6_pinfo *mptcp_inet6_sk(const struct sock *sk)
 }
 #endif
 
-struct sock *mptcp_sk_clone(const struct sock *sk,
-                           const struct mptcp_options_received *mp_opt,
-                           struct request_sock *req)
+struct sock *mptcp_sk_clone_init(const struct sock *sk,
+                                const struct mptcp_options_received *mp_opt,
+                                struct sock *ssk,
+                                struct request_sock *req)
 {
        struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
        struct sock *nsk = sk_clone_lock(sk, GFP_ATOMIC);
@@ -3137,7 +3145,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
        msk = mptcp_sk(nsk);
        msk->local_key = subflow_req->local_key;
        msk->token = subflow_req->token;
-       msk->subflow = NULL;
+       WRITE_ONCE(msk->subflow, NULL);
        msk->in_accept_queue = 1;
        WRITE_ONCE(msk->fully_established, false);
        if (mp_opt->suboptions & OPTION_MPTCP_CSUMREQD)
@@ -3150,10 +3158,30 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
        msk->setsockopt_seq = mptcp_sk(sk)->setsockopt_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);
-
        security_inet_csk_clone(nsk, req);
+
+       /* this can't race with mptcp_close(), as the msk is
+        * not yet exposted to user-space
+        */
+       inet_sk_state_store(nsk, TCP_ESTABLISHED);
+
+       /* The msk maintain a ref to each subflow in the connections list */
+       WRITE_ONCE(msk->first, ssk);
+       list_add(&mptcp_subflow_ctx(ssk)->node, &msk->conn_list);
+       sock_hold(ssk);
+
+       /* new mpc subflow takes ownership of the newly
+        * created mptcp socket
+        */
+       mptcp_token_accept(subflow_req, msk);
+
+       /* set msk addresses early to ensure mptcp_pm_get_local_id()
+        * uses the correct data
+        */
+       mptcp_copy_inaddrs(nsk, ssk);
+       mptcp_propagate_sndbuf(nsk, ssk);
+
+       mptcp_rcv_space_init(msk, ssk);
        bh_unlock_sock(nsk);
 
        /* note: the newly allocated socket refcount is 2 now */
@@ -3185,7 +3213,7 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
        struct socket *listener;
        struct sock *newsk;
 
-       listener = msk->subflow;
+       listener = READ_ONCE(msk->subflow);
        if (WARN_ON_ONCE(!listener)) {
                *err = -EINVAL;
                return NULL;
@@ -3465,14 +3493,16 @@ bool mptcp_finish_join(struct sock *ssk)
                return false;
        }
 
-       if (!list_empty(&subflow->node))
-               goto out;
+       /* active subflow, already present inside the conn_list */
+       if (!list_empty(&subflow->node)) {
+               mptcp_subflow_joined(msk, ssk);
+               return true;
+       }
 
        if (!mptcp_pm_allow_new_subflow(msk))
                goto err_prohibited;
 
-       /* active connections are already on conn_list.
-        * If we can't acquire msk socket lock here, let the release callback
+       /* If we can't acquire msk socket lock here, let the release callback
         * handle it
         */
        mptcp_data_lock(parent);
@@ -3495,11 +3525,6 @@ err_prohibited:
                return false;
        }
 
-       subflow->map_seq = READ_ONCE(msk->ack_seq);
-       WRITE_ONCE(msk->allow_infinite_fallback, false);
-
-out:
-       mptcp_event(MPTCP_EVENT_SUB_ESTABLISHED, msk, ssk, GFP_ATOMIC);
        return true;
 }
 
@@ -3617,9 +3642,9 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
         * acquired the subflow socket lock, too.
         */
        if (msk->fastopening)
-               err = __inet_stream_connect(ssock, uaddr, addr_len, msk->connect_flags, 1);
+               err = __inet_stream_connect(ssock, uaddr, addr_len, O_NONBLOCK, 1);
        else
-               err = inet_stream_connect(ssock, uaddr, addr_len, msk->connect_flags);
+               err = inet_stream_connect(ssock, uaddr, addr_len, O_NONBLOCK);
        inet_sk(sk)->defer_connect = inet_sk(ssock->sk)->defer_connect;
 
        /* on successful connect, the msk state will be moved to established by
@@ -3632,12 +3657,10 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 
        mptcp_copy_inaddrs(sk, ssock->sk);
 
-       /* unblocking connect, mptcp-level inet_stream_connect will error out
-        * without changing the socket state, update it here.
+       /* silence EINPROGRESS and let the caller inet_stream_connect
+        * handle the connection in progress
         */
-       if (err == -EINPROGRESS)
-               sk->sk_socket->state = ssock->state;
-       return err;
+       return 0;
 }
 
 static struct proto mptcp_prot = {
@@ -3696,18 +3719,6 @@ unlock:
        return err;
 }
 
-static int mptcp_stream_connect(struct socket *sock, struct sockaddr *uaddr,
-                               int addr_len, int flags)
-{
-       int ret;
-
-       lock_sock(sock->sk);
-       mptcp_sk(sock->sk)->connect_flags = flags;
-       ret = __inet_stream_connect(sock, uaddr, addr_len, flags, 0);
-       release_sock(sock->sk);
-       return ret;
-}
-
 static int mptcp_listen(struct socket *sock, int backlog)
 {
        struct mptcp_sock *msk = mptcp_sk(sock->sk);
@@ -3751,10 +3762,10 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
 
        pr_debug("msk=%p", msk);
 
-       /* buggy applications can call accept on socket states other then LISTEN
+       /* Buggy applications can call accept on socket states other then LISTEN
         * but no need to allocate the first subflow just to error out.
         */
-       ssock = msk->subflow;
+       ssock = READ_ONCE(msk->subflow);
        if (!ssock)
                return -EINVAL;
 
@@ -3800,9 +3811,6 @@ static __poll_t mptcp_check_writeable(struct mptcp_sock *msk)
 {
        struct sock *sk = (struct sock *)msk;
 
-       if (unlikely(sk->sk_shutdown & SEND_SHUTDOWN))
-               return EPOLLOUT | EPOLLWRNORM;
-
        if (sk_stream_is_writeable(sk))
                return EPOLLOUT | EPOLLWRNORM;
 
@@ -3820,6 +3828,7 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock,
        struct sock *sk = sock->sk;
        struct mptcp_sock *msk;
        __poll_t mask = 0;
+       u8 shutdown;
        int state;
 
        msk = mptcp_sk(sk);
@@ -3828,23 +3837,30 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock,
        state = inet_sk_state_load(sk);
        pr_debug("msk=%p state=%d flags=%lx", msk, state, msk->flags);
        if (state == TCP_LISTEN) {
-               if (WARN_ON_ONCE(!msk->subflow || !msk->subflow->sk))
+               struct socket *ssock = READ_ONCE(msk->subflow);
+
+               if (WARN_ON_ONCE(!ssock || !ssock->sk))
                        return 0;
 
-               return inet_csk_listen_poll(msk->subflow->sk);
+               return inet_csk_listen_poll(ssock->sk);
        }
 
+       shutdown = READ_ONCE(sk->sk_shutdown);
+       if (shutdown == SHUTDOWN_MASK || state == TCP_CLOSE)
+               mask |= EPOLLHUP;
+       if (shutdown & RCV_SHUTDOWN)
+               mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
+
        if (state != TCP_SYN_SENT && state != TCP_SYN_RECV) {
                mask |= mptcp_check_readable(msk);
-               mask |= mptcp_check_writeable(msk);
+               if (shutdown & SEND_SHUTDOWN)
+                       mask |= EPOLLOUT | EPOLLWRNORM;
+               else
+                       mask |= mptcp_check_writeable(msk);
        } else if (state == TCP_SYN_SENT && inet_sk(sk)->defer_connect) {
                /* cf tcp_poll() note about TFO */
                mask |= EPOLLOUT | EPOLLWRNORM;
        }
-       if (sk->sk_shutdown == SHUTDOWN_MASK || state == TCP_CLOSE)
-               mask |= EPOLLHUP;
-       if (sk->sk_shutdown & RCV_SHUTDOWN)
-               mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
 
        /* This barrier is coupled with smp_wmb() in __mptcp_error_report() */
        smp_rmb();
@@ -3859,7 +3875,7 @@ static const struct proto_ops mptcp_stream_ops = {
        .owner             = THIS_MODULE,
        .release           = inet_release,
        .bind              = mptcp_bind,
-       .connect           = mptcp_stream_connect,
+       .connect           = inet_stream_connect,
        .socketpair        = sock_no_socketpair,
        .accept            = mptcp_stream_accept,
        .getname           = inet_getname,
@@ -3954,7 +3970,7 @@ static const struct proto_ops mptcp_v6_stream_ops = {
        .owner             = THIS_MODULE,
        .release           = inet6_release,
        .bind              = mptcp_bind,
-       .connect           = mptcp_stream_connect,
+       .connect           = inet_stream_connect,
        .socketpair        = sock_no_socketpair,
        .accept            = mptcp_stream_accept,
        .getname           = inet6_getname,
index 2d7b2c80a1641233795eb33e986c19837a2e5bc6..c5255258bfb39334959387e8d15a757dc63ad5b3 100644 (file)
@@ -297,7 +297,6 @@ struct mptcp_sock {
                        nodelay:1,
                        fastopening:1,
                        in_accept_queue:1;
-       int             connect_flags;
        struct work_struct work;
        struct sk_buff  *ooo_last_skb;
        struct rb_root  out_of_order_queue;
@@ -306,7 +305,11 @@ struct mptcp_sock {
        struct list_head rtx_queue;
        struct mptcp_data_frag *first_pending;
        struct list_head join_list;
-       struct socket   *subflow; /* outgoing connect/listener/!mp_capable */
+       struct socket   *subflow; /* outgoing connect/listener/!mp_capable
+                                  * The mptcp ops can safely dereference, using suitable
+                                  * ONCE annotation, the subflow outside the socket
+                                  * lock as such sock is freed after close().
+                                  */
        struct sock     *first;
        struct mptcp_pm_data    pm;
        struct {
@@ -613,7 +616,6 @@ int mptcp_is_checksum_enabled(const struct net *net);
 int mptcp_allow_join_id0(const struct net *net);
 unsigned int mptcp_stale_loss_cnt(const struct net *net);
 int mptcp_get_pm_type(const struct net *net);
-void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk);
 void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow,
                                     const struct mptcp_options_received *mp_opt);
 bool __mptcp_retransmit_pending_data(struct sock *sk);
@@ -683,9 +685,10 @@ void __init mptcp_proto_init(void);
 int __init mptcp_proto_v6_init(void);
 #endif
 
-struct sock *mptcp_sk_clone(const struct sock *sk,
-                           const struct mptcp_options_received *mp_opt,
-                           struct request_sock *req);
+struct sock *mptcp_sk_clone_init(const struct sock *sk,
+                                const struct mptcp_options_received *mp_opt,
+                                struct sock *ssk,
+                                struct request_sock *req);
 void mptcp_get_options(const struct sk_buff *skb,
                       struct mptcp_options_received *mp_opt);
 
index ba065b66551a45eb2ca41c6ace9c3fd540d3e7fc..4688daa6b38b75ea0b2092dbb2cf2b4a419edc93 100644 (file)
@@ -815,38 +815,12 @@ create_child:
                ctx->setsockopt_seq = listener->setsockopt_seq;
 
                if (ctx->mp_capable) {
-                       ctx->conn = mptcp_sk_clone(listener->conn, &mp_opt, req);
+                       ctx->conn = mptcp_sk_clone_init(listener->conn, &mp_opt, child, req);
                        if (!ctx->conn)
                                goto fallback;
 
                        owner = mptcp_sk(ctx->conn);
-
-                       /* this can't race with mptcp_close(), as the msk is
-                        * not yet exposted to user-space
-                        */
-                       inet_sk_state_store(ctx->conn, TCP_ESTABLISHED);
-
-                       /* record the newly created socket as the first msk
-                        * subflow, but don't link it yet into conn_list
-                        */
-                       WRITE_ONCE(owner->first, child);
-
-                       /* new mpc subflow takes ownership of the newly
-                        * created mptcp socket
-                        */
-                       owner->setsockopt_seq = ctx->setsockopt_seq;
                        mptcp_pm_new_connection(owner, child, 1);
-                       mptcp_token_accept(subflow_req, owner);
-
-                       /* set msk addresses early to ensure mptcp_pm_get_local_id()
-                        * uses the correct data
-                        */
-                       mptcp_copy_inaddrs(ctx->conn, child);
-                       mptcp_propagate_sndbuf(ctx->conn, child);
-
-                       mptcp_rcv_space_init(owner, child);
-                       list_add(&ctx->node, &owner->conn_list);
-                       sock_hold(child);
 
                        /* with OoO packets we can reach here without ingress
                         * mpc option
index f0783e42108bab59cbf59e4296898ed3bffaf44c..5f76ae86a6561f6decc21c6d35e5311e7488c921 100644 (file)
@@ -711,9 +711,11 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct)
 
        rcu_read_lock();
        ct_hook = rcu_dereference(nf_ct_hook);
-       BUG_ON(ct_hook == NULL);
-       ct_hook->destroy(nfct);
+       if (ct_hook)
+               ct_hook->destroy(nfct);
        rcu_read_unlock();
+
+       WARN_ON(!ct_hook);
 }
 EXPORT_SYMBOL(nf_conntrack_destroy);
 
index d40544cd61a6c032f511653f345fd01127132d11..69c8c8c7e9b8e7d7d0c370ba67eff59bbfea3608 100644 (file)
@@ -2976,7 +2976,9 @@ nla_put_failure:
        return -1;
 }
 
+#if IS_ENABLED(CONFIG_NF_NAT)
 static const union nf_inet_addr any_addr;
+#endif
 
 static __be32 nf_expect_get_id(const struct nf_conntrack_expect *exp)
 {
@@ -3460,10 +3462,12 @@ ctnetlink_change_expect(struct nf_conntrack_expect *x,
        return 0;
 }
 
+#if IS_ENABLED(CONFIG_NF_NAT)
 static const struct nla_policy exp_nat_nla_policy[CTA_EXPECT_NAT_MAX+1] = {
        [CTA_EXPECT_NAT_DIR]    = { .type = NLA_U32 },
        [CTA_EXPECT_NAT_TUPLE]  = { .type = NLA_NESTED },
 };
+#endif
 
 static int
 ctnetlink_parse_expect_nat(const struct nlattr *attr,
index 57f6724c99a76763e212a53b4e29c969d3efa469..169e16fc2bceb1b611da209bd6b1250b125f1baf 100644 (file)
@@ -1218,11 +1218,12 @@ static int __init nf_conntrack_standalone_init(void)
        nf_conntrack_htable_size_user = nf_conntrack_htable_size;
 #endif
 
+       nf_conntrack_init_end();
+
        ret = register_pernet_subsys(&nf_conntrack_net_ops);
        if (ret < 0)
                goto out_pernet;
 
-       nf_conntrack_init_end();
        return 0;
 
 out_pernet:
index 59fb8320ab4d7745ca08e5ffe58cf18c8c196487..dc5675962de4fcfd90518b7ab3d145b60893e2d9 100644 (file)
@@ -3865,12 +3865,10 @@ static struct nft_rule *nft_rule_lookup_byid(const struct net *net,
        struct nft_trans *trans;
 
        list_for_each_entry(trans, &nft_net->commit_list, list) {
-               struct nft_rule *rule = nft_trans_rule(trans);
-
                if (trans->msg_type == NFT_MSG_NEWRULE &&
                    trans->ctx.chain == chain &&
                    id == nft_trans_rule_id(trans))
-                       return rule;
+                       return nft_trans_rule(trans);
        }
        return ERR_PTR(-ENOENT);
 }
index c3563f0be26925836a48e699bd5d828edf51883a..680fe557686e42d3421a445b6c5472bd4056a65a 100644 (file)
@@ -344,6 +344,12 @@ static void nft_netdev_event(unsigned long event, struct net_device *dev,
                return;
        }
 
+       /* UNREGISTER events are also happening on netns exit.
+        *
+        * Although nf_tables core releases all tables/chains, only this event
+        * handler provides guarantee that hook->ops.dev is still accessible,
+        * so we cannot skip exiting net namespaces.
+        */
        __nft_release_basechain(ctx);
 }
 
@@ -362,9 +368,6 @@ static int nf_tables_netdev_event(struct notifier_block *this,
            event != NETDEV_CHANGENAME)
                return NOTIFY_DONE;
 
-       if (!check_net(ctx.net))
-               return NOTIFY_DONE;
-
        nft_net = nft_pernet(ctx.net);
        mutex_lock(&nft_net->commit_mutex);
        list_for_each_entry(table, &nft_net->tables, list) {
index 19ea4d3c35535552a3acf1ac18f33b91645f944a..2f114aa10f1a7ad18c540e1cc1beba0345e4e85a 100644 (file)
@@ -221,7 +221,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set,
 {
        struct nft_set *set = (struct nft_set *)__set;
        struct rb_node *prev = rb_prev(&rbe->node);
-       struct nft_rbtree_elem *rbe_prev;
+       struct nft_rbtree_elem *rbe_prev = NULL;
        struct nft_set_gc_batch *gcb;
 
        gcb = nft_set_gc_batch_check(set, NULL, GFP_ATOMIC);
@@ -229,17 +229,21 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set,
                return -ENOMEM;
 
        /* search for expired end interval coming before this element. */
-       do {
+       while (prev) {
                rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node);
                if (nft_rbtree_interval_end(rbe_prev))
                        break;
 
                prev = rb_prev(prev);
-       } while (prev != NULL);
+       }
+
+       if (rbe_prev) {
+               rb_erase(&rbe_prev->node, &priv->root);
+               atomic_dec(&set->nelems);
+       }
 
-       rb_erase(&rbe_prev->node, &priv->root);
        rb_erase(&rbe->node, &priv->root);
-       atomic_sub(2, &set->nelems);
+       atomic_dec(&set->nelems);
 
        nft_set_gc_batch_add(gcb, rbe);
        nft_set_gc_batch_complete(gcb);
@@ -268,7 +272,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
                               struct nft_set_ext **ext)
 {
        struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
-       struct rb_node *node, *parent, **p, *first = NULL;
+       struct rb_node *node, *next, *parent, **p, *first = NULL;
        struct nft_rbtree *priv = nft_set_priv(set);
        u8 genmask = nft_genmask_next(net);
        int d, err;
@@ -307,7 +311,9 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
         * Values stored in the tree are in reversed order, starting from
         * highest to lowest value.
         */
-       for (node = first; node != NULL; node = rb_next(node)) {
+       for (node = first; node != NULL; node = next) {
+               next = rb_next(node);
+
                rbe = rb_entry(node, struct nft_rbtree_elem, node);
 
                if (!nft_set_elem_active(&rbe->ext, genmask))
index 7ef8b9a1e30c5a87687899dfcfc014fc033bf572..3a1e0fd5bf149c3ece9e0f004107efe149e3f2c3 100644 (file)
@@ -1779,7 +1779,7 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
                                break;
                        }
                }
-               if (put_user(ALIGN(nlk->ngroups / 8, sizeof(u32)), optlen))
+               if (put_user(ALIGN(BITS_TO_BYTES(nlk->ngroups), sizeof(u32)), optlen))
                        err = -EFAULT;
                netlink_unlock_table();
                return err;
@@ -1990,7 +1990,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 
        skb_free_datagram(sk, skb);
 
-       if (nlk->cb_running &&
+       if (READ_ONCE(nlk->cb_running) &&
            atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) {
                ret = netlink_dump(sk);
                if (ret) {
@@ -2302,7 +2302,7 @@ static int netlink_dump(struct sock *sk)
        if (cb->done)
                cb->done(cb);
 
-       nlk->cb_running = false;
+       WRITE_ONCE(nlk->cb_running, false);
        module = cb->module;
        skb = cb->skb;
        mutex_unlock(nlk->cb_mutex);
@@ -2365,7 +2365,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
                        goto error_put;
        }
 
-       nlk->cb_running = true;
+       WRITE_ONCE(nlk->cb_running, true);
        nlk->dump_done_errno = INT_MAX;
 
        mutex_unlock(nlk->cb_mutex);
@@ -2703,7 +2703,7 @@ static int netlink_native_seq_show(struct seq_file *seq, void *v)
                           nlk->groups ? (u32)nlk->groups[0] : 0,
                           sk_rmem_alloc_get(s),
                           sk_wmem_alloc_get(s),
-                          nlk->cb_running,
+                          READ_ONCE(nlk->cb_running),
                           refcount_read(&s->sk_refcnt),
                           atomic_read(&s->sk_drops),
                           sock_i_ino(s)
index 3f99b432ea707e20a9620fb89cdf37d5e4f121e9..e2d2af924cff4a4103e59e04a6efe69c6fcca23e 100644 (file)
@@ -123,7 +123,7 @@ void nr_write_internal(struct sock *sk, int frametype)
        unsigned char  *dptr;
        int len, timeout;
 
-       len = NR_NETWORK_LEN + NR_TRANSPORT_LEN;
+       len = NR_TRANSPORT_LEN;
 
        switch (frametype & 0x0F) {
        case NR_CONNREQ:
@@ -141,7 +141,8 @@ void nr_write_internal(struct sock *sk, int frametype)
                return;
        }
 
-       if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
+       skb = alloc_skb(NR_NETWORK_LEN + len, GFP_ATOMIC);
+       if (!skb)
                return;
 
        /*
@@ -149,7 +150,7 @@ void nr_write_internal(struct sock *sk, int frametype)
         */
        skb_reserve(skb, NR_NETWORK_LEN);
 
-       dptr = skb_put(skb, skb_tailroom(skb));
+       dptr = skb_put(skb, len);
 
        switch (frametype & 0x0F) {
        case NR_CONNREQ:
index e9ca007718b7e5a82c882b21724273f50f7276bd..0f23e5e8e03ebaaaefbc567153e3da531aecb3ca 100644 (file)
@@ -77,13 +77,12 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
                                       netdev_features_t features)
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
+       u16 mac_offset = skb->mac_header;
        unsigned int nsh_len, mac_len;
        __be16 proto;
-       int nhoff;
 
        skb_reset_network_header(skb);
 
-       nhoff = skb->network_header - skb->mac_header;
        mac_len = skb->mac_len;
 
        if (unlikely(!pskb_may_pull(skb, NSH_BASE_HDR_LEN)))
@@ -108,15 +107,14 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
        segs = skb_mac_gso_segment(skb, features);
        if (IS_ERR_OR_NULL(segs)) {
                skb_gso_error_unwind(skb, htons(ETH_P_NSH), nsh_len,
-                                    skb->network_header - nhoff,
-                                    mac_len);
+                                    mac_offset, mac_len);
                goto out;
        }
 
        for (skb = segs; skb; skb = skb->next) {
                skb->protocol = htons(ETH_P_NSH);
                __skb_push(skb, nsh_len);
-               skb_set_mac_header(skb, -nhoff);
+               skb->mac_header = mac_offset;
                skb->network_header = skb->mac_header + mac_len;
                skb->mac_len = mac_len;
        }
index 640d94e34635b51709d51be27635d23b3c184d0c..a2dbeb264f260e5b8923ece9aac99fe19ddfeb62 100644 (file)
@@ -1934,10 +1934,8 @@ static void packet_parse_headers(struct sk_buff *skb, struct socket *sock)
        /* Move network header to the right position for VLAN tagged packets */
        if (likely(skb->dev->type == ARPHRD_ETHER) &&
            eth_type_vlan(skb->protocol) &&
-           __vlan_get_protocol(skb, skb->protocol, &depth) != 0) {
-               if (pskb_may_pull(skb, depth))
-                       skb_set_network_header(skb, depth);
-       }
+           vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
+               skb_set_network_header(skb, depth);
 
        skb_probe_transport_header(skb);
 }
@@ -3203,6 +3201,9 @@ static int packet_do_bind(struct sock *sk, const char *name, int ifindex,
 
        lock_sock(sk);
        spin_lock(&po->bind_lock);
+       if (!proto)
+               proto = po->num;
+
        rcu_read_lock();
 
        if (po->fanout) {
@@ -3301,7 +3302,7 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr,
        memcpy(name, uaddr->sa_data, sizeof(uaddr->sa_data_min));
        name[sizeof(uaddr->sa_data_min)] = 0;
 
-       return packet_do_bind(sk, name, 0, pkt_sk(sk)->num);
+       return packet_do_bind(sk, name, 0, 0);
 }
 
 static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
@@ -3318,8 +3319,7 @@ static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len
        if (sll->sll_family != AF_PACKET)
                return -EINVAL;
 
-       return packet_do_bind(sk, NULL, sll->sll_ifindex,
-                             sll->sll_protocol ? : pkt_sk(sk)->num);
+       return packet_do_bind(sk, NULL, sll->sll_ifindex, sll->sll_protocol);
 }
 
 static struct proto packet_proto = {
index d0c4eda4cdc6f2d0ef259a889c884c69f1f81790..f6b200cb3c0668db7bf380d0868583440edca89b 100644 (file)
@@ -143,7 +143,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
        rp = nlmsg_data(nlh);
        rp->pdiag_family = AF_PACKET;
        rp->pdiag_type = sk->sk_type;
-       rp->pdiag_num = ntohs(po->num);
+       rp->pdiag_num = ntohs(READ_ONCE(po->num));
        rp->pdiag_ino = sk_ino;
        sock_diag_save_cookie(sk, rp->pdiag_cookie);
 
index 31f738d65f1c669529e1f0ddab8fdc89740dfb89..da0b3b5157d5f343f7ffac19882e3d3a0ea26ea1 100644 (file)
@@ -980,6 +980,7 @@ static int __init af_rxrpc_init(void)
        BUILD_BUG_ON(sizeof(struct rxrpc_skb_priv) > sizeof_field(struct sk_buff, cb));
 
        ret = -ENOMEM;
+       rxrpc_gen_version_string();
        rxrpc_call_jar = kmem_cache_create(
                "rxrpc_call_jar", sizeof(struct rxrpc_call), 0,
                SLAB_HWCACHE_ALIGN, NULL);
index 5d44dc08f66d0d1adfcec26a30f333d10a70a2d7..e8e14c6f904d9e999014f39ad1f0ae88dffc9e51 100644 (file)
@@ -1068,6 +1068,7 @@ int rxrpc_get_server_data_key(struct rxrpc_connection *, const void *, time64_t,
 /*
  * local_event.c
  */
+void rxrpc_gen_version_string(void);
 void rxrpc_send_version_request(struct rxrpc_local *local,
                                struct rxrpc_host_header *hdr,
                                struct sk_buff *skb);
index 5e69ea6b233dacee3e0eb12eb265488b022694fb..993c69f97488ccc3efac58def58fc8be8e89a7fc 100644 (file)
 #include <generated/utsrelease.h>
 #include "ar-internal.h"
 
-static const char rxrpc_version_string[65] = "linux-" UTS_RELEASE " AF_RXRPC";
+static char rxrpc_version_string[65]; // "linux-" UTS_RELEASE " AF_RXRPC";
+
+/*
+ * Generate the VERSION packet string.
+ */
+void rxrpc_gen_version_string(void)
+{
+       snprintf(rxrpc_version_string, sizeof(rxrpc_version_string),
+                "linux-%.49s AF_RXRPC", UTS_RELEASE);
+}
 
 /*
  * Reply to a version request
index 9dbc43388e579590dc4e2faccae5eb62144c1696..815c3e416bc540582a4b620953478fe674335c65 100644 (file)
@@ -1153,6 +1153,9 @@ static int fl_set_geneve_opt(const struct nlattr *nla, struct fl_flow_key *key,
        if (option_len > sizeof(struct geneve_opt))
                data_len = option_len - sizeof(struct geneve_opt);
 
+       if (key->enc_opts.len > FLOW_DIS_TUN_OPTS_MAX - 4)
+               return -ERANGE;
+
        opt = (struct geneve_opt *)&key->enc_opts.data[key->enc_opts.len];
        memset(opt, 0xff, option_len);
        opt->length = data_len / 4;
index fdb8f429333d26a1380063445ebfc9afad3aef84..014209b1dd5844b5bcd8148cf0f0176fd8cbf906 100644 (file)
@@ -1252,7 +1252,12 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
        sch->parent = parent;
 
        if (handle == TC_H_INGRESS) {
-               sch->flags |= TCQ_F_INGRESS;
+               if (!(sch->flags & TCQ_F_INGRESS)) {
+                       NL_SET_ERR_MSG(extack,
+                                      "Specified parent ID is reserved for ingress and clsact Qdiscs");
+                       err = -EINVAL;
+                       goto err_out3;
+               }
                handle = TC_H_MAKE(TC_H_INGRESS, 0);
        } else {
                if (handle == 0) {
@@ -1591,11 +1596,20 @@ replay:
                                        NL_SET_ERR_MSG(extack, "Invalid qdisc name");
                                        return -EINVAL;
                                }
+                               if (q->flags & TCQ_F_INGRESS) {
+                                       NL_SET_ERR_MSG(extack,
+                                                      "Cannot regraft ingress or clsact Qdiscs");
+                                       return -EINVAL;
+                               }
                                if (q == p ||
                                    (p && check_loop(q, p, 0))) {
                                        NL_SET_ERR_MSG(extack, "Qdisc parent/child loop detected");
                                        return -ELOOP;
                                }
+                               if (clid == TC_H_INGRESS) {
+                                       NL_SET_ERR_MSG(extack, "Ingress cannot graft directly");
+                                       return -EINVAL;
+                               }
                                qdisc_refcount_inc(q);
                                goto graft;
                        } else {
index 84838128b9c5b53db597c3923ca98ea5326081d7..e43a4549937230c986d23ba4550573da2d9a53c8 100644 (file)
@@ -80,6 +80,9 @@ static int ingress_init(struct Qdisc *sch, struct nlattr *opt,
        struct net_device *dev = qdisc_dev(sch);
        int err;
 
+       if (sch->parent != TC_H_INGRESS)
+               return -EOPNOTSUPP;
+
        net_inc_ingress_queue();
 
        mini_qdisc_pair_init(&q->miniqp, sch, &dev->miniq_ingress);
@@ -101,6 +104,9 @@ static void ingress_destroy(struct Qdisc *sch)
 {
        struct ingress_sched_data *q = qdisc_priv(sch);
 
+       if (sch->parent != TC_H_INGRESS)
+               return;
+
        tcf_block_put_ext(q->block, sch, &q->block_info);
        net_dec_ingress_queue();
 }
@@ -134,7 +140,7 @@ static struct Qdisc_ops ingress_qdisc_ops __read_mostly = {
        .cl_ops                 =       &ingress_class_ops,
        .id                     =       "ingress",
        .priv_size              =       sizeof(struct ingress_sched_data),
-       .static_flags           =       TCQ_F_CPUSTATS,
+       .static_flags           =       TCQ_F_INGRESS | TCQ_F_CPUSTATS,
        .init                   =       ingress_init,
        .destroy                =       ingress_destroy,
        .dump                   =       ingress_dump,
@@ -219,6 +225,9 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt,
        struct net_device *dev = qdisc_dev(sch);
        int err;
 
+       if (sch->parent != TC_H_CLSACT)
+               return -EOPNOTSUPP;
+
        net_inc_ingress_queue();
        net_inc_egress_queue();
 
@@ -248,6 +257,9 @@ static void clsact_destroy(struct Qdisc *sch)
 {
        struct clsact_sched_data *q = qdisc_priv(sch);
 
+       if (sch->parent != TC_H_CLSACT)
+               return;
+
        tcf_block_put_ext(q->egress_block, sch, &q->egress_block_info);
        tcf_block_put_ext(q->ingress_block, sch, &q->ingress_block_info);
 
@@ -269,7 +281,7 @@ static struct Qdisc_ops clsact_qdisc_ops __read_mostly = {
        .cl_ops                 =       &clsact_class_ops,
        .id                     =       "clsact",
        .priv_size              =       sizeof(struct clsact_sched_data),
-       .static_flags           =       TCQ_F_CPUSTATS,
+       .static_flags           =       TCQ_F_INGRESS | TCQ_F_CPUSTATS,
        .init                   =       clsact_init,
        .destroy                =       clsact_destroy,
        .dump                   =       ingress_dump,
index 2f66a200651742d318d90778a9452fe9ad656a2c..2abe45af98e7c6efd5baffb88a8687e595cf3f24 100644 (file)
@@ -324,9 +324,12 @@ bool sctp_transport_pl_recv(struct sctp_transport *t)
                t->pl.probe_size += SCTP_PL_BIG_STEP;
        } else if (t->pl.state == SCTP_PL_SEARCH) {
                if (!t->pl.probe_high) {
-                       t->pl.probe_size = min(t->pl.probe_size + SCTP_PL_BIG_STEP,
-                                              SCTP_MAX_PLPMTU);
-                       return false;
+                       if (t->pl.probe_size < SCTP_MAX_PLPMTU) {
+                               t->pl.probe_size = min(t->pl.probe_size + SCTP_PL_BIG_STEP,
+                                                      SCTP_MAX_PLPMTU);
+                               return false;
+                       }
+                       t->pl.probe_high = SCTP_MAX_PLPMTU;
                }
                t->pl.probe_size += SCTP_PL_MIN_STEP;
                if (t->pl.probe_size >= t->pl.probe_high) {
@@ -341,7 +344,7 @@ bool sctp_transport_pl_recv(struct sctp_transport *t)
        } else if (t->pl.state == SCTP_PL_COMPLETE) {
                /* Raise probe_size again after 30 * interval in Search Complete */
                t->pl.state = SCTP_PL_SEARCH; /* Search Complete -> Search */
-               t->pl.probe_size += SCTP_PL_MIN_STEP;
+               t->pl.probe_size = min(t->pl.probe_size + SCTP_PL_MIN_STEP, SCTP_MAX_PLPMTU);
        }
 
        return t->pl.state == SCTP_PL_COMPLETE;
index 50c38b624f772c05d8ecd2745da8fa719d6dc4b1..538e9c6ec8c98248a8324284b30b07bf84fd88f5 100644 (file)
@@ -2000,8 +2000,10 @@ static int smc_listen_rdma_init(struct smc_sock *new_smc,
                return rc;
 
        /* create send buffer and rmb */
-       if (smc_buf_create(new_smc, false))
+       if (smc_buf_create(new_smc, false)) {
+               smc_conn_abort(new_smc, ini->first_contact_local);
                return SMC_CLC_DECL_MEM;
+       }
 
        return 0;
 }
@@ -2217,8 +2219,11 @@ static void smc_find_rdma_v2_device_serv(struct smc_sock *new_smc,
        smcr_version = ini->smcr_version;
        ini->smcr_version = SMC_V2;
        rc = smc_listen_rdma_init(new_smc, ini);
-       if (!rc)
+       if (!rc) {
                rc = smc_listen_rdma_reg(new_smc, ini->first_contact_local);
+               if (rc)
+                       smc_conn_abort(new_smc, ini->first_contact_local);
+       }
        if (!rc)
                return;
        ini->smcr_version = smcr_version;
index 31db7438857c9f81fd336bfce74c5c92b7d275c6..dbdf03e8aa5b55f29d71e9f7c28169cac358740f 100644 (file)
@@ -67,8 +67,8 @@ static void smc_close_stream_wait(struct smc_sock *smc, long timeout)
 
                rc = sk_wait_event(sk, &timeout,
                                   !smc_tx_prepared_sends(&smc->conn) ||
-                                  sk->sk_err == ECONNABORTED ||
-                                  sk->sk_err == ECONNRESET ||
+                                  READ_ONCE(sk->sk_err) == ECONNABORTED ||
+                                  READ_ONCE(sk->sk_err) == ECONNRESET ||
                                   smc->conn.killed,
                                   &wait);
                if (rc)
index 454356771cda55b10c496cbebc470c273d4c56ea..3f465faf2b6814b7e48972bb538bb8c348e62af7 100644 (file)
@@ -127,6 +127,7 @@ static int smcr_lgr_conn_assign_link(struct smc_connection *conn, bool first)
        int i, j;
 
        /* do link balancing */
+       conn->lnk = NULL;       /* reset conn->lnk first */
        for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
                struct smc_link *lnk = &conn->lgr->lnk[i];
 
index a0840b8c935b872d772c2d3809ad20364865aa09..7a8d9163d186e176808818488ceae05c3cc81701 100644 (file)
@@ -578,7 +578,10 @@ static struct smc_buf_desc *smc_llc_get_next_rmb(struct smc_link_group *lgr,
 {
        struct smc_buf_desc *buf_next;
 
-       if (!buf_pos || list_is_last(&buf_pos->list, &lgr->rmbs[*buf_lst])) {
+       if (!buf_pos)
+               return _smc_llc_get_next_rmb(lgr, buf_lst);
+
+       if (list_is_last(&buf_pos->list, &lgr->rmbs[*buf_lst])) {
                (*buf_lst)++;
                return _smc_llc_get_next_rmb(lgr, buf_lst);
        }
@@ -614,6 +617,8 @@ static int smc_llc_fill_ext_v2(struct smc_llc_msg_add_link_v2_ext *ext,
                goto out;
        buf_pos = smc_llc_get_first_rmb(lgr, &buf_lst);
        for (i = 0; i < ext->num_rkeys; i++) {
+               while (buf_pos && !(buf_pos)->used)
+                       buf_pos = smc_llc_get_next_rmb(lgr, &buf_lst, buf_pos);
                if (!buf_pos)
                        break;
                rmb = buf_pos;
@@ -623,8 +628,6 @@ static int smc_llc_fill_ext_v2(struct smc_llc_msg_add_link_v2_ext *ext,
                        cpu_to_be64((uintptr_t)rmb->cpu_addr) :
                        cpu_to_be64((u64)sg_dma_address(rmb->sgt[lnk_idx].sgl));
                buf_pos = smc_llc_get_next_rmb(lgr, &buf_lst, buf_pos);
-               while (buf_pos && !(buf_pos)->used)
-                       buf_pos = smc_llc_get_next_rmb(lgr, &buf_lst, buf_pos);
        }
        len += i * sizeof(ext->rt[0]);
 out:
index 4380d32f5a5f96205d486dea4ff763435bc2e95d..9a2f3638d161d2ff7d7261835a5b13be63b11701 100644 (file)
@@ -267,9 +267,9 @@ int smc_rx_wait(struct smc_sock *smc, long *timeo,
        sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
        add_wait_queue(sk_sleep(sk), &wait);
        rc = sk_wait_event(sk, timeo,
-                          sk->sk_err ||
+                          READ_ONCE(sk->sk_err) ||
                           cflags->peer_conn_abort ||
-                          sk->sk_shutdown & RCV_SHUTDOWN ||
+                          READ_ONCE(sk->sk_shutdown) & RCV_SHUTDOWN ||
                           conn->killed ||
                           fcrit(conn),
                           &wait);
index f4b6a71ac488a40e1a36abe4562017fff7e98739..45128443f1f10ff8bea1dc65214c1db3beefc135 100644 (file)
@@ -113,8 +113,8 @@ static int smc_tx_wait(struct smc_sock *smc, int flags)
                        break; /* at least 1 byte of free & no urgent data */
                set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
                sk_wait_event(sk, &timeo,
-                             sk->sk_err ||
-                             (sk->sk_shutdown & SEND_SHUTDOWN) ||
+                             READ_ONCE(sk->sk_err) ||
+                             (READ_ONCE(sk->sk_shutdown) & SEND_SHUTDOWN) ||
                              smc_cdc_rxed_any_close(conn) ||
                              (atomic_read(&conn->sndbuf_space) &&
                               !conn->urg_tx_pend),
index a7b4b37d86df7a9232d582a14863c05b5fd34b68..b7e01d0fe0824d1f277c1fe70f68f09a10319832 100644 (file)
@@ -2911,7 +2911,7 @@ static int do_recvmmsg(int fd, struct mmsghdr __user *mmsg,
                 * error to return on the next call or if the
                 * app asks about it using getsockopt(SO_ERROR).
                 */
-               sock->sk->sk_err = -err;
+               WRITE_ONCE(sock->sk->sk_err, -err);
        }
 out_put:
        fput_light(sock->file, fput_needed);
index 212c5d57465a1bf56afc96af1e91d135ca6e1325..9734e1d9f991f85df5157c7580daddf732bfa258 100644 (file)
@@ -639,6 +639,16 @@ gss_krb5_cts_crypt(struct crypto_sync_skcipher *cipher, struct xdr_buf *buf,
 
        ret = write_bytes_to_xdr_buf(buf, offset, data, len);
 
+#if IS_ENABLED(CONFIG_KUNIT)
+       /*
+        * CBC-CTS does not define an output IV but RFC 3962 defines it as the
+        * penultimate block of ciphertext, so copy that into the IV buffer
+        * before returning.
+        */
+       if (encrypt)
+               memcpy(iv, data, crypto_sync_skcipher_ivsize(cipher));
+#endif
+
 out:
        kfree(data);
        return ret;
index c8321de341eea31430f3ae74cabe21ffe6564f19..6debf4fd42d4e8566f9c21f74cac24269fab012a 100644 (file)
@@ -927,11 +927,10 @@ static void __rpc_execute(struct rpc_task *task)
                 */
                do_action = task->tk_action;
                /* Tasks with an RPC error status should exit */
-               if (do_action != rpc_exit_task &&
+               if (do_action && do_action != rpc_exit_task &&
                    (status = READ_ONCE(task->tk_rpc_status)) != 0) {
                        task->tk_status = status;
-                       if (do_action != NULL)
-                               do_action = rpc_exit_task;
+                       do_action = rpc_exit_task;
                }
                /* Callbacks override all actions */
                if (task->tk_callback) {
index 26367cf4c17a0d7e411126270864007eef873a4d..79967b6925bd6178d27f65f26b675fcbe9e2cdcd 100644 (file)
@@ -1052,7 +1052,7 @@ static int __svc_register(struct net *net, const char *progname,
 #endif
        }
 
-       trace_svc_register(progname, version, protocol, port, family, error);
+       trace_svc_register(progname, version, family, protocol, port, error);
        return error;
 }
 
@@ -1416,7 +1416,7 @@ err_bad_rpc:
        /* Only RPCv2 supported */
        xdr_stream_encode_u32(xdr, RPC_VERSION);
        xdr_stream_encode_u32(xdr, RPC_VERSION);
-       goto sendit;
+       return 1;       /* don't wrap */
 
 err_bad_auth:
        dprintk("svc: authentication failed (%d)\n",
@@ -1432,7 +1432,7 @@ err_bad_auth:
 err_bad_prog:
        dprintk("svc: unknown program %d\n", rqstp->rq_prog);
        serv->sv_stats->rpcbadfmt++;
-       xdr_stream_encode_u32(xdr, RPC_PROG_UNAVAIL);
+       *rqstp->rq_accept_statp = rpc_prog_unavail;
        goto sendit;
 
 err_bad_vers:
@@ -1440,7 +1440,12 @@ err_bad_vers:
                       rqstp->rq_vers, rqstp->rq_prog, progp->pg_name);
 
        serv->sv_stats->rpcbadfmt++;
-       xdr_stream_encode_u32(xdr, RPC_PROG_MISMATCH);
+       *rqstp->rq_accept_statp = rpc_prog_mismatch;
+
+       /*
+        * svc_authenticate() has already added the verifier and
+        * advanced the stream just past rq_accept_statp.
+        */
        xdr_stream_encode_u32(xdr, process.mismatch.lovers);
        xdr_stream_encode_u32(xdr, process.mismatch.hivers);
        goto sendit;
@@ -1449,19 +1454,19 @@ err_bad_proc:
        svc_printk(rqstp, "unknown procedure (%d)\n", rqstp->rq_proc);
 
        serv->sv_stats->rpcbadfmt++;
-       xdr_stream_encode_u32(xdr, RPC_PROC_UNAVAIL);
+       *rqstp->rq_accept_statp = rpc_proc_unavail;
        goto sendit;
 
 err_garbage_args:
        svc_printk(rqstp, "failed to decode RPC header\n");
 
        serv->sv_stats->rpcbadfmt++;
-       xdr_stream_encode_u32(xdr, RPC_GARBAGE_ARGS);
+       *rqstp->rq_accept_statp = rpc_garbage_args;
        goto sendit;
 
 err_system_err:
        serv->sv_stats->rpcbadfmt++;
-       xdr_stream_encode_u32(xdr, RPC_SYSTEM_ERR);
+       *rqstp->rq_accept_statp = rpc_system_err;
        goto sendit;
 }
 
index 84e5d7d31481bd579e5c09496ff128d2a1e0564d..13a14897bc17d61308d7af6bcad4e41e214a815b 100644 (file)
@@ -532,13 +532,23 @@ void svc_reserve(struct svc_rqst *rqstp, int space)
 }
 EXPORT_SYMBOL_GPL(svc_reserve);
 
+static void free_deferred(struct svc_xprt *xprt, struct svc_deferred_req *dr)
+{
+       if (!dr)
+               return;
+
+       xprt->xpt_ops->xpo_release_ctxt(xprt, dr->xprt_ctxt);
+       kfree(dr);
+}
+
 static void svc_xprt_release(struct svc_rqst *rqstp)
 {
        struct svc_xprt *xprt = rqstp->rq_xprt;
 
-       xprt->xpt_ops->xpo_release_rqst(rqstp);
+       xprt->xpt_ops->xpo_release_ctxt(xprt, rqstp->rq_xprt_ctxt);
+       rqstp->rq_xprt_ctxt = NULL;
 
-       kfree(rqstp->rq_deferred);
+       free_deferred(xprt, rqstp->rq_deferred);
        rqstp->rq_deferred = NULL;
 
        svc_rqst_release_pages(rqstp);
@@ -1054,7 +1064,7 @@ static void svc_delete_xprt(struct svc_xprt *xprt)
        spin_unlock_bh(&serv->sv_lock);
 
        while ((dr = svc_deferred_dequeue(xprt)) != NULL)
-               kfree(dr);
+               free_deferred(xprt, dr);
 
        call_xpt_users(xprt);
        svc_xprt_put(xprt);
@@ -1176,8 +1186,8 @@ static void svc_revisit(struct cache_deferred_req *dreq, int too_many)
        if (too_many || test_bit(XPT_DEAD, &xprt->xpt_flags)) {
                spin_unlock(&xprt->xpt_lock);
                trace_svc_defer_drop(dr);
+               free_deferred(xprt, dr);
                svc_xprt_put(xprt);
-               kfree(dr);
                return;
        }
        dr->xprt = NULL;
@@ -1222,14 +1232,14 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req)
                dr->addrlen = rqstp->rq_addrlen;
                dr->daddr = rqstp->rq_daddr;
                dr->argslen = rqstp->rq_arg.len >> 2;
-               dr->xprt_ctxt = rqstp->rq_xprt_ctxt;
-               rqstp->rq_xprt_ctxt = NULL;
 
                /* back up head to the start of the buffer and copy */
                skip = rqstp->rq_arg.len - rqstp->rq_arg.head[0].iov_len;
                memcpy(dr->args, rqstp->rq_arg.head[0].iov_base - skip,
                       dr->argslen << 2);
        }
+       dr->xprt_ctxt = rqstp->rq_xprt_ctxt;
+       rqstp->rq_xprt_ctxt = NULL;
        trace_svc_defer(rqstp);
        svc_xprt_get(rqstp->rq_xprt);
        dr->xprt = rqstp->rq_xprt;
@@ -1262,6 +1272,8 @@ static noinline int svc_deferred_recv(struct svc_rqst *rqstp)
        rqstp->rq_daddr       = dr->daddr;
        rqstp->rq_respages    = rqstp->rq_pages;
        rqstp->rq_xprt_ctxt   = dr->xprt_ctxt;
+
+       dr->xprt_ctxt = NULL;
        svc_xprt_received(rqstp->rq_xprt);
        return dr->argslen << 2;
 }
index a51c9b989d58a784edf712d6f560e5c0983b7fb1..f77cebe2c07130a93816cd1a02c01a2c25ac8a35 100644 (file)
@@ -121,27 +121,27 @@ static void svc_reclassify_socket(struct socket *sock)
 #endif
 
 /**
- * svc_tcp_release_rqst - Release transport-related resources
- * @rqstp: request structure with resources to be released
+ * svc_tcp_release_ctxt - Release transport-related resources
+ * @xprt: the transport which owned the context
+ * @ctxt: the context from rqstp->rq_xprt_ctxt or dr->xprt_ctxt
  *
  */
-static void svc_tcp_release_rqst(struct svc_rqst *rqstp)
+static void svc_tcp_release_ctxt(struct svc_xprt *xprt, void *ctxt)
 {
 }
 
 /**
- * svc_udp_release_rqst - Release transport-related resources
- * @rqstp: request structure with resources to be released
+ * svc_udp_release_ctxt - Release transport-related resources
+ * @xprt: the transport which owned the context
+ * @ctxt: the context from rqstp->rq_xprt_ctxt or dr->xprt_ctxt
  *
  */
-static void svc_udp_release_rqst(struct svc_rqst *rqstp)
+static void svc_udp_release_ctxt(struct svc_xprt *xprt, void *ctxt)
 {
-       struct sk_buff *skb = rqstp->rq_xprt_ctxt;
+       struct sk_buff *skb = ctxt;
 
-       if (skb) {
-               rqstp->rq_xprt_ctxt = NULL;
+       if (skb)
                consume_skb(skb);
-       }
 }
 
 union svc_pktinfo_u {
@@ -696,7 +696,8 @@ static int svc_udp_sendto(struct svc_rqst *rqstp)
        unsigned int sent;
        int err;
 
-       svc_udp_release_rqst(rqstp);
+       svc_udp_release_ctxt(xprt, rqstp->rq_xprt_ctxt);
+       rqstp->rq_xprt_ctxt = NULL;
 
        svc_set_cmsg_data(rqstp, cmh);
 
@@ -768,7 +769,7 @@ static const struct svc_xprt_ops svc_udp_ops = {
        .xpo_recvfrom = svc_udp_recvfrom,
        .xpo_sendto = svc_udp_sendto,
        .xpo_result_payload = svc_sock_result_payload,
-       .xpo_release_rqst = svc_udp_release_rqst,
+       .xpo_release_ctxt = svc_udp_release_ctxt,
        .xpo_detach = svc_sock_detach,
        .xpo_free = svc_sock_free,
        .xpo_has_wspace = svc_udp_has_wspace,
@@ -895,6 +896,9 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
                trace_svcsock_accept_err(xprt, serv->sv_name, err);
                return NULL;
        }
+       if (IS_ERR(sock_alloc_file(newsock, O_NONBLOCK, NULL)))
+               return NULL;
+
        set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags);
 
        err = kernel_getpeername(newsock, sin);
@@ -935,7 +939,7 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
        return &newsvsk->sk_xprt;
 
 failed:
-       sock_release(newsock);
+       sockfd_put(newsock);
        return NULL;
 }
 
@@ -1298,7 +1302,8 @@ static int svc_tcp_sendto(struct svc_rqst *rqstp)
        unsigned int sent;
        int err;
 
-       svc_tcp_release_rqst(rqstp);
+       svc_tcp_release_ctxt(xprt, rqstp->rq_xprt_ctxt);
+       rqstp->rq_xprt_ctxt = NULL;
 
        atomic_inc(&svsk->sk_sendqlen);
        mutex_lock(&xprt->xpt_mutex);
@@ -1343,7 +1348,7 @@ static const struct svc_xprt_ops svc_tcp_ops = {
        .xpo_recvfrom = svc_tcp_recvfrom,
        .xpo_sendto = svc_tcp_sendto,
        .xpo_result_payload = svc_sock_result_payload,
-       .xpo_release_rqst = svc_tcp_release_rqst,
+       .xpo_release_ctxt = svc_tcp_release_ctxt,
        .xpo_detach = svc_tcp_sock_detach,
        .xpo_free = svc_sock_free,
        .xpo_has_wspace = svc_tcp_has_wspace,
@@ -1430,7 +1435,6 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
                                                struct socket *sock,
                                                int flags)
 {
-       struct file     *filp = NULL;
        struct svc_sock *svsk;
        struct sock     *inet;
        int             pmap_register = !(flags & SVC_SOCK_ANONYMOUS);
@@ -1439,14 +1443,6 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
        if (!svsk)
                return ERR_PTR(-ENOMEM);
 
-       if (!sock->file) {
-               filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
-               if (IS_ERR(filp)) {
-                       kfree(svsk);
-                       return ERR_CAST(filp);
-               }
-       }
-
        inet = sock->sk;
 
        if (pmap_register) {
@@ -1456,8 +1452,6 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
                                     inet->sk_protocol,
                                     ntohs(inet_sk(inet)->inet_sport));
                if (err < 0) {
-                       if (filp)
-                               fput(filp);
                        kfree(svsk);
                        return ERR_PTR(err);
                }
@@ -1486,25 +1480,10 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
        return svsk;
 }
 
-bool svc_alien_sock(struct net *net, int fd)
-{
-       int err;
-       struct socket *sock = sockfd_lookup(fd, &err);
-       bool ret = false;
-
-       if (!sock)
-               goto out;
-       if (sock_net(sock->sk) != net)
-               ret = true;
-       sockfd_put(sock);
-out:
-       return ret;
-}
-EXPORT_SYMBOL_GPL(svc_alien_sock);
-
 /**
  * svc_addsock - add a listener socket to an RPC service
  * @serv: pointer to RPC service to which to add a new listener
+ * @net: caller's network namespace
  * @fd: file descriptor of the new listener
  * @name_return: pointer to buffer to fill in with name of listener
  * @len: size of the buffer
@@ -1514,8 +1493,8 @@ EXPORT_SYMBOL_GPL(svc_alien_sock);
  * Name is terminated with '\n'.  On error, returns a negative errno
  * value.
  */
-int svc_addsock(struct svc_serv *serv, const int fd, char *name_return,
-               const size_t len, const struct cred *cred)
+int svc_addsock(struct svc_serv *serv, struct net *net, const int fd,
+               char *name_return, const size_t len, const struct cred *cred)
 {
        int err = 0;
        struct socket *so = sockfd_lookup(fd, &err);
@@ -1526,6 +1505,9 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return,
 
        if (!so)
                return err;
+       err = -EINVAL;
+       if (sock_net(so->sk) != net)
+               goto out;
        err = -EAFNOSUPPORT;
        if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6))
                goto out;
index 1c658fa4306335dc01cf871078a3d13726205350..a22fe7587fa6f2cc4624d263076fb1e90ea5b04f 100644 (file)
@@ -239,21 +239,20 @@ void svc_rdma_recv_ctxt_put(struct svcxprt_rdma *rdma,
 }
 
 /**
- * svc_rdma_release_rqst - Release transport-specific per-rqst resources
- * @rqstp: svc_rqst being released
+ * svc_rdma_release_ctxt - Release transport-specific per-rqst resources
+ * @xprt: the transport which owned the context
+ * @vctxt: the context from rqstp->rq_xprt_ctxt or dr->xprt_ctxt
  *
  * 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)
+void svc_rdma_release_ctxt(struct svc_xprt *xprt, void *vctxt)
 {
-       struct svc_rdma_recv_ctxt *ctxt = rqstp->rq_xprt_ctxt;
-       struct svc_xprt *xprt = rqstp->rq_xprt;
+       struct svc_rdma_recv_ctxt *ctxt = vctxt;
        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);
 }
index 416b298f74ddbbcf219505467e2a4c34bea9c6ae..ca04f7a6a085ce55cb9e09f860dd979f5cfac87c 100644 (file)
@@ -80,7 +80,7 @@ static const struct svc_xprt_ops svc_rdma_ops = {
        .xpo_recvfrom = svc_rdma_recvfrom,
        .xpo_sendto = svc_rdma_sendto,
        .xpo_result_payload = svc_rdma_result_payload,
-       .xpo_release_rqst = svc_rdma_release_rqst,
+       .xpo_release_ctxt = svc_rdma_release_ctxt,
        .xpo_detach = svc_rdma_detach,
        .xpo_free = svc_rdma_free,
        .xpo_has_wspace = svc_rdma_has_wspace,
index 35cac7733fd3abca49e6a8eb93cd0c95efd9147e..53881406e2006c0204e7e87e6604759a9f697c61 100644 (file)
@@ -541,6 +541,19 @@ int tipc_bearer_mtu(struct net *net, u32 bearer_id)
        return mtu;
 }
 
+int tipc_bearer_min_mtu(struct net *net, u32 bearer_id)
+{
+       int mtu = TIPC_MIN_BEARER_MTU;
+       struct tipc_bearer *b;
+
+       rcu_read_lock();
+       b = bearer_get(net, bearer_id);
+       if (b)
+               mtu += b->encap_hlen;
+       rcu_read_unlock();
+       return mtu;
+}
+
 /* tipc_bearer_xmit_skb - sends buffer to destination over bearer
  */
 void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id,
@@ -1138,8 +1151,8 @@ int __tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info)
                                return -EINVAL;
                        }
 #ifdef CONFIG_TIPC_MEDIA_UDP
-                       if (tipc_udp_mtu_bad(nla_get_u32
-                                            (props[TIPC_NLA_PROP_MTU]))) {
+                       if (nla_get_u32(props[TIPC_NLA_PROP_MTU]) <
+                           b->encap_hlen + TIPC_MIN_BEARER_MTU) {
                                NL_SET_ERR_MSG(info->extack,
                                               "MTU value is out-of-range");
                                return -EINVAL;
index 490ad6e5f7a3c8d0fed649f65cea92b7948c3e69..bd0cc5c287ef8acaed47d98880b76bfffa3c25f3 100644 (file)
@@ -146,6 +146,7 @@ struct tipc_media {
  * @identity: array index of this bearer within TIPC bearer array
  * @disc: ptr to link setup request
  * @net_plane: network plane ('A' through 'H') currently associated with bearer
+ * @encap_hlen: encap headers length
  * @up: bearer up flag (bit 0)
  * @refcnt: tipc_bearer reference counter
  *
@@ -170,6 +171,7 @@ struct tipc_bearer {
        u32 identity;
        struct tipc_discoverer *disc;
        char net_plane;
+       u16 encap_hlen;
        unsigned long up;
        refcount_t refcnt;
 };
@@ -232,6 +234,7 @@ int tipc_bearer_setup(void);
 void tipc_bearer_cleanup(void);
 void tipc_bearer_stop(struct net *net);
 int tipc_bearer_mtu(struct net *net, u32 bearer_id);
+int tipc_bearer_min_mtu(struct net *net, u32 bearer_id);
 bool tipc_bearer_bcast_support(struct net *net, u32 bearer_id);
 void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id,
                          struct sk_buff *skb,
index b3ce24823f50354c694da21f6c3dbad25f249294..2eff1c7949cbcc5f97855bb58373ec3595496aa0 100644 (file)
@@ -2200,7 +2200,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
        struct tipc_msg *hdr = buf_msg(skb);
        struct tipc_gap_ack_blks *ga = NULL;
        bool reply = msg_probe(hdr), retransmitted = false;
-       u32 dlen = msg_data_sz(hdr), glen = 0;
+       u32 dlen = msg_data_sz(hdr), glen = 0, msg_max;
        u16 peers_snd_nxt =  msg_next_sent(hdr);
        u16 peers_tol = msg_link_tolerance(hdr);
        u16 peers_prio = msg_linkprio(hdr);
@@ -2239,6 +2239,9 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
        switch (mtyp) {
        case RESET_MSG:
        case ACTIVATE_MSG:
+               msg_max = msg_max_pkt(hdr);
+               if (msg_max < tipc_bearer_min_mtu(l->net, l->bearer_id))
+                       break;
                /* Complete own link name with peer's interface name */
                if_name =  strrchr(l->name, ':') + 1;
                if (sizeof(l->name) - (if_name - l->name) <= TIPC_MAX_IF_NAME)
@@ -2283,8 +2286,8 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
                l->peer_session = msg_session(hdr);
                l->in_session = true;
                l->peer_bearer_id = msg_bearer_id(hdr);
-               if (l->mtu > msg_max_pkt(hdr))
-                       l->mtu = msg_max_pkt(hdr);
+               if (l->mtu > msg_max)
+                       l->mtu = msg_max;
                break;
 
        case STATE_MSG:
index 37edfe10f8c6ffea553a54b24b9513bd2e18d694..dd73d71c02a99df7acd7ce3fb0d4a96d1778171d 100644 (file)
@@ -314,9 +314,9 @@ static void tsk_rej_rx_queue(struct sock *sk, int error)
                tipc_sk_respond(sk, skb, error);
 }
 
-static bool tipc_sk_connected(struct sock *sk)
+static bool tipc_sk_connected(const struct sock *sk)
 {
-       return sk->sk_state == TIPC_ESTABLISHED;
+       return READ_ONCE(sk->sk_state) == TIPC_ESTABLISHED;
 }
 
 /* tipc_sk_type_connectionless - check if the socket is datagram socket
index c2bb818704c8ff19c03030816857e4eb06a020bf..0a85244fd61885aca6dd72a8bb54ba7678dff319 100644 (file)
@@ -738,8 +738,8 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
                        udp_conf.local_ip.s_addr = local.ipv4.s_addr;
                udp_conf.use_udp_checksums = false;
                ub->ifindex = dev->ifindex;
-               if (tipc_mtu_bad(dev, sizeof(struct iphdr) +
-                                     sizeof(struct udphdr))) {
+               b->encap_hlen = sizeof(struct iphdr) + sizeof(struct udphdr);
+               if (tipc_mtu_bad(dev, b->encap_hlen)) {
                        err = -EINVAL;
                        goto err;
                }
@@ -760,6 +760,7 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
                else
                        udp_conf.local_ip6 = local.ipv6;
                ub->ifindex = dev->ifindex;
+               b->encap_hlen = sizeof(struct ipv6hdr) + sizeof(struct udphdr);
                b->mtu = 1280;
 #endif
        } else {
index 804c3880d0288c9fde321d37ffa27ae9b9d79c95..0672acab27731d14214a6387e29bd3d51f3f19d9 100644 (file)
@@ -167,6 +167,11 @@ static inline bool tls_strp_msg_ready(struct tls_sw_context_rx *ctx)
        return ctx->strp.msg_ready;
 }
 
+static inline bool tls_strp_msg_mixed_decrypted(struct tls_sw_context_rx *ctx)
+{
+       return ctx->strp.mixed_decrypted;
+}
+
 #ifdef CONFIG_TLS_DEVICE
 int tls_device_init(void);
 void tls_device_cleanup(void);
index a7cc4f9faac28ce10d3088570d2a44f5bef9a8e1..bf69c9d6d06c05fa3c1a99f8a08e69434760a9a7 100644 (file)
@@ -1007,20 +1007,14 @@ int tls_device_decrypted(struct sock *sk, struct tls_context *tls_ctx)
        struct tls_sw_context_rx *sw_ctx = tls_sw_ctx_rx(tls_ctx);
        struct sk_buff *skb = tls_strp_msg(sw_ctx);
        struct strp_msg *rxm = strp_msg(skb);
-       int is_decrypted = skb->decrypted;
-       int is_encrypted = !is_decrypted;
-       struct sk_buff *skb_iter;
-       int left;
-
-       left = rxm->full_len - skb->len;
-       /* Check if all the data is decrypted already */
-       skb_iter = skb_shinfo(skb)->frag_list;
-       while (skb_iter && left > 0) {
-               is_decrypted &= skb_iter->decrypted;
-               is_encrypted &= !skb_iter->decrypted;
-
-               left -= skb_iter->len;
-               skb_iter = skb_iter->next;
+       int is_decrypted, is_encrypted;
+
+       if (!tls_strp_msg_mixed_decrypted(sw_ctx)) {
+               is_decrypted = skb->decrypted;
+               is_encrypted = !is_decrypted;
+       } else {
+               is_decrypted = 0;
+               is_encrypted = 0;
        }
 
        trace_tls_device_decrypted(sk, tcp_sk(sk)->copied_seq - rxm->full_len,
index b32c112984dd9567fd9d07cc6850f234c1914a43..f2e7302a4d96b9f7ddd4ddf9afb6cac5672886e6 100644 (file)
@@ -111,7 +111,8 @@ int wait_on_pending_writer(struct sock *sk, long *timeo)
                        break;
                }
 
-               if (sk_wait_event(sk, timeo, !sk->sk_write_pending, &wait))
+               if (sk_wait_event(sk, timeo,
+                                 !READ_ONCE(sk->sk_write_pending), &wait))
                        break;
        }
        remove_wait_queue(sk_sleep(sk), &wait);
index 955ac3e0bf4d3f5b3eac98528c626c762cf1c237..f37f4a0fcd3c2f0108de4d8e9daf10e28fe0ef1a 100644 (file)
@@ -20,7 +20,9 @@ static void tls_strp_abort_strp(struct tls_strparser *strp, int err)
        strp->stopped = 1;
 
        /* Report an error on the lower socket */
-       strp->sk->sk_err = -err;
+       WRITE_ONCE(strp->sk->sk_err, -err);
+       /* Paired with smp_rmb() in tcp_poll() */
+       smp_wmb();
        sk_error_report(strp->sk);
 }
 
@@ -29,34 +31,50 @@ static void tls_strp_anchor_free(struct tls_strparser *strp)
        struct skb_shared_info *shinfo = skb_shinfo(strp->anchor);
 
        DEBUG_NET_WARN_ON_ONCE(atomic_read(&shinfo->dataref) != 1);
-       shinfo->frag_list = NULL;
+       if (!strp->copy_mode)
+               shinfo->frag_list = NULL;
        consume_skb(strp->anchor);
        strp->anchor = NULL;
 }
 
-/* Create a new skb with the contents of input copied to its page frags */
-static struct sk_buff *tls_strp_msg_make_copy(struct tls_strparser *strp)
+static struct sk_buff *
+tls_strp_skb_copy(struct tls_strparser *strp, struct sk_buff *in_skb,
+                 int offset, int len)
 {
-       struct strp_msg *rxm;
        struct sk_buff *skb;
-       int i, err, offset;
+       int i, err;
 
-       skb = alloc_skb_with_frags(0, strp->stm.full_len, TLS_PAGE_ORDER,
+       skb = alloc_skb_with_frags(0, len, TLS_PAGE_ORDER,
                                   &err, strp->sk->sk_allocation);
        if (!skb)
                return NULL;
 
-       offset = strp->stm.offset;
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
-               WARN_ON_ONCE(skb_copy_bits(strp->anchor, offset,
+               WARN_ON_ONCE(skb_copy_bits(in_skb, offset,
                                           skb_frag_address(frag),
                                           skb_frag_size(frag)));
                offset += skb_frag_size(frag);
        }
 
-       skb_copy_header(skb, strp->anchor);
+       skb->len = len;
+       skb->data_len = len;
+       skb_copy_header(skb, in_skb);
+       return skb;
+}
+
+/* Create a new skb with the contents of input copied to its page frags */
+static struct sk_buff *tls_strp_msg_make_copy(struct tls_strparser *strp)
+{
+       struct strp_msg *rxm;
+       struct sk_buff *skb;
+
+       skb = tls_strp_skb_copy(strp, strp->anchor, strp->stm.offset,
+                               strp->stm.full_len);
+       if (!skb)
+               return NULL;
+
        rxm = strp_msg(skb);
        rxm->offset = 0;
        return skb;
@@ -180,22 +198,22 @@ static void tls_strp_flush_anchor_copy(struct tls_strparser *strp)
        for (i = 0; i < shinfo->nr_frags; i++)
                __skb_frag_unref(&shinfo->frags[i], false);
        shinfo->nr_frags = 0;
+       if (strp->copy_mode) {
+               kfree_skb_list(shinfo->frag_list);
+               shinfo->frag_list = NULL;
+       }
        strp->copy_mode = 0;
+       strp->mixed_decrypted = 0;
 }
 
-static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
-                          unsigned int offset, size_t in_len)
+static int tls_strp_copyin_frag(struct tls_strparser *strp, struct sk_buff *skb,
+                               struct sk_buff *in_skb, unsigned int offset,
+                               size_t in_len)
 {
-       struct tls_strparser *strp = (struct tls_strparser *)desc->arg.data;
-       struct sk_buff *skb;
-       skb_frag_t *frag;
        size_t len, chunk;
+       skb_frag_t *frag;
        int sz;
 
-       if (strp->msg_ready)
-               return 0;
-
-       skb = strp->anchor;
        frag = &skb_shinfo(skb)->frags[skb->len / PAGE_SIZE];
 
        len = in_len;
@@ -208,19 +226,26 @@ static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
                                           skb_frag_size(frag),
                                           chunk));
 
-               sz = tls_rx_msg_size(strp, strp->anchor);
-               if (sz < 0) {
-                       desc->error = sz;
-                       return 0;
-               }
-
-               /* We may have over-read, sz == 0 is guaranteed under-read */
-               if (sz > 0)
-                       chunk = min_t(size_t, chunk, sz - skb->len);
-
                skb->len += chunk;
                skb->data_len += chunk;
                skb_frag_size_add(frag, chunk);
+
+               sz = tls_rx_msg_size(strp, skb);
+               if (sz < 0)
+                       return sz;
+
+               /* We may have over-read, sz == 0 is guaranteed under-read */
+               if (unlikely(sz && sz < skb->len)) {
+                       int over = skb->len - sz;
+
+                       WARN_ON_ONCE(over > chunk);
+                       skb->len -= over;
+                       skb->data_len -= over;
+                       skb_frag_size_add(frag, -over);
+
+                       chunk -= over;
+               }
+
                frag++;
                len -= chunk;
                offset += chunk;
@@ -247,15 +272,99 @@ static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
                offset += chunk;
        }
 
-       if (strp->stm.full_len == skb->len) {
+read_done:
+       return in_len - len;
+}
+
+static int tls_strp_copyin_skb(struct tls_strparser *strp, struct sk_buff *skb,
+                              struct sk_buff *in_skb, unsigned int offset,
+                              size_t in_len)
+{
+       struct sk_buff *nskb, *first, *last;
+       struct skb_shared_info *shinfo;
+       size_t chunk;
+       int sz;
+
+       if (strp->stm.full_len)
+               chunk = strp->stm.full_len - skb->len;
+       else
+               chunk = TLS_MAX_PAYLOAD_SIZE + PAGE_SIZE;
+       chunk = min(chunk, in_len);
+
+       nskb = tls_strp_skb_copy(strp, in_skb, offset, chunk);
+       if (!nskb)
+               return -ENOMEM;
+
+       shinfo = skb_shinfo(skb);
+       if (!shinfo->frag_list) {
+               shinfo->frag_list = nskb;
+               nskb->prev = nskb;
+       } else {
+               first = shinfo->frag_list;
+               last = first->prev;
+               last->next = nskb;
+               first->prev = nskb;
+       }
+
+       skb->len += chunk;
+       skb->data_len += chunk;
+
+       if (!strp->stm.full_len) {
+               sz = tls_rx_msg_size(strp, skb);
+               if (sz < 0)
+                       return sz;
+
+               /* We may have over-read, sz == 0 is guaranteed under-read */
+               if (unlikely(sz && sz < skb->len)) {
+                       int over = skb->len - sz;
+
+                       WARN_ON_ONCE(over > chunk);
+                       skb->len -= over;
+                       skb->data_len -= over;
+                       __pskb_trim(nskb, nskb->len - over);
+
+                       chunk -= over;
+               }
+
+               strp->stm.full_len = sz;
+       }
+
+       return chunk;
+}
+
+static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
+                          unsigned int offset, size_t in_len)
+{
+       struct tls_strparser *strp = (struct tls_strparser *)desc->arg.data;
+       struct sk_buff *skb;
+       int ret;
+
+       if (strp->msg_ready)
+               return 0;
+
+       skb = strp->anchor;
+       if (!skb->len)
+               skb_copy_decrypted(skb, in_skb);
+       else
+               strp->mixed_decrypted |= !!skb_cmp_decrypted(skb, in_skb);
+
+       if (IS_ENABLED(CONFIG_TLS_DEVICE) && strp->mixed_decrypted)
+               ret = tls_strp_copyin_skb(strp, skb, in_skb, offset, in_len);
+       else
+               ret = tls_strp_copyin_frag(strp, skb, in_skb, offset, in_len);
+       if (ret < 0) {
+               desc->error = ret;
+               ret = 0;
+       }
+
+       if (strp->stm.full_len && strp->stm.full_len == skb->len) {
                desc->count = 0;
 
                strp->msg_ready = 1;
                tls_rx_msg_ready(strp);
        }
 
-read_done:
-       return in_len - len;
+       return ret;
 }
 
 static int tls_strp_read_copyin(struct tls_strparser *strp)
@@ -315,15 +424,19 @@ static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort)
        return 0;
 }
 
-static bool tls_strp_check_no_dup(struct tls_strparser *strp)
+static bool tls_strp_check_queue_ok(struct tls_strparser *strp)
 {
        unsigned int len = strp->stm.offset + strp->stm.full_len;
-       struct sk_buff *skb;
+       struct sk_buff *first, *skb;
        u32 seq;
 
-       skb = skb_shinfo(strp->anchor)->frag_list;
-       seq = TCP_SKB_CB(skb)->seq;
+       first = skb_shinfo(strp->anchor)->frag_list;
+       skb = first;
+       seq = TCP_SKB_CB(first)->seq;
 
+       /* Make sure there's no duplicate data in the queue,
+        * and the decrypted status matches.
+        */
        while (skb->len < len) {
                seq += skb->len;
                len -= skb->len;
@@ -331,6 +444,8 @@ static bool tls_strp_check_no_dup(struct tls_strparser *strp)
 
                if (TCP_SKB_CB(skb)->seq != seq)
                        return false;
+               if (skb_cmp_decrypted(first, skb))
+                       return false;
        }
 
        return true;
@@ -411,7 +526,7 @@ static int tls_strp_read_sock(struct tls_strparser *strp)
                        return tls_strp_read_copy(strp, true);
        }
 
-       if (!tls_strp_check_no_dup(strp))
+       if (!tls_strp_check_queue_ok(strp))
                return tls_strp_read_copy(strp, false);
 
        strp->msg_ready = 1;
index 635b8bf6b937c1d362c62a527d9656c11e97df6b..1a53c8f481e9a40d835881233eda1d2b36da9b7a 100644 (file)
@@ -70,7 +70,9 @@ noinline void tls_err_abort(struct sock *sk, int err)
 {
        WARN_ON_ONCE(err >= 0);
        /* sk->sk_err should contain a positive error code. */
-       sk->sk_err = -err;
+       WRITE_ONCE(sk->sk_err, -err);
+       /* Paired with smp_rmb() in tcp_poll() */
+       smp_wmb();
        sk_error_report(sk);
 }
 
@@ -2304,10 +2306,14 @@ static void tls_data_ready(struct sock *sk)
        struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
        struct sk_psock *psock;
+       gfp_t alloc_save;
 
        trace_sk_data_ready(sk);
 
+       alloc_save = sk->sk_allocation;
+       sk->sk_allocation = GFP_ATOMIC;
        tls_strp_data_ready(&ctx->strp);
+       sk->sk_allocation = alloc_save;
 
        psock = sk_psock_get(sk);
        if (psock) {
index fb31e8a4409ed979e4443e7d3d392a5e0f2c424b..e7728b57a8c70ed3ea9f5a268cb9cc1238168bf4 100644 (file)
@@ -603,7 +603,7 @@ static void unix_release_sock(struct sock *sk, int embrion)
        /* Clear state */
        unix_state_lock(sk);
        sock_orphan(sk);
-       sk->sk_shutdown = SHUTDOWN_MASK;
+       WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);
        path         = u->path;
        u->path.dentry = NULL;
        u->path.mnt = NULL;
@@ -628,7 +628,7 @@ static void unix_release_sock(struct sock *sk, int embrion)
                if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
                        unix_state_lock(skpair);
                        /* No more writes */
-                       skpair->sk_shutdown = SHUTDOWN_MASK;
+                       WRITE_ONCE(skpair->sk_shutdown, SHUTDOWN_MASK);
                        if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
                                WRITE_ONCE(skpair->sk_err, ECONNRESET);
                        unix_state_unlock(skpair);
@@ -1442,7 +1442,7 @@ static long unix_wait_for_peer(struct sock *other, long timeo)
 
        sched = !sock_flag(other, SOCK_DEAD) &&
                !(other->sk_shutdown & RCV_SHUTDOWN) &&
-               unix_recvq_full(other);
+               unix_recvq_full_lockless(other);
 
        unix_state_unlock(other);
 
@@ -2553,7 +2553,7 @@ static int unix_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
 {
        struct unix_sock *u = unix_sk(sk);
        struct sk_buff *skb;
-       int err, copied;
+       int err;
 
        mutex_lock(&u->iolock);
        skb = skb_recv_datagram(sk, MSG_DONTWAIT, &err);
@@ -2561,10 +2561,7 @@ static int unix_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
        if (!skb)
                return err;
 
-       copied = recv_actor(sk, skb);
-       kfree_skb(skb);
-
-       return copied;
+       return recv_actor(sk, skb);
 }
 
 /*
@@ -3008,7 +3005,7 @@ static int unix_shutdown(struct socket *sock, int mode)
        ++mode;
 
        unix_state_lock(sk);
-       sk->sk_shutdown |= mode;
+       WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | mode);
        other = unix_peer(sk);
        if (other)
                sock_hold(other);
@@ -3028,7 +3025,7 @@ static int unix_shutdown(struct socket *sock, int mode)
                if (mode&SEND_SHUTDOWN)
                        peer_mode |= RCV_SHUTDOWN;
                unix_state_lock(other);
-               other->sk_shutdown |= peer_mode;
+               WRITE_ONCE(other->sk_shutdown, other->sk_shutdown | peer_mode);
                unix_state_unlock(other);
                other->sk_state_change(other);
                if (peer_mode == SHUTDOWN_MASK)
@@ -3160,16 +3157,18 @@ static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wa
 {
        struct sock *sk = sock->sk;
        __poll_t mask;
+       u8 shutdown;
 
        sock_poll_wait(file, sock, wait);
        mask = 0;
+       shutdown = READ_ONCE(sk->sk_shutdown);
 
        /* exceptional events? */
        if (READ_ONCE(sk->sk_err))
                mask |= EPOLLERR;
-       if (sk->sk_shutdown == SHUTDOWN_MASK)
+       if (shutdown == SHUTDOWN_MASK)
                mask |= EPOLLHUP;
-       if (sk->sk_shutdown & RCV_SHUTDOWN)
+       if (shutdown & RCV_SHUTDOWN)
                mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
 
        /* readable? */
@@ -3203,9 +3202,11 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
        struct sock *sk = sock->sk, *other;
        unsigned int writable;
        __poll_t mask;
+       u8 shutdown;
 
        sock_poll_wait(file, sock, wait);
        mask = 0;
+       shutdown = READ_ONCE(sk->sk_shutdown);
 
        /* exceptional events? */
        if (READ_ONCE(sk->sk_err) ||
@@ -3213,9 +3214,9 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
                mask |= EPOLLERR |
                        (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
 
-       if (sk->sk_shutdown & RCV_SHUTDOWN)
+       if (shutdown & RCV_SHUTDOWN)
                mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
-       if (sk->sk_shutdown == SHUTDOWN_MASK)
+       if (shutdown == SHUTDOWN_MASK)
                mask |= EPOLLHUP;
 
        /* readable? */
index 413407bb646c19afd77f32090a09439e99f53e56..efb8a0937a13b74b3aaa0c2722d4f0e61f29fd5c 100644 (file)
@@ -1462,7 +1462,7 @@ static int vsock_connect(struct socket *sock, struct sockaddr *addr,
                        vsock_transport_cancel_pkt(vsk);
                        vsock_remove_connected(vsk);
                        goto out_wait;
-               } else if (timeout == 0) {
+               } else if ((sk->sk_state != TCP_ESTABLISHED) && (timeout == 0)) {
                        err = -ETIMEDOUT;
                        sk->sk_state = TCP_CLOSE;
                        sock->state = SS_UNCONNECTED;
index e4878551f1402cfb8977d0ac792c92bb8e9b2ccf..b769fc2589315098083f5b2a2c6850438d4265c4 100644 (file)
@@ -1441,7 +1441,6 @@ int virtio_transport_read_skb(struct vsock_sock *vsk, skb_read_actor_t recv_acto
        struct sock *sk = sk_vsock(vsk);
        struct sk_buff *skb;
        int off = 0;
-       int copied;
        int err;
 
        spin_lock_bh(&vvs->rx_lock);
@@ -1454,9 +1453,7 @@ int virtio_transport_read_skb(struct vsock_sock *vsk, skb_read_actor_t recv_acto
        if (!skb)
                return err;
 
-       copied = recv_actor(sk, skb);
-       kfree_skb(skb);
-       return copied;
+       return recv_actor(sk, skb);
 }
 EXPORT_SYMBOL_GPL(virtio_transport_read_skb);
 
index a1382255fab35d9976d2c36a6d915a66e6995cef..c501db7bbdb3d00bcdc76714fc19ed020031163f 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2008 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright 2016      Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
  */
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -540,6 +540,10 @@ static int cfg80211_parse_ap_info(struct cfg80211_colocated_ap *entry,
        /* skip the TBTT offset */
        pos++;
 
+       /* ignore entries with invalid BSSID */
+       if (!is_valid_ether_addr(pos))
+               return -EINVAL;
+
        memcpy(entry->bssid, pos, ETH_ALEN);
        pos += ETH_ALEN;
 
index bef28c6187ebdd0cfc34c8594aab96ac0b13dd24..408f5e55744edd1c865fe679da6bc43e4413f2db 100644 (file)
@@ -378,7 +378,7 @@ int xfrm_dev_policy_add(struct net *net, struct xfrm_policy *xp,
                break;
        default:
                xdo->dev = NULL;
-               dev_put(dev);
+               netdev_put(dev, &xdo->dev_tracker);
                NL_SET_ERR_MSG(extack, "Unrecognized offload direction");
                return -EINVAL;
        }
index 35279c220bd786750da0ead2765a99b290539c5d..1f99dc46902719e6716b0cb93f95d1087d2c8bd8 100644 (file)
@@ -310,52 +310,6 @@ static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet)
        skb->mark = 0;
 }
 
-static int xfrmi_input(struct sk_buff *skb, int nexthdr, __be32 spi,
-                      int encap_type, unsigned short family)
-{
-       struct sec_path *sp;
-
-       sp = skb_sec_path(skb);
-       if (sp && (sp->len || sp->olen) &&
-           !xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family))
-               goto discard;
-
-       XFRM_SPI_SKB_CB(skb)->family = family;
-       if (family == AF_INET) {
-               XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
-               XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
-       } else {
-               XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
-               XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
-       }
-
-       return xfrm_input(skb, nexthdr, spi, encap_type);
-discard:
-       kfree_skb(skb);
-       return 0;
-}
-
-static int xfrmi4_rcv(struct sk_buff *skb)
-{
-       return xfrmi_input(skb, ip_hdr(skb)->protocol, 0, 0, AF_INET);
-}
-
-static int xfrmi6_rcv(struct sk_buff *skb)
-{
-       return xfrmi_input(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
-                          0, 0, AF_INET6);
-}
-
-static int xfrmi4_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
-{
-       return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET);
-}
-
-static int xfrmi6_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
-{
-       return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET6);
-}
-
 static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
 {
        const struct xfrm_mode *inner_mode;
@@ -991,8 +945,8 @@ static struct pernet_operations xfrmi_net_ops = {
 };
 
 static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = {
-       .handler        =       xfrmi6_rcv,
-       .input_handler  =       xfrmi6_input,
+       .handler        =       xfrm6_rcv,
+       .input_handler  =       xfrm_input,
        .cb_handler     =       xfrmi_rcv_cb,
        .err_handler    =       xfrmi6_err,
        .priority       =       10,
@@ -1042,8 +996,8 @@ static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = {
 #endif
 
 static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
-       .handler        =       xfrmi4_rcv,
-       .input_handler  =       xfrmi4_input,
+       .handler        =       xfrm4_rcv,
+       .input_handler  =       xfrm_input,
        .cb_handler     =       xfrmi_rcv_cb,
        .err_handler    =       xfrmi4_err,
        .priority       =       10,
index 5c61ec04b839ba1e0c7da13d96f9804c04b71f53..6d15788b512315f030899998354a7c8f4edc4e8c 100644 (file)
@@ -3312,7 +3312,7 @@ xfrm_secpath_reject(int idx, struct sk_buff *skb, const struct flowi *fl)
 
 static inline int
 xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x,
-             unsigned short family)
+             unsigned short family, u32 if_id)
 {
        if (xfrm_state_kern(x))
                return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, tmpl->encap_family);
@@ -3323,7 +3323,8 @@ xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x,
                (tmpl->allalgs || (tmpl->aalgos & (1<<x->props.aalgo)) ||
                 !(xfrm_id_proto_match(tmpl->id.proto, IPSEC_PROTO_ANY))) &&
                !(x->props.mode != XFRM_MODE_TRANSPORT &&
-                 xfrm_state_addr_cmp(tmpl, x, family));
+                 xfrm_state_addr_cmp(tmpl, x, family)) &&
+               (if_id == 0 || if_id == x->if_id);
 }
 
 /*
@@ -3335,7 +3336,7 @@ xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x,
  */
 static inline int
 xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int start,
-              unsigned short family)
+              unsigned short family, u32 if_id)
 {
        int idx = start;
 
@@ -3345,7 +3346,7 @@ xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int star
        } else
                start = -1;
        for (; idx < sp->len; idx++) {
-               if (xfrm_state_ok(tmpl, sp->xvec[idx], family))
+               if (xfrm_state_ok(tmpl, sp->xvec[idx], family, if_id))
                        return ++idx;
                if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
                        if (start == -1)
@@ -3712,12 +3713,6 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
                }
                xfrm_nr = ti;
 
-               if (net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK &&
-                   !xfrm_nr) {
-                       XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
-                       goto reject;
-               }
-
                if (npols > 1) {
                        xfrm_tmpl_sort(stp, tpp, xfrm_nr, family);
                        tpp = stp;
@@ -3730,7 +3725,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
                 * are implied between each two transformations.
                 */
                for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
-                       k = xfrm_policy_ok(tpp[i], sp, k, family);
+                       k = xfrm_policy_ok(tpp[i], sp, k, family, if_id);
                        if (k < 0) {
                                if (k < -1)
                                        /* "-2 - errored_index" returned */
@@ -3745,9 +3740,6 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
                        goto reject;
                }
 
-               if (if_id)
-                       secpath_reset(skb);
-
                xfrm_pols_put(pols, npols);
                return 1;
        }
index d720e163ae6e5efb8342402f59be0db284fb0663..c34a2a06ca9407230ab66426bf14e39fd04637f4 100644 (file)
@@ -1770,7 +1770,7 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
 }
 
 static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family,
-                        struct netlink_ext_ack *extack)
+                        int dir, struct netlink_ext_ack *extack)
 {
        u16 prev_family;
        int i;
@@ -1796,6 +1796,10 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family,
                switch (ut[i].mode) {
                case XFRM_MODE_TUNNEL:
                case XFRM_MODE_BEET:
+                       if (ut[i].optional && dir == XFRM_POLICY_OUT) {
+                               NL_SET_ERR_MSG(extack, "Mode in optional template not allowed in outbound policy");
+                               return -EINVAL;
+                       }
                        break;
                default:
                        if (ut[i].family != prev_family) {
@@ -1833,7 +1837,7 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family,
 }
 
 static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs,
-                              struct netlink_ext_ack *extack)
+                              int dir, struct netlink_ext_ack *extack)
 {
        struct nlattr *rt = attrs[XFRMA_TMPL];
 
@@ -1844,7 +1848,7 @@ static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs,
                int nr = nla_len(rt) / sizeof(*utmpl);
                int err;
 
-               err = validate_tmpl(nr, utmpl, pol->family, extack);
+               err = validate_tmpl(nr, utmpl, pol->family, dir, extack);
                if (err)
                        return err;
 
@@ -1921,7 +1925,7 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net,
        if (err)
                goto error;
 
-       if (!(err = copy_from_user_tmpl(xp, attrs, extack)))
+       if (!(err = copy_from_user_tmpl(xp, attrs, p->dir, extack)))
                err = copy_from_user_sec_ctx(xp, attrs);
        if (err)
                goto error;
@@ -1980,6 +1984,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 
        if (err) {
                xfrm_dev_policy_delete(xp);
+               xfrm_dev_policy_free(xp);
                security_xfrm_policy_free(xp->security);
                kfree(xp);
                return err;
@@ -3499,7 +3504,7 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt,
                return NULL;
 
        nr = ((len - sizeof(*p)) / sizeof(*ut));
-       if (validate_tmpl(nr, ut, p->sel.family, NULL))
+       if (validate_tmpl(nr, ut, p->sel.family, p->dir, NULL))
                return NULL;
 
        if (p->dir > XFRM_POLICY_OUT)
index b2db430bd3ff3b6abe6e5f9a8f630047baf4de18..bf49ed0d73623f9d45c8a52fc739144bd9c8b51b 100644 (file)
@@ -253,6 +253,13 @@ config SAMPLE_INTEL_MEI
        help
          Build a sample program to work with mei device.
 
+config SAMPLE_TPS6594_PFSM
+       bool "Build example program working with TPS6594 PFSM driver"
+       depends on HEADERS_INSTALL
+       depends on CC_CAN_LINK
+       help
+         Build a sample program to work with PFSM devices.
+
 config SAMPLE_WATCHDOG
        bool "watchdog sample"
        depends on CC_CAN_LINK
index 7727f1a0d6d157c5735ef9a286e59ea43f3fbcf3..0a551c2b33f430d639ad6f420b1e391a0599ccf7 100644 (file)
@@ -31,6 +31,7 @@ obj-$(CONFIG_VIDEO_PCI_SKELETON)      += v4l/
 obj-y                                  += vfio-mdev/
 subdir-$(CONFIG_SAMPLE_VFS)            += vfs
 obj-$(CONFIG_SAMPLE_INTEL_MEI)         += mei/
+obj-$(CONFIG_SAMPLE_TPS6594_PFSM)      += pfsm/
 subdir-$(CONFIG_SAMPLE_WATCHDOG)       += watchdog
 subdir-$(CONFIG_SAMPLE_WATCH_QUEUE)    += watch_queue
 obj-$(CONFIG_SAMPLE_KMEMLEAK)          += kmemleak/
index 6448b78261076266993f7766539ce55df4c578da..bf66277115e2a9c7d1c7e25241bc47925ce48d45 100644 (file)
@@ -498,7 +498,6 @@ int main(int argc, char **argv)
                                        "Option -%c requires an argument.\n\n",
                                        optopt);
                case 'h':
-                       __fallthrough;
                default:
                        Usage();
                        return 0;
diff --git a/samples/pfsm/.gitignore b/samples/pfsm/.gitignore
new file mode 100644 (file)
index 0000000..f350a03
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+/pfsm-wakeup
diff --git a/samples/pfsm/Makefile b/samples/pfsm/Makefile
new file mode 100644 (file)
index 0000000..213e8d9
--- /dev/null
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+userprogs-always-y += pfsm-wakeup
+
+userccflags += -I usr/include
diff --git a/samples/pfsm/pfsm-wakeup.c b/samples/pfsm/pfsm-wakeup.c
new file mode 100644 (file)
index 0000000..299dd9e
--- /dev/null
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TPS6594 PFSM userspace example
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ *
+ * This example shows how to use PFSMs from a userspace application,
+ * on TI j721s2 platform. The PMIC is armed to be triggered by a RTC
+ * alarm to execute state transition (RETENTION to ACTIVE).
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <linux/rtc.h>
+#include <linux/tps6594_pfsm.h>
+
+#define ALARM_DELTA_SEC 30
+
+#define RTC_A "/dev/rtc0"
+
+#define PMIC_NB 3
+#define PMIC_A "/dev/pfsm-0-0x48"
+#define PMIC_B "/dev/pfsm-0-0x4c"
+#define PMIC_C "/dev/pfsm-2-0x58"
+
+static const char * const dev_pfsm[] = {PMIC_A, PMIC_B, PMIC_C};
+
+int main(int argc, char *argv[])
+{
+       int i, ret, fd_rtc, fd_pfsm[PMIC_NB] = { 0 };
+       struct rtc_time rtc_tm;
+       struct pmic_state_opt pmic_opt = { 0 };
+       unsigned long data;
+
+       fd_rtc = open(RTC_A, O_RDONLY);
+       if (fd_rtc < 0) {
+               perror("Failed to open RTC device.");
+               goto out;
+       }
+
+       for (i = 0 ; i < PMIC_NB ; i++) {
+               fd_pfsm[i] = open(dev_pfsm[i], O_RDWR);
+               if (fd_pfsm[i] < 0) {
+                       perror("Failed to open PFSM device.");
+                       goto out;
+               }
+       }
+
+       /* Read RTC date/time */
+       ret = ioctl(fd_rtc, RTC_RD_TIME, &rtc_tm);
+       if (ret < 0) {
+               perror("Failed to read RTC date/time.");
+               goto out;
+       }
+       printf("Current RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n",
+              rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
+              rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
+
+       /* Set RTC alarm to ALARM_DELTA_SEC sec in the future, and check for rollover */
+       rtc_tm.tm_sec += ALARM_DELTA_SEC;
+       if (rtc_tm.tm_sec >= 60) {
+               rtc_tm.tm_sec %= 60;
+               rtc_tm.tm_min++;
+       }
+       if (rtc_tm.tm_min == 60) {
+               rtc_tm.tm_min = 0;
+               rtc_tm.tm_hour++;
+       }
+       if (rtc_tm.tm_hour == 24)
+               rtc_tm.tm_hour = 0;
+       ret = ioctl(fd_rtc, RTC_ALM_SET, &rtc_tm);
+       if (ret < 0) {
+               perror("Failed to set RTC alarm.");
+               goto out;
+       }
+
+       /* Enable alarm interrupts */
+       ret = ioctl(fd_rtc, RTC_AIE_ON, 0);
+       if (ret < 0) {
+               perror("Failed to enable alarm interrupts.");
+               goto out;
+       }
+       printf("Waiting %d seconds for alarm...\n", ALARM_DELTA_SEC);
+
+       /*
+        * Set RETENTION state with options for PMIC_C/B/A respectively.
+        * Since PMIC_A is master, it should be the last one to be configured.
+        */
+       pmic_opt.ddr_retention = 1;
+       for (i = PMIC_NB - 1 ; i >= 0 ; i--) {
+               printf("Set RETENTION state for PMIC_%d.\n", i);
+               sleep(1);
+               ret = ioctl(fd_pfsm[i], PMIC_SET_RETENTION_STATE, &pmic_opt);
+               if (ret < 0) {
+                       perror("Failed to set RETENTION state.");
+                       goto out_reset;
+               }
+       }
+
+       /* This blocks until the alarm ring causes an interrupt */
+       ret = read(fd_rtc, &data, sizeof(unsigned long));
+       if (ret < 0)
+               perror("Failed to get RTC alarm.");
+       else
+               puts("Alarm rang.\n");
+
+out_reset:
+       ioctl(fd_rtc, RTC_AIE_OFF, 0);
+
+       /* Set ACTIVE state for PMIC_A */
+       ioctl(fd_pfsm[0], PMIC_SET_ACTIVE_STATE, 0);
+
+out:
+       for (i = 0 ; i < PMIC_NB ; i++)
+               if (fd_pfsm[i])
+                       close(fd_pfsm[i]);
+
+       if (fd_rtc)
+               close(fd_rtc);
+
+       return 0;
+}
index ea31640b267155eb3e46a0c2489c94fd688f1475..938dba219534aeec47042ebbc14ddcddb0bbb511 100755 (executable)
@@ -98,7 +98,7 @@ all_compiled_sources()
        {
                echo include/generated/autoconf.h
                find $ignore -name "*.cmd" -exec \
-                       sed -n -E 's/^source_.* (.*)/\1/p; s/^  (\S.*) \\/\1/p' {} \+ |
+                       grep -Poh '(?<=^  )\S+|(?<== )\S+[^\\](?=$)' {} \+ |
                awk '!a[$0]++'
        } | xargs realpath -esq $([ -z "$KBUILD_ABS_SRCTREE" ] && echo --relative-to=.) |
        sort -u
index 0aecf9334ec31e9df00fd5d81a06dc202a66327e..8b21520bd4b9fc273b3f07680ca017381951c3de 100644 (file)
@@ -26,5 +26,9 @@ quiet_cmd_flask = GEN     $(obj)/flask.h $(obj)/av_permissions.h
       cmd_flask = $< $(obj)/flask.h $(obj)/av_permissions.h
 
 targets += flask.h av_permissions.h
-$(obj)/flask.h $(obj)/av_permissions.h &: scripts/selinux/genheaders/genheaders FORCE
+# once make >= 4.3 is required, we can use grouped targets in the rule below,
+# which basically involves adding both headers and a '&' before the colon, see
+# the example below:
+#   $(obj)/flask.h $(obj)/av_permissions.h &: scripts/selinux/...
+$(obj)/flask.h: scripts/selinux/genheaders/genheaders FORCE
        $(call if_changed,flask)
index 46e273bd4a7866b7a4661f679833b4ab205c276d..50a6b50f5db4c38374eebd99eaab81161401bda1 100644 (file)
@@ -141,6 +141,14 @@ int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_channel,
 
 void *snd_pcm_plug_buf_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t size);
 void snd_pcm_plug_buf_unlock(struct snd_pcm_substream *plug, void *ptr);
+#else
+
+static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; }
+static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; }
+static inline int snd_pcm_plug_slave_format(int format, const struct snd_mask *format_mask) { return format; }
+
+#endif
+
 snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream,
                                     const char *ptr, snd_pcm_uframes_t size,
                                     int in_kernel);
@@ -151,14 +159,6 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream,
 snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream,
                                     void **bufs, snd_pcm_uframes_t frames);
 
-#else
-
-static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; }
-static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; }
-static inline int snd_pcm_plug_slave_format(int format, const struct snd_mask *format_mask) { return format; }
-
-#endif
-
 #ifdef PLUGIN_DEBUG
 #define pdprintf(fmt, args...) printk(KERN_DEBUG "plugin: " fmt, ##args)
 #else
index a15f55b0dce377002b69e6678b89d011828655ed..295163bb8abb623c03a92a10b30f1b5dc630fa4a 100644 (file)
@@ -259,8 +259,10 @@ int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x)
                return err;
 
        err = init_stream(dg00x, &dg00x->tx_stream);
-       if (err < 0)
+       if (err < 0) {
                destroy_stream(dg00x, &dg00x->rx_stream);
+               return err;
+       }
 
        err = amdtp_domain_init(&dg00x->domain);
        if (err < 0) {
index accc9d279ce5aa248689eb070975a0018b7e040d..6c043fbd606f1759003d861575e53e28f60b612f 100644 (file)
@@ -611,7 +611,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_power_up_pm);
 int snd_hdac_keep_power_up(struct hdac_device *codec)
 {
        if (!atomic_inc_not_zero(&codec->in_pm)) {
-               int ret = pm_runtime_get_if_in_use(&codec->dev);
+               int ret = pm_runtime_get_if_active(&codec->dev, true);
                if (!ret)
                        return -1;
                if (ret < 0)
index 62f45847b351dd6e466730e20ecc01f3285de3ea..7d882b33d45e588beed8aa6add6f5847010ce2db 100644 (file)
@@ -531,7 +531,7 @@ static int load_firmware(struct snd_cs46xx *chip)
        return err;
 }
 
-int snd_cs46xx_download_image(struct snd_cs46xx *chip)
+static __maybe_unused int snd_cs46xx_download_image(struct snd_cs46xx *chip)
 {
        int idx, err;
        unsigned int offset = 0;
index fc114e5224806f44cfffd3797997c17fc0a9087b..dbf7aa88e0e31a48a751e91761cfa644f98ab1c1 100644 (file)
@@ -1155,8 +1155,8 @@ static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
        return path && path->ctls[ctl_type];
 }
 
-static const char * const channel_name[4] = {
-       "Front", "Surround", "CLFE", "Side"
+static const char * const channel_name[] = {
+       "Front", "Surround", "CLFE", "Side", "Back",
 };
 
 /* give some appropriate ctl name prefix for the given line out channel */
@@ -1182,7 +1182,7 @@ static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
 
        /* multi-io channels */
        if (ch >= cfg->line_outs)
-               return channel_name[ch];
+               goto fixed_name;
 
        switch (cfg->line_out_type) {
        case AUTO_PIN_SPEAKER_OUT:
@@ -1234,6 +1234,7 @@ static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
        if (cfg->line_outs == 1 && !spec->multi_ios)
                return "Line Out";
 
+ fixed_name:
        if (ch >= ARRAY_SIZE(channel_name)) {
                snd_BUG();
                return "PCM";
index 099722ebaed83901df9c23904baa13e2bd9734b3..748a3c40966e9725e3760600d8bc8126576316fc 100644 (file)
@@ -1306,6 +1306,7 @@ static const struct snd_pci_quirk ca0132_quirks[] = {
        SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI),
        SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI),
        SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI),
+       SND_PCI_QUIRK(0x3842, 0x104b, "EVGA X299 Dark", QUIRK_R3DI),
        SND_PCI_QUIRK(0x3842, 0x1055, "EVGA Z390 DARK", QUIRK_R3DI),
        SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D),
        SND_PCI_QUIRK(0x1102, 0x0018, "Recon3D", QUIRK_R3D),
index 64a944016c788d8fd2fef3382d4fe5d59cf904e7..5c0b1a09fd57c822f38fb4323876589bed891d42 100644 (file)
@@ -4589,6 +4589,11 @@ HDA_CODEC_ENTRY(0x10de009d, "GPU 9d HDMI/DP",    patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de009e, "GPU 9e HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de009f, "GPU 9f HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de00a0, "GPU a0 HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de00a3, "GPU a3 HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de00a4, "GPU a4 HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de00a5, "GPU a5 HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de00a6, "GPU a6 HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de00a7, "GPU a7 HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de8001, "MCP73 HDMI",      patch_nvhdmi_2ch),
 HDA_CODEC_ENTRY(0x10de8067, "MCP67/68 HDMI",   patch_nvhdmi_2ch),
 HDA_CODEC_ENTRY(0x67663d82, "Arise 82 HDMI/DP",        patch_gf_hdmi),
index 172ffc2c332b7acfa8bc6c099762f412b8748da0..7b5f194513c7b010c65d8e5f85598cce6f69f2ee 100644 (file)
@@ -7063,6 +7063,8 @@ enum {
        ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
        ALC295_FIXUP_DISABLE_DAC3,
        ALC285_FIXUP_SPEAKER2_TO_DAC1,
+       ALC285_FIXUP_ASUS_SPEAKER2_TO_DAC1,
+       ALC285_FIXUP_ASUS_HEADSET_MIC,
        ALC280_FIXUP_HP_HEADSET_MIC,
        ALC221_FIXUP_HP_FRONT_MIC,
        ALC292_FIXUP_TPT460,
@@ -8033,6 +8035,22 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC269_FIXUP_THINKPAD_ACPI
        },
+       [ALC285_FIXUP_ASUS_SPEAKER2_TO_DAC1] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc285_fixup_speaker2_to_dac1,
+               .chained = true,
+               .chain_id = ALC245_FIXUP_CS35L41_SPI_2
+       },
+       [ALC285_FIXUP_ASUS_HEADSET_MIC] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x03a11050 },
+                       { 0x1b, 0x03a11c30 },
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC285_FIXUP_ASUS_SPEAKER2_TO_DAC1
+       },
        [ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -9363,7 +9381,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x802f, "HP Z240", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x8077, "HP", ALC256_FIXUP_HP_HEADSET_MIC),
        SND_PCI_QUIRK(0x103c, 0x8158, "HP", ALC256_FIXUP_HP_HEADSET_MIC),
-       SND_PCI_QUIRK(0x103c, 0x820d, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+       SND_PCI_QUIRK(0x103c, 0x820d, "HP Pavilion 15", ALC295_FIXUP_HP_X360),
        SND_PCI_QUIRK(0x103c, 0x8256, "HP", ALC221_FIXUP_HP_FRONT_MIC),
        SND_PCI_QUIRK(0x103c, 0x827e, "HP x360", ALC295_FIXUP_HP_X360),
        SND_PCI_QUIRK(0x103c, 0x827f, "HP x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
@@ -9458,7 +9476,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x8aa3, "HP ProBook 450 G9 (MB 8AA1)", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8aa8, "HP EliteBook 640 G9 (MB 8AA6)", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8aab, "HP EliteBook 650 G9 (MB 8AA9)", ALC236_FIXUP_HP_GPIO_LED),
-        SND_PCI_QUIRK(0x103c, 0x8abb, "HP ZBook Firefly 14 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8abb, "HP ZBook Firefly 14 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8ad1, "HP EliteBook 840 14 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b42, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
@@ -9469,8 +9487,13 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x8b47, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
        SND_PCI_QUIRK(0x103c, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+       SND_PCI_QUIRK(0x103c, 0x8b63, "HP Elite Dragonfly 13.5 inch G4", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b65, "HP ProBook 455 15.6 inch G10 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
        SND_PCI_QUIRK(0x103c, 0x8b66, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+       SND_PCI_QUIRK(0x103c, 0x8b70, "HP EliteBook 835 G10", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x103c, 0x8b72, "HP EliteBook 845 G10", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x103c, 0x8b74, "HP EliteBook 845W G10", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x103c, 0x8b77, "HP ElieBook 865 G10", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x103c, 0x8b7a, "HP", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b7d, "HP", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b87, "HP", ALC236_FIXUP_HP_GPIO_LED),
@@ -9480,7 +9503,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x8b8f, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b92, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b96, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+       SND_PCI_QUIRK(0x103c, 0x8b97, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
        SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8c26, "HP HP EliteBook 800G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
        SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -9500,6 +9525,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1313, "Asus K42JZ", ALC269VB_FIXUP_ASUS_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
+       SND_PCI_QUIRK(0x1043, 0x1473, "ASUS GU604V", ALC285_FIXUP_ASUS_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1043, 0x1483, "ASUS GU603V", ALC285_FIXUP_ASUS_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
        SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK),
        SND_PCI_QUIRK(0x1043, 0x1683, "ASUS UM3402YAR", ALC287_FIXUP_CS35L41_I2C_2),
@@ -9522,6 +9549,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+       SND_PCI_QUIRK(0x1043, 0x1c62, "ASUS GU603", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS),
        SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401),
@@ -9618,6 +9646,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x7716, "Clevo NS50PU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x7717, "Clevo NS70PU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x7718, "Clevo L140PU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x7724, "Clevo L140AU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8228, "Clevo NR40BU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8520, "Clevo NH50D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8521, "Clevo NH77D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
@@ -11663,6 +11692,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
        SND_PCI_QUIRK(0x103c, 0x870c, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
        SND_PCI_QUIRK(0x103c, 0x8719, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
+       SND_PCI_QUIRK(0x103c, 0x872b, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
        SND_PCI_QUIRK(0x103c, 0x873e, "HP", ALC671_FIXUP_HP_HEADSET_MIC2),
        SND_PCI_QUIRK(0x103c, 0x877e, "HP 288 Pro G6", ALC671_FIXUP_HP_HEADSET_MIC2),
        SND_PCI_QUIRK(0x103c, 0x885f, "HP 288 Pro G8", ALC671_FIXUP_HP_HEADSET_MIC2),
@@ -11689,6 +11719,8 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN),
        SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN),
        SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN),
+       SND_PCI_QUIRK(0x17aa, 0x3321, "Lenovo ThinkCentre M70 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
+       SND_PCI_QUIRK(0x17aa, 0x331b, "Lenovo ThinkCentre M90 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
        SND_PCI_QUIRK(0x17aa, 0x3742, "Lenovo TianYi510Pro-14IOB", ALC897_FIXUP_HEADSET_MIC_PIN2),
        SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
index 0bc6e4066d0f5b1b015ff7b7639e1f9baa14ae98..4406a5def0768e2c7495daae8b595e3bd0bffff8 100644 (file)
@@ -311,6 +311,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "8A22"),
                }
        },
+       {
+               .driver_data = &acp6x_card,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "System76"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "pang12"),
+               }
+       },
        {}
 };
 
index 8538e2871c5fa7b672d81ca828364f47c2c38821..1e4205295a0de56c5c6c038e225e0179dcdf3bba 100644 (file)
@@ -46,7 +46,7 @@ static const struct reg_default cs35l41_reg[] = {
        { CS35L41_DSP1_RX5_SRC,                 0x00000020 },
        { CS35L41_DSP1_RX6_SRC,                 0x00000021 },
        { CS35L41_DSP1_RX7_SRC,                 0x0000003A },
-       { CS35L41_DSP1_RX8_SRC,                 0x00000001 },
+       { CS35L41_DSP1_RX8_SRC,                 0x0000003B },
        { CS35L41_NGATE1_SRC,                   0x00000008 },
        { CS35L41_NGATE2_SRC,                   0x00000009 },
        { CS35L41_AMP_DIG_VOL_CTRL,             0x00008000 },
@@ -58,8 +58,8 @@ static const struct reg_default cs35l41_reg[] = {
        { CS35L41_IRQ1_MASK2,                   0xFFFFFFFF },
        { CS35L41_IRQ1_MASK3,                   0xFFFF87FF },
        { CS35L41_IRQ1_MASK4,                   0xFEFFFFFF },
-       { CS35L41_GPIO1_CTRL1,                  0xE1000001 },
-       { CS35L41_GPIO2_CTRL1,                  0xE1000001 },
+       { CS35L41_GPIO1_CTRL1,                  0x81000001 },
+       { CS35L41_GPIO2_CTRL1,                  0x81000001 },
        { CS35L41_MIXER_NGATE_CFG,              0x00000000 },
        { CS35L41_MIXER_NGATE_CH1_CFG,          0x00000303 },
        { CS35L41_MIXER_NGATE_CH2_CFG,          0x00000303 },
index 46762f7f1449f2d452effaa8267db03b93ed1de5..d1677d76d018881ac28bf034baaac1f762557bdb 100644 (file)
@@ -852,10 +852,11 @@ static void cs35l56_dsp_work(struct work_struct *work)
         */
        if (cs35l56->sdw_peripheral) {
                cs35l56->sdw_irq_no_unmask = true;
-               cancel_work_sync(&cs35l56->sdw_irq_work);
+               flush_work(&cs35l56->sdw_irq_work);
                sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0);
                sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1);
                sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF);
+               flush_work(&cs35l56->sdw_irq_work);
        }
 
        ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_SHUTDOWN);
index da6fcf7f0991aec10e8adf10ad34f09c93b9185a..de978c3d70b7bb5940d535a6687276be968464c4 100644 (file)
@@ -746,6 +746,8 @@ static int tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol,
        struct tx_macro *tx = snd_soc_component_get_drvdata(component);
 
        val = ucontrol->value.enumerated.item[0];
+       if (val >= e->items)
+               return -EINVAL;
 
        switch (e->reg) {
        case CDC_TX_INP_MUX_ADC_MUX0_CFG0:
@@ -772,6 +774,9 @@ static int tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol,
        case CDC_TX_INP_MUX_ADC_MUX7_CFG0:
                mic_sel_reg = CDC_TX7_TX_PATH_CFG0;
                break;
+       default:
+               dev_err(component->dev, "Error in configuration!!\n");
+               return -EINVAL;
        }
 
        if (val != 0) {
index 2935c1bb81f3fbc16c3cd7e56bc7d05c04693423..5bc46b0417866292dabfc56c8df59fc037571a01 100644 (file)
@@ -267,7 +267,9 @@ static int rt5682_i2c_probe(struct i2c_client *i2c)
                ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
                        rt5682_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
                        | IRQF_ONESHOT, "rt5682", rt5682);
-               if (ret)
+               if (!ret)
+                       rt5682->irq = i2c->irq;
+               else
                        dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
        }
 
index f6c798b65c08a6b6b53c060cfe798a8e36e93aaf..5d992543b791fc317cbc51217d429fd63252005c 100644 (file)
@@ -2959,6 +2959,9 @@ static int rt5682_suspend(struct snd_soc_component *component)
        if (rt5682->is_sdw)
                return 0;
 
+       if (rt5682->irq)
+               disable_irq(rt5682->irq);
+
        cancel_delayed_work_sync(&rt5682->jack_detect_work);
        cancel_delayed_work_sync(&rt5682->jd_check_work);
        if (rt5682->hs_jack && (rt5682->jack_type & SND_JACK_HEADSET) == SND_JACK_HEADSET) {
@@ -3027,6 +3030,9 @@ static int rt5682_resume(struct snd_soc_component *component)
        mod_delayed_work(system_power_efficient_wq,
                &rt5682->jack_detect_work, msecs_to_jiffies(0));
 
+       if (rt5682->irq)
+               enable_irq(rt5682->irq);
+
        return 0;
 }
 #else
index d568c6993c337115873c7355ca54b2cbce5d6511..e8efd8a84a6ccdecb692af41462b319a3dd164f6 100644 (file)
@@ -1462,6 +1462,7 @@ struct rt5682_priv {
        int pll_out[RT5682_PLLS];
 
        int jack_type;
+       int irq;
        int irq_work_delay_time;
 };
 
index 00b60369b02988ad99d7c55d574dda385de182b1..c29324403e9d5f64cb5b8aa233477650394810d3 100644 (file)
@@ -53,6 +53,18 @@ static const struct reg_default ssm2602_reg[SSM2602_CACHEREGNUM] = {
        { .reg = 0x09, .def = 0x0000 }
 };
 
+/*
+ * ssm2602 register patch
+ * Workaround for playback distortions after power up: activates digital
+ * core, and then powers on output, DAC, and whole chip at the same time
+ */
+
+static const struct reg_sequence ssm2602_patch[] = {
+       { SSM2602_ACTIVE, 0x01 },
+       { SSM2602_PWR,    0x07 },
+       { SSM2602_RESET,  0x00 },
+};
+
 
 /*Appending several "None"s just for OSS mixer use*/
 static const char *ssm2602_input_select[] = {
@@ -598,6 +610,9 @@ static int ssm260x_component_probe(struct snd_soc_component *component)
                return ret;
        }
 
+       regmap_register_patch(ssm2602->regmap, ssm2602_patch,
+                             ARRAY_SIZE(ssm2602_patch));
+
        /* set the update bits */
        regmap_update_bits(ssm2602->regmap, SSM2602_LINVOL,
                            LINVOL_LRIN_BOTH, LINVOL_LRIN_BOTH);
index acdf98b2ee9c20a006d8c997fd9f84ecb8d59c7a..399a489f24f2dbd7a3b935064f759de15ac9ec29 100644 (file)
@@ -132,13 +132,13 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
 
                /* Error Handling: TX */
                if (isr[i] & ISR_TXFO) {
-                       dev_err(dev->dev, "TX overrun (ch_id=%d)\n", i);
+                       dev_err_ratelimited(dev->dev, "TX overrun (ch_id=%d)\n", i);
                        irq_valid = true;
                }
 
                /* Error Handling: TX */
                if (isr[i] & ISR_RXFO) {
-                       dev_err(dev->dev, "RX overrun (ch_id=%d)\n", i);
+                       dev_err_ratelimited(dev->dev, "RX overrun (ch_id=%d)\n", i);
                        irq_valid = true;
                }
        }
@@ -183,30 +183,6 @@ static void i2s_stop(struct dw_i2s_dev *dev,
        }
 }
 
-static int dw_i2s_startup(struct snd_pcm_substream *substream,
-               struct snd_soc_dai *cpu_dai)
-{
-       struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
-       union dw_i2s_snd_dma_data *dma_data = NULL;
-
-       if (!(dev->capability & DWC_I2S_RECORD) &&
-                       (substream->stream == SNDRV_PCM_STREAM_CAPTURE))
-               return -EINVAL;
-
-       if (!(dev->capability & DWC_I2S_PLAY) &&
-                       (substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
-               return -EINVAL;
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               dma_data = &dev->play_dma_data;
-       else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-               dma_data = &dev->capture_dma_data;
-
-       snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data);
-
-       return 0;
-}
-
 static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
 {
        u32 ch_reg;
@@ -305,12 +281,6 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static void dw_i2s_shutdown(struct snd_pcm_substream *substream,
-               struct snd_soc_dai *dai)
-{
-       snd_soc_dai_set_dma_data(dai, substream, NULL);
-}
-
 static int dw_i2s_prepare(struct snd_pcm_substream *substream,
                          struct snd_soc_dai *dai)
 {
@@ -382,8 +352,6 @@ static int dw_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 }
 
 static const struct snd_soc_dai_ops dw_i2s_dai_ops = {
-       .startup        = dw_i2s_startup,
-       .shutdown       = dw_i2s_shutdown,
        .hw_params      = dw_i2s_hw_params,
        .prepare        = dw_i2s_prepare,
        .trigger        = dw_i2s_trigger,
@@ -625,6 +593,14 @@ static int dw_configure_dai_by_dt(struct dw_i2s_dev *dev,
 
 }
 
+static int dw_i2s_dai_probe(struct snd_soc_dai *dai)
+{
+       struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+       snd_soc_dai_init_dma_data(dai, &dev->play_dma_data, &dev->capture_dma_data);
+       return 0;
+}
+
 static int dw_i2s_probe(struct platform_device *pdev)
 {
        const struct i2s_platform_data *pdata = pdev->dev.platform_data;
@@ -643,6 +619,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        dw_i2s_dai->ops = &dw_i2s_dai_ops;
+       dw_i2s_dai->probe = dw_i2s_dai_probe;
 
        dev->i2s_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
        if (IS_ERR(dev->i2s_base))
index 94341e4352b3cd35a4a9e2abe6bb3d994357a98b..3f08082a55bec27e498726cdcd6bcd3c2783a152 100644 (file)
@@ -1159,7 +1159,7 @@ static int fsl_micfil_probe(struct platform_device *pdev)
        ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
        if (ret) {
                dev_err(&pdev->dev, "failed to pcm register\n");
-               return ret;
+               goto err_pm_disable;
        }
 
        fsl_micfil_dai.capture.formats = micfil->soc->formats;
@@ -1169,9 +1169,20 @@ static int fsl_micfil_probe(struct platform_device *pdev)
        if (ret) {
                dev_err(&pdev->dev, "failed to register component %s\n",
                        fsl_micfil_component.name);
+               goto err_pm_disable;
        }
 
        return ret;
+
+err_pm_disable:
+       pm_runtime_disable(&pdev->dev);
+
+       return ret;
+}
+
+static void fsl_micfil_remove(struct platform_device *pdev)
+{
+       pm_runtime_disable(&pdev->dev);
 }
 
 static int __maybe_unused fsl_micfil_runtime_suspend(struct device *dev)
@@ -1232,6 +1243,7 @@ static const struct dev_pm_ops fsl_micfil_pm_ops = {
 
 static struct platform_driver fsl_micfil_driver = {
        .probe = fsl_micfil_probe,
+       .remove_new = fsl_micfil_remove,
        .driver = {
                .name = "fsl-micfil-dai",
                .pm = &fsl_micfil_pm_ops,
index 02683dce277aff11cfcb09795209beebfd6196a5..1860099c782a7249b89deb35637061de804faf05 100644 (file)
@@ -169,6 +169,7 @@ static bool apl_lp_streaming(struct avs_dev *adev)
 {
        struct avs_path *path;
 
+       spin_lock(&adev->path_list_lock);
        /* Any gateway without buffer allocated in LP area disqualifies D0IX. */
        list_for_each_entry(path, &adev->path_list, node) {
                struct avs_path_pipeline *ppl;
@@ -188,11 +189,14 @@ static bool apl_lp_streaming(struct avs_dev *adev)
                                if (cfg->copier.dma_type == INVALID_OBJECT_ID)
                                        continue;
 
-                               if (!mod->gtw_attrs.lp_buffer_alloc)
+                               if (!mod->gtw_attrs.lp_buffer_alloc) {
+                                       spin_unlock(&adev->path_list_lock);
                                        return false;
+                               }
                        }
                }
        }
+       spin_unlock(&adev->path_list_lock);
 
        return true;
 }
index d7fccdcb9c167f819bbc265cbc8fd440f907460a..0cf38c9e768e7b2952155b6bea15591fe2441cc8 100644 (file)
@@ -283,8 +283,8 @@ void avs_release_firmwares(struct avs_dev *adev);
 
 int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id,
                        u8 core_id, u8 domain, void *param, u32 param_size,
-                       u16 *instance_id);
-void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u16 instance_id,
+                       u8 *instance_id);
+void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u8 instance_id,
                           u8 ppl_instance_id, u8 core_id);
 int avs_dsp_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority,
                            bool lp, u16 attributes, u8 *instance_id);
index b2823c2107f77306b360239167dca62d7bdb05a1..60f8fb0bff95b1b3331b478a8de6f95a47076b61 100644 (file)
@@ -443,7 +443,7 @@ static int avs_register_i2s_boards(struct avs_dev *adev)
        }
 
        for (mach = boards->machs; mach->id[0]; mach++) {
-               if (!acpi_dev_present(mach->id, NULL, -1))
+               if (!acpi_dev_present(mach->id, mach->uid, -1))
                        continue;
 
                if (mach->machine_quirk)
index a8b14b784f8a519c61af84b87b54685be60d66f1..3dfa2e9816db06410aeec0ee50a6a54c5750eac3 100644 (file)
@@ -21,17 +21,25 @@ static struct avs_dev *avs_get_kcontrol_adev(struct snd_kcontrol *kcontrol)
        return to_avs_dev(w->dapm->component->dev);
 }
 
-static struct avs_path_module *avs_get_kcontrol_module(struct avs_dev *adev, u32 id)
+static struct avs_path_module *avs_get_volume_module(struct avs_dev *adev, u32 id)
 {
        struct avs_path *path;
        struct avs_path_pipeline *ppl;
        struct avs_path_module *mod;
 
-       list_for_each_entry(path, &adev->path_list, node)
-               list_for_each_entry(ppl, &path->ppl_list, node)
-                       list_for_each_entry(mod, &ppl->mod_list, node)
-                               if (mod->template->ctl_id && mod->template->ctl_id == id)
+       spin_lock(&adev->path_list_lock);
+       list_for_each_entry(path, &adev->path_list, node) {
+               list_for_each_entry(ppl, &path->ppl_list, node) {
+                       list_for_each_entry(mod, &ppl->mod_list, node) {
+                               if (guid_equal(&mod->template->cfg_ext->type, &AVS_PEAKVOL_MOD_UUID)
+                                   && mod->template->ctl_id == id) {
+                                       spin_unlock(&adev->path_list_lock);
                                        return mod;
+                               }
+                       }
+               }
+       }
+       spin_unlock(&adev->path_list_lock);
 
        return NULL;
 }
@@ -49,7 +57,7 @@ int avs_control_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va
        /* prevent access to modules while path is being constructed */
        mutex_lock(&adev->path_mutex);
 
-       active_module = avs_get_kcontrol_module(adev, ctl_data->id);
+       active_module = avs_get_volume_module(adev, ctl_data->id);
        if (active_module) {
                ret = avs_ipc_peakvol_get_volume(adev, active_module->module_id,
                                                 active_module->instance_id, &dspvols,
@@ -89,7 +97,7 @@ int avs_control_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va
                changed = 1;
        }
 
-       active_module = avs_get_kcontrol_module(adev, ctl_data->id);
+       active_module = avs_get_volume_module(adev, ctl_data->id);
        if (active_module) {
                dspvol.channel_id = AVS_ALL_CHANNELS_MASK;
                dspvol.target_volume = *volume;
index b881100d3e02ac49c01bbeb41bc5d26f45fce22d..aa03af4473e94390ed686fb73c4a1a2066125e6a 100644 (file)
@@ -225,7 +225,7 @@ err:
 
 int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id,
                        u8 core_id, u8 domain, void *param, u32 param_size,
-                       u16 *instance_id)
+                       u8 *instance_id)
 {
        struct avs_module_entry mentry;
        bool was_loaded = false;
@@ -272,7 +272,7 @@ err_mod_entry:
        return ret;
 }
 
-void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u16 instance_id,
+void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u8 instance_id,
                           u8 ppl_instance_id, u8 core_id)
 {
        struct avs_module_entry mentry;
index d3b60ae7d7432d94d00fe4fd59556d730a002f80..7f23a304b4a94ef7f5d02d7d7ef3b4c8b36ef72e 100644 (file)
@@ -619,7 +619,7 @@ enum avs_channel_config {
        AVS_CHANNEL_CONFIG_DUAL_MONO = 9,
        AVS_CHANNEL_CONFIG_I2S_DUAL_STEREO_0 = 10,
        AVS_CHANNEL_CONFIG_I2S_DUAL_STEREO_1 = 11,
-       AVS_CHANNEL_CONFIG_4_CHANNEL = 12,
+       AVS_CHANNEL_CONFIG_7_1 = 12,
        AVS_CHANNEL_CONFIG_INVALID
 };
 
index 197222c5e008edeb0cb0de37cdcbcfd5184caafd..657f7b093e805af196da4b54deb085fa5b3c2b89 100644 (file)
@@ -37,7 +37,7 @@ struct avs_path_pipeline {
 
 struct avs_path_module {
        u16 module_id;
-       u16 instance_id;
+       u8 instance_id;
        union avs_gtw_attributes gtw_attrs;
 
        struct avs_tplg_module *template;
index 31c032a0f7e4b35ee6624d2ccc5af690aa8c3275..1fbb2c2fadb55368c9c20aa5f9d039ae1054fde3 100644 (file)
@@ -468,21 +468,34 @@ static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_so
 
        host_stream = snd_hdac_ext_stream_assign(bus, substream, HDAC_EXT_STREAM_TYPE_HOST);
        if (!host_stream) {
-               kfree(data);
-               return -EBUSY;
+               ret = -EBUSY;
+               goto err;
        }
 
        data->host_stream = host_stream;
-       snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+       ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+       if (ret < 0)
+               goto err;
+
        /* avoid wrap-around with wall-clock */
-       snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 20, 178000000);
-       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates);
+       ret = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 20, 178000000);
+       if (ret < 0)
+               goto err;
+
+       ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates);
+       if (ret < 0)
+               goto err;
+
        snd_pcm_set_sync(substream);
 
        dev_dbg(dai->dev, "%s fe STARTUP tag %d str %p",
                __func__, hdac_stream(host_stream)->stream_tag, substream);
 
        return 0;
+
+err:
+       kfree(data);
+       return ret;
 }
 
 static void avs_dai_fe_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
index 70a94201d6a56a9408614959f726957d819db708..275928281c6c63809fccd7d29381a890db0b7735 100644 (file)
@@ -18,7 +18,7 @@ static int avs_dsp_init_probe(struct avs_dev *adev, union avs_connector_node_id
 {
        struct avs_probe_cfg cfg = {{0}};
        struct avs_module_entry mentry;
-       u16 dummy;
+       u8 dummy;
 
        avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry);
 
index 6d9cfe0a504110b4086e2aba7ea73e3bd98fb6b3..d0f6c945d9aeedd1309298ee69863de2403e9b63 100644 (file)
@@ -218,18 +218,48 @@ static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        return 0;
 }
 
+static int jz4740_i2s_get_i2sdiv(unsigned long mclk, unsigned long rate,
+                                unsigned long i2sdiv_max)
+{
+       unsigned long div, rate1, rate2, err1, err2;
+
+       div = mclk / (64 * rate);
+       if (div == 0)
+               div = 1;
+
+       rate1 = mclk / (64 * div);
+       rate2 = mclk / (64 * (div + 1));
+
+       err1 = abs(rate1 - rate);
+       err2 = abs(rate2 - rate);
+
+       /*
+        * Choose the divider that produces the smallest error in the
+        * output rate and reject dividers with a 5% or higher error.
+        * In the event that both dividers are outside the acceptable
+        * error margin, reject the rate to prevent distorted audio.
+        * (The number 5% is arbitrary.)
+        */
+       if (div <= i2sdiv_max && err1 <= err2 && err1 < rate/20)
+               return div;
+       if (div < i2sdiv_max && err2 < rate/20)
+               return div + 1;
+
+       return -EINVAL;
+}
+
 static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 {
        struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
        struct regmap_field *div_field;
+       unsigned long i2sdiv_max;
        unsigned int sample_size;
-       uint32_t ctrl;
-       int div;
+       uint32_t ctrl, conf;
+       int div = 1;
 
        regmap_read(i2s->regmap, JZ_REG_AIC_CTRL, &ctrl);
-
-       div = clk_get_rate(i2s->clk_i2s) / (64 * params_rate(params));
+       regmap_read(i2s->regmap, JZ_REG_AIC_CONF, &conf);
 
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S8:
@@ -258,11 +288,27 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
                        ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO;
 
                div_field = i2s->field_i2sdiv_playback;
+               i2sdiv_max = GENMASK(i2s->soc_info->field_i2sdiv_playback.msb,
+                                    i2s->soc_info->field_i2sdiv_playback.lsb);
        } else {
                ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE;
                ctrl |= FIELD_PREP(JZ_AIC_CTRL_INPUT_SAMPLE_SIZE, sample_size);
 
                div_field = i2s->field_i2sdiv_capture;
+               i2sdiv_max = GENMASK(i2s->soc_info->field_i2sdiv_capture.msb,
+                                    i2s->soc_info->field_i2sdiv_capture.lsb);
+       }
+
+       /*
+        * Only calculate I2SDIV if we're supplying the bit or frame clock.
+        * If the codec is supplying both clocks then the divider output is
+        * unused, and we don't want it to limit the allowed sample rates.
+        */
+       if (conf & (JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER)) {
+               div = jz4740_i2s_get_i2sdiv(clk_get_rate(i2s->clk_i2s),
+                                           params_rate(params), i2sdiv_max);
+               if (div < 0)
+                       return div;
        }
 
        regmap_write(i2s->regmap, JZ_REG_AIC_CTRL, ctrl);
index a6b4f29049bbc81138b7e221a0951ae352950bc0..539e3a023bc4e204bf63a284bf00f9ba22dce4bc 100644 (file)
@@ -644,9 +644,3 @@ int mt8186_init_clock(struct mtk_base_afe *afe)
 
        return 0;
 }
-
-void mt8186_deinit_clock(void *priv)
-{
-       struct mtk_base_afe *afe = priv;
-       mt8186_audsys_clk_unregister(afe);
-}
index d5988717d8f2d8d2463314a973d8cb404d9f82f1..a9d59e506d9aff0e0349ecf478ab2b886f01515a 100644 (file)
@@ -81,7 +81,6 @@ enum {
 struct mtk_base_afe;
 int mt8186_set_audio_int_bus_parent(struct mtk_base_afe *afe, int clk_id);
 int mt8186_init_clock(struct mtk_base_afe *afe);
-void mt8186_deinit_clock(void *priv);
 int mt8186_afe_enable_cgs(struct mtk_base_afe *afe);
 void mt8186_afe_disable_cgs(struct mtk_base_afe *afe);
 int mt8186_afe_enable_clock(struct mtk_base_afe *afe);
index 41172a82103eec64faf62776d52bc4bdc2971924..a868a04ed4e7af15a0f7de48ae434ad36bb3ef25 100644 (file)
@@ -2848,10 +2848,6 @@ static int mt8186_afe_pcm_dev_probe(struct platform_device *pdev)
                return ret;
        }
 
-       ret = devm_add_action_or_reset(dev, mt8186_deinit_clock, (void *)afe);
-       if (ret)
-               return ret;
-
        /* init memif */
        afe->memif_32bit_supported = 0;
        afe->memif_size = MT8186_MEMIF_NUM;
index 578969ca91c8e6ad98725ca39595feafed61e200..5666be6b1bd2e3d4cf9e0ef40ed9bfd46ce198a5 100644 (file)
@@ -84,6 +84,29 @@ static const struct afe_gate aud_clks[CLK_AUD_NR_CLK] = {
        GATE_AUD2(CLK_AUD_ETDM_OUT1_BCLK, "aud_etdm_out1_bclk", "top_audio", 24),
 };
 
+static void mt8186_audsys_clk_unregister(void *data)
+{
+       struct mtk_base_afe *afe = data;
+       struct mt8186_afe_private *afe_priv = afe->platform_priv;
+       struct clk *clk;
+       struct clk_lookup *cl;
+       int i;
+
+       if (!afe_priv)
+               return;
+
+       for (i = 0; i < CLK_AUD_NR_CLK; i++) {
+               cl = afe_priv->lookup[i];
+               if (!cl)
+                       continue;
+
+               clk = cl->clk;
+               clk_unregister_gate(clk);
+
+               clkdev_drop(cl);
+       }
+}
+
 int mt8186_audsys_clk_register(struct mtk_base_afe *afe)
 {
        struct mt8186_afe_private *afe_priv = afe->platform_priv;
@@ -124,27 +147,6 @@ int mt8186_audsys_clk_register(struct mtk_base_afe *afe)
                afe_priv->lookup[i] = cl;
        }
 
-       return 0;
+       return devm_add_action_or_reset(afe->dev, mt8186_audsys_clk_unregister, afe);
 }
 
-void mt8186_audsys_clk_unregister(struct mtk_base_afe *afe)
-{
-       struct mt8186_afe_private *afe_priv = afe->platform_priv;
-       struct clk *clk;
-       struct clk_lookup *cl;
-       int i;
-
-       if (!afe_priv)
-               return;
-
-       for (i = 0; i < CLK_AUD_NR_CLK; i++) {
-               cl = afe_priv->lookup[i];
-               if (!cl)
-                       continue;
-
-               clk = cl->clk;
-               clk_unregister_gate(clk);
-
-               clkdev_drop(cl);
-       }
-}
index b8d6a06e11e8d84c7781e3ab191ea6345a202f12..897a2914dc191372827db1366486684d88e8c734 100644 (file)
@@ -10,6 +10,5 @@
 #define _MT8186_AUDSYS_CLK_H_
 
 int mt8186_audsys_clk_register(struct mtk_base_afe *afe);
-void mt8186_audsys_clk_unregister(struct mtk_base_afe *afe);
 
 #endif
index adb69d7820a809f14a38a9bc608b1e7f609fc39b..4fb1ac8e1c4ae7d9de17c02551176291d0ea730f 100644 (file)
@@ -2405,6 +2405,9 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
                if (!snd_soc_dpcm_be_can_update(fe, be, stream))
                        continue;
 
+               if (!snd_soc_dpcm_can_be_prepared(fe, be, stream))
+                       continue;
+
                if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
                    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
                    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND) &&
@@ -3042,3 +3045,20 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
        return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
 }
 EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
+
+/*
+ * We can only prepare a BE DAI if any of it's FE are not prepared,
+ * running or paused for the specified stream direction.
+ */
+int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe,
+                                struct snd_soc_pcm_runtime *be, int stream)
+{
+       const enum snd_soc_dpcm_state state[] = {
+               SND_SOC_DPCM_STATE_START,
+               SND_SOC_DPCM_STATE_PAUSED,
+               SND_SOC_DPCM_STATE_PREPARE,
+       };
+
+       return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
+}
+EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_prepared);
index 4e0c48a361599fdf1f8e74ba06fd043da91566d2..749e856dc6011f021850c6579b6db026efdb1760 100644 (file)
@@ -209,7 +209,12 @@ int acp_sof_ipc_msg_data(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sp
                acp_mailbox_read(sdev, offset, p, sz);
        } else {
                struct snd_pcm_substream *substream = sps->substream;
-               struct acp_dsp_stream *stream = substream->runtime->private_data;
+               struct acp_dsp_stream *stream;
+
+               if (!substream || !substream->runtime)
+                       return -ESTRPIPE;
+
+               stream = substream->runtime->private_data;
 
                if (!stream)
                        return -ESTRPIPE;
index b42b5982cbbca6cabf6c27384745d131689d158a..d547318e0d32f43feb075d18bcf4d7feba452862 100644 (file)
@@ -438,8 +438,8 @@ void snd_sof_handle_fw_exception(struct snd_sof_dev *sdev, const char *msg)
                /* should we prevent DSP entering D3 ? */
                if (!sdev->ipc_dump_printed)
                        dev_info(sdev->dev,
-                                "preventing DSP entering D3 state to preserve context\n");
-               pm_runtime_get_noresume(sdev->dev);
+                                "Attempting to prevent DSP from entering D3 state to preserve context\n");
+               pm_runtime_get_if_in_use(sdev->dev);
        }
 
        /* dump vital information to the logs */
index 775582ab7494187cca6f2ce76e9dcb24f921707a..b7cbf66badf5b12e039b62f28ce34937124ef3d5 100644 (file)
@@ -19,6 +19,9 @@
 
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_MLINK)
 
+/* worst-case number of sublinks is used for sublink refcount array allocation only */
+#define HDAML_MAX_SUBLINKS (AZX_ML_LCTL_CPA_SHIFT - AZX_ML_LCTL_SPA_SHIFT)
+
 /**
  * struct hdac_ext2_link - HDAudio extended+alternate link
  *
@@ -33,6 +36,7 @@
  * @leptr:             extended link pointer
  * @eml_lock:          mutual exclusion to access shared registers e.g. CPA/SPA bits
  * in LCTL register
+ * @sublink_ref_count: array of refcounts, required to power-manage sublinks independently
  * @base_ptr:          pointer to shim/ip/shim_vs space
  * @instance_offset:   offset between each of @slcount instances managed by link
  * @shim_offset:       offset to SHIM register base
@@ -53,6 +57,7 @@ struct hdac_ext2_link {
        u32 leptr;
 
        struct mutex eml_lock; /* prevent concurrent access to e.g. CPA/SPA */
+       int sublink_ref_count[HDAML_MAX_SUBLINKS];
 
        /* internal values computed from LCAP contents */
        void __iomem *base_ptr;
@@ -68,6 +73,7 @@ struct hdac_ext2_link {
 #define AZX_REG_SDW_SHIM_OFFSET                                0x0
 #define AZX_REG_SDW_IP_OFFSET                          0x100
 #define AZX_REG_SDW_VS_SHIM_OFFSET                     0x6000
+#define AZX_REG_SDW_SHIM_PCMSyCM(y)                    (0x16 + 0x4 * (y))
 
 /* only one instance supported */
 #define AZX_REG_INTEL_DMIC_SHIM_OFFSET                 0x0
@@ -91,7 +97,7 @@ struct hdac_ext2_link {
  */
 
 static int hdaml_lnk_enum(struct device *dev, struct hdac_ext2_link *h2link,
-                         void __iomem *ml_addr, int link_idx)
+                         void __iomem *remap_addr, void __iomem *ml_addr, int link_idx)
 {
        struct hdac_ext_link *hlink = &h2link->hext_link;
        u32 base_offset;
@@ -126,15 +132,16 @@ static int hdaml_lnk_enum(struct device *dev, struct hdac_ext2_link *h2link,
                link_idx, h2link->slcount);
 
        /* find IP ID and offsets */
-       h2link->leptr = readl(hlink->ml_addr + AZX_REG_ML_LEPTR);
+       h2link->leptr = readl(ml_addr + AZX_REG_ML_LEPTR);
 
        h2link->elid = FIELD_GET(AZX_REG_ML_LEPTR_ID, h2link->leptr);
 
        base_offset = FIELD_GET(AZX_REG_ML_LEPTR_PTR, h2link->leptr);
-       h2link->base_ptr = hlink->ml_addr + base_offset;
+       h2link->base_ptr = remap_addr + base_offset;
 
        switch (h2link->elid) {
        case AZX_REG_ML_LEPTR_ID_SDW:
+               h2link->instance_offset = AZX_REG_SDW_INSTANCE_OFFSET;
                h2link->shim_offset = AZX_REG_SDW_SHIM_OFFSET;
                h2link->ip_offset = AZX_REG_SDW_IP_OFFSET;
                h2link->shim_vs_offset = AZX_REG_SDW_VS_SHIM_OFFSET;
@@ -149,6 +156,7 @@ static int hdaml_lnk_enum(struct device *dev, struct hdac_ext2_link *h2link,
                        link_idx, base_offset);
                break;
        case AZX_REG_ML_LEPTR_ID_INTEL_SSP:
+               h2link->instance_offset = AZX_REG_INTEL_SSP_INSTANCE_OFFSET;
                h2link->shim_offset = AZX_REG_INTEL_SSP_SHIM_OFFSET;
                h2link->ip_offset = AZX_REG_INTEL_SSP_IP_OFFSET;
                h2link->shim_vs_offset = AZX_REG_INTEL_SSP_VS_SHIM_OFFSET;
@@ -333,6 +341,21 @@ static void hdaml_link_set_lsdiid(u32 __iomem *lsdiid, int dev_num)
        writel(val, lsdiid);
 }
 
+static void hdaml_shim_map_stream_ch(u16 __iomem *pcmsycm, int lchan, int hchan,
+                                    int stream_id, int dir)
+{
+       u16 val;
+
+       val = readw(pcmsycm);
+
+       u16p_replace_bits(&val, lchan, GENMASK(3, 0));
+       u16p_replace_bits(&val, hchan, GENMASK(7, 4));
+       u16p_replace_bits(&val, stream_id, GENMASK(13, 8));
+       u16p_replace_bits(&val, dir, BIT(15));
+
+       writew(val, pcmsycm);
+}
+
 static void hdaml_lctl_offload_enable(u32 __iomem *lctl, bool enable)
 {
        u32 val = readl(lctl);
@@ -364,7 +387,7 @@ static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index)
        hlink->bus = bus;
        hlink->ml_addr = bus->mlcap + AZX_ML_BASE + (AZX_ML_INTERVAL * index);
 
-       ret = hdaml_lnk_enum(bus->dev, h2link, hlink->ml_addr, index);
+       ret = hdaml_lnk_enum(bus->dev, h2link, bus->remap_addr, hlink->ml_addr, index);
        if (ret < 0) {
                kfree(h2link);
                return ret;
@@ -641,8 +664,13 @@ static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid,
        if (eml_lock)
                mutex_lock(&h2link->eml_lock);
 
-       if (++hlink->ref_count > 1)
-               goto skip_init;
+       if (!alt) {
+               if (++hlink->ref_count > 1)
+                       goto skip_init;
+       } else {
+               if (++h2link->sublink_ref_count[sublink] > 1)
+                       goto skip_init;
+       }
 
        ret = hdaml_link_init(hlink->ml_addr + AZX_REG_ML_LCTL, sublink);
 
@@ -684,9 +712,13 @@ static int hdac_bus_eml_power_down_base(struct hdac_bus *bus, bool alt, int elid
        if (eml_lock)
                mutex_lock(&h2link->eml_lock);
 
-       if (--hlink->ref_count > 0)
-               goto skip_shutdown;
-
+       if (!alt) {
+               if (--hlink->ref_count > 0)
+                       goto skip_shutdown;
+       } else {
+               if (--h2link->sublink_ref_count[sublink] > 0)
+                       goto skip_shutdown;
+       }
        ret = hdaml_link_shutdown(hlink->ml_addr + AZX_REG_ML_LCTL, sublink);
 
 skip_shutdown:
@@ -740,6 +772,40 @@ int hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num)
        return 0;
 } EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_set_lsdiid, SND_SOC_SOF_HDA_MLINK);
 
+/*
+ * the 'y' parameter comes from the PCMSyCM hardware register naming. 'y' refers to the
+ * PDI index, i.e. the FIFO used for RX or TX
+ */
+int hdac_bus_eml_sdw_map_stream_ch(struct hdac_bus *bus, int sublink, int y,
+                                  int channel_mask, int stream_id, int dir)
+{
+       struct hdac_ext2_link *h2link;
+       u16 __iomem *pcmsycm;
+       u16 val;
+
+       h2link = find_ext2_link(bus, true, AZX_REG_ML_LEPTR_ID_SDW);
+       if (!h2link)
+               return -ENODEV;
+
+       pcmsycm = h2link->base_ptr + h2link->shim_offset +
+               h2link->instance_offset * sublink +
+               AZX_REG_SDW_SHIM_PCMSyCM(y);
+
+       mutex_lock(&h2link->eml_lock);
+
+       hdaml_shim_map_stream_ch(pcmsycm, 0, hweight32(channel_mask),
+                                stream_id, dir);
+
+       mutex_unlock(&h2link->eml_lock);
+
+       val = readw(pcmsycm);
+
+       dev_dbg(bus->dev, "channel_mask %#x stream_id %d dir %d pcmscm %#x\n",
+               channel_mask, stream_id, dir, val);
+
+       return 0;
+} EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_map_stream_ch, SND_SOC_SOF_HDA_MLINK);
+
 void hda_bus_ml_put_all(struct hdac_bus *bus)
 {
        struct hdac_ext_link *hlink;
@@ -836,6 +902,18 @@ struct hdac_ext_link *hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus)
 }
 EXPORT_SYMBOL_NS(hdac_bus_eml_dmic_get_hlink, SND_SOC_SOF_HDA_MLINK);
 
+struct hdac_ext_link *hdac_bus_eml_sdw_get_hlink(struct hdac_bus *bus)
+{
+       struct hdac_ext2_link *h2link;
+
+       h2link = find_ext2_link(bus, true, AZX_REG_ML_LEPTR_ID_SDW);
+       if (!h2link)
+               return NULL;
+
+       return &h2link->hext_link;
+}
+EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_get_hlink, SND_SOC_SOF_HDA_MLINK);
+
 int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable)
 {
        struct hdac_ext2_link *h2link;
index fc1eb8e2de2c1d9e19f3a86522e2af3f3c162a8d..ba4ef290b6343fee3b8267180ffdb352fef6b77a 100644 (file)
@@ -2103,10 +2103,13 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
         * For the case of PAUSE/HW_FREE, since there are no quirks, flags can be used as is.
         */
 
-       if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS)
+       if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) {
+               /* Clear stale command */
+               config->flags &= ~SOF_DAI_CONFIG_FLAGS_CMD_MASK;
                config->flags |= flags;
-       else
+       } else {
                config->flags = flags;
+       }
 
        /* only send the IPC if the widget is set up in the DSP */
        if (swidget->use_count > 0) {
index 059eebf0a68756dc6c99882e7dcd6f0a118daa69..5abe616a2054a0b969663c15d1b4c66faff4fa97 100644 (file)
@@ -59,7 +59,7 @@ static const struct sof_topology_token ipc4_in_audio_format_tokens[] = {
                audio_fmt.interleaving_style)},
        {SOF_TKN_CAVS_AUDIO_FORMAT_IN_FMT_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
                offsetof(struct sof_ipc4_pin_format, audio_fmt.fmt_cfg)},
-       {SOF_TKN_CAVS_AUDIO_FORMAT_PIN_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
+       {SOF_TKN_CAVS_AUDIO_FORMAT_INPUT_PIN_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
                offsetof(struct sof_ipc4_pin_format, pin_index)},
        {SOF_TKN_CAVS_AUDIO_FORMAT_IBS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
                offsetof(struct sof_ipc4_pin_format, buffer_size)},
@@ -79,7 +79,7 @@ static const struct sof_topology_token ipc4_out_audio_format_tokens[] = {
                audio_fmt.interleaving_style)},
        {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_FMT_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
                offsetof(struct sof_ipc4_pin_format, audio_fmt.fmt_cfg)},
-       {SOF_TKN_CAVS_AUDIO_FORMAT_PIN_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
+       {SOF_TKN_CAVS_AUDIO_FORMAT_OUTPUT_PIN_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
                offsetof(struct sof_ipc4_pin_format, pin_index)},
        {SOF_TKN_CAVS_AUDIO_FORMAT_OBS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
                offsetof(struct sof_ipc4_pin_format, buffer_size)},
index 567db32173a88fc922cfc87b8f5640efa3219e89..d0ab6f390734e576677eea411971b97da57724ff 100644 (file)
@@ -643,16 +643,17 @@ static int sof_pcm_probe(struct snd_soc_component *component)
                                       "%s/%s",
                                       plat_data->tplg_filename_prefix,
                                       plat_data->tplg_filename);
-       if (!tplg_filename)
-               return -ENOMEM;
+       if (!tplg_filename) {
+               ret = -ENOMEM;
+               goto pm_error;
+       }
 
        ret = snd_sof_load_topology(component, tplg_filename);
-       if (ret < 0) {
+       if (ret < 0)
                dev_err(component->dev, "error: failed to load DSP topology %d\n",
                        ret);
-               return ret;
-       }
 
+pm_error:
        pm_runtime_mark_last_busy(component->dev);
        pm_runtime_put_autosuspend(component->dev);
 
index 2fdbc53ca7150b3ad5f597d22705d83fc87ce7c3..2b232442e84bcd44a79ec60ed9507bc26391c771 100644 (file)
@@ -164,7 +164,7 @@ static int sof_resume(struct device *dev, bool runtime_resume)
                ret = tplg_ops->set_up_all_pipelines(sdev, false);
                if (ret < 0) {
                        dev_err(sdev->dev, "Failed to restore pipeline after resume %d\n", ret);
-                       return ret;
+                       goto setup_fail;
                }
        }
 
@@ -178,6 +178,18 @@ static int sof_resume(struct device *dev, bool runtime_resume)
                        dev_err(sdev->dev, "ctx_restore IPC error during resume: %d\n", ret);
        }
 
+setup_fail:
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
+       if (ret < 0) {
+               /*
+                * Debugfs cannot be read in runtime suspend, so cache
+                * the contents upon failure. This allows to capture
+                * possible DSP coredump information.
+                */
+               sof_cache_debugfs(sdev);
+       }
+#endif
+
        return ret;
 }
 
index fff126808bc04c07e1b9a9755b429ee547f2ae81..8d9e9d5f40e45b9626bf4797a4316c39e975042f 100644 (file)
@@ -218,12 +218,7 @@ static ssize_t sof_probes_dfs_points_read(struct file *file, char __user *to,
 
        ret = ipc->points_info(cdev, &desc, &num_desc);
        if (ret < 0)
-               goto exit;
-
-       pm_runtime_mark_last_busy(dev);
-       err = pm_runtime_put_autosuspend(dev);
-       if (err < 0)
-               dev_err_ratelimited(dev, "debugfs read failed to idle %d\n", err);
+               goto pm_error;
 
        for (i = 0; i < num_desc; i++) {
                offset = strlen(buf);
@@ -241,6 +236,13 @@ static ssize_t sof_probes_dfs_points_read(struct file *file, char __user *to,
        ret = simple_read_from_buffer(to, count, ppos, buf, strlen(buf));
 
        kfree(desc);
+
+pm_error:
+       pm_runtime_mark_last_busy(dev);
+       err = pm_runtime_put_autosuspend(dev);
+       if (err < 0)
+               dev_err_ratelimited(dev, "debugfs read failed to idle %d\n", err);
+
 exit:
        kfree(buf);
        return ret;
index d3d536b0a8f54d8516d360e0c0b80f7cc8fcc022..f160dc454b44882d177e61537b6515d962c61f96 100644 (file)
@@ -586,6 +586,10 @@ static int sof_copy_tuples(struct snd_sof_dev *sdev, struct snd_soc_tplg_vendor_
                                if (*num_copied_tuples == tuples_size)
                                        return 0;
                        }
+
+                       /* stop when we've found the required token instances */
+                       if (found == num_tokens * token_instance_num)
+                               return 0;
                }
 
                /* next array */
@@ -1261,7 +1265,7 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s
                if (num_sets > 1) {
                        struct snd_sof_tuple *new_tuples;
 
-                       num_tuples += token_list[object_token_list[i]].count * num_sets;
+                       num_tuples += token_list[object_token_list[i]].count * (num_sets - 1);
                        new_tuples = krealloc(swidget->tuples,
                                              sizeof(*new_tuples) * num_tuples, GFP_KERNEL);
                        if (!new_tuples) {
index 4b1c5ba121f391db21a542a453147256d4055430..ab5fed9f55b60ec8b255448a9cbb435f9e04d96b 100644 (file)
@@ -423,6 +423,7 @@ static int line6_parse_audio_format_rates_quirk(struct snd_usb_audio *chip,
        case USB_ID(0x0e41, 0x4248): /* Line6 Helix >= fw 2.82 */
        case USB_ID(0x0e41, 0x4249): /* Line6 Helix Rack >= fw 2.82 */
        case USB_ID(0x0e41, 0x424a): /* Line6 Helix LT >= fw 2.82 */
+       case USB_ID(0x0e41, 0x424b): /* Line6 Pod Go */
        case USB_ID(0x19f7, 0x0011): /* Rode Rodecaster Pro */
                return set_fixed_rate(fp, 48000, SNDRV_PCM_RATE_48000);
        }
index f8129c624b0709815cbd266d569bb12fb70e6047..f7ddd73a8c0fa2dabffd2782f674f3b484079875 100644 (file)
@@ -198,6 +198,15 @@ struct kvm_arm_copy_mte_tags {
        __u64 reserved[2];
 };
 
+/*
+ * Counter/Timer offset structure. Describe the virtual/physical offset.
+ * To be used with KVM_ARM_SET_COUNTER_OFFSET.
+ */
+struct kvm_arm_counter_offset {
+       __u64 counter_offset;
+       __u64 reserved;
+};
+
 #define KVM_ARM_TAGS_TO_GUEST          0
 #define KVM_ARM_TAGS_FROM_GUEST                1
 
@@ -372,6 +381,10 @@ enum {
 #endif
 };
 
+/* Device Control API on vm fd */
+#define KVM_ARM_VM_SMCCC_CTRL          0
+#define   KVM_ARM_VM_SMCCC_FILTER      0
+
 /* Device Control API: ARM VGIC */
 #define KVM_DEV_ARM_VGIC_GRP_ADDR      0
 #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
@@ -411,6 +424,8 @@ enum {
 #define KVM_ARM_VCPU_TIMER_CTRL                1
 #define   KVM_ARM_VCPU_TIMER_IRQ_VTIMER                0
 #define   KVM_ARM_VCPU_TIMER_IRQ_PTIMER                1
+#define   KVM_ARM_VCPU_TIMER_IRQ_HVTIMER       2
+#define   KVM_ARM_VCPU_TIMER_IRQ_HPTIMER       3
 #define KVM_ARM_VCPU_PVTIME_CTRL       2
 #define   KVM_ARM_VCPU_PVTIME_IPA      0
 
@@ -469,6 +484,27 @@ enum {
 /* run->fail_entry.hardware_entry_failure_reason codes. */
 #define KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED    (1ULL << 0)
 
+enum kvm_smccc_filter_action {
+       KVM_SMCCC_FILTER_HANDLE = 0,
+       KVM_SMCCC_FILTER_DENY,
+       KVM_SMCCC_FILTER_FWD_TO_USER,
+
+#ifdef __KERNEL__
+       NR_SMCCC_FILTER_ACTIONS
+#endif
+};
+
+struct kvm_smccc_filter {
+       __u32 base;
+       __u32 nr_functions;
+       __u8 action;
+       __u8 pad[15];
+};
+
+/* arm64-specific KVM_EXIT_HYPERCALL flags */
+#define KVM_HYPERCALL_EXIT_SMC         (1U << 0)
+#define KVM_HYPERCALL_EXIT_16BIT       (1U << 1)
+
 #endif
 
 #endif /* __ARM_KVM_H__ */
index b89005819cd551a9cc983fde516a9a060137ad84..cb8ca46213bed0a837d9e134877f623c4e0e0525 100644 (file)
@@ -97,7 +97,7 @@
 #define X86_FEATURE_SYSENTER32         ( 3*32+15) /* "" sysenter in IA32 userspace */
 #define X86_FEATURE_REP_GOOD           ( 3*32+16) /* REP microcode works well */
 #define X86_FEATURE_AMD_LBR_V2         ( 3*32+17) /* AMD Last Branch Record Extension Version 2 */
-#define X86_FEATURE_LFENCE_RDTSC       ( 3*32+18) /* "" LFENCE synchronizes RDTSC */
+/* FREE, was #define X86_FEATURE_LFENCE_RDTSC          ( 3*32+18) "" LFENCE synchronizes RDTSC */
 #define X86_FEATURE_ACC_POWER          ( 3*32+19) /* AMD Accumulated Power Mechanism */
 #define X86_FEATURE_NOPL               ( 3*32+20) /* The NOPL (0F 1F) instructions */
 #define X86_FEATURE_ALWAYS             ( 3*32+21) /* "" Always-present feature */
 
 /* Virtualization flags: Linux defined, word 8 */
 #define X86_FEATURE_TPR_SHADOW         ( 8*32+ 0) /* Intel TPR Shadow */
-#define X86_FEATURE_VNMI               ( 8*32+ 1) /* Intel Virtual NMI */
-#define X86_FEATURE_FLEXPRIORITY       ( 8*32+ 2) /* Intel FlexPriority */
-#define X86_FEATURE_EPT                        ( 8*32+ 3) /* Intel Extended Page Table */
-#define X86_FEATURE_VPID               ( 8*32+ 4) /* Intel Virtual Processor ID */
+#define X86_FEATURE_FLEXPRIORITY       ( 8*32+ 1) /* Intel FlexPriority */
+#define X86_FEATURE_EPT                        ( 8*32+ 2) /* Intel Extended Page Table */
+#define X86_FEATURE_VPID               ( 8*32+ 3) /* Intel Virtual Processor ID */
 
 #define X86_FEATURE_VMMCALL            ( 8*32+15) /* Prefer VMMCALL to VMCALL */
 #define X86_FEATURE_XENPV              ( 8*32+16) /* "" Xen paravirtual guest */
 #define X86_FEATURE_SGX_EDECCSSA       (11*32+18) /* "" SGX EDECCSSA user leaf function */
 #define X86_FEATURE_CALL_DEPTH         (11*32+19) /* "" Call depth tracking for RSB stuffing */
 #define X86_FEATURE_MSR_TSX_CTRL       (11*32+20) /* "" MSR IA32_TSX_CTRL (Intel) implemented */
+#define X86_FEATURE_SMBA               (11*32+21) /* "" Slow Memory Bandwidth Allocation */
+#define X86_FEATURE_BMEC               (11*32+22) /* "" Bandwidth Monitoring Event Configuration */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
 #define X86_FEATURE_AVX_VNNI           (12*32+ 4) /* AVX VNNI instructions */
 #define X86_FEATURE_AVX512_BF16                (12*32+ 5) /* AVX512 BFLOAT16 instructions */
 #define X86_FEATURE_CMPCCXADD           (12*32+ 7) /* "" CMPccXADD instructions */
+#define X86_FEATURE_ARCH_PERFMON_EXT   (12*32+ 8) /* "" Intel Architectural PerfMon Extension */
+#define X86_FEATURE_FZRM               (12*32+10) /* "" Fast zero-length REP MOVSB */
+#define X86_FEATURE_FSRS               (12*32+11) /* "" Fast short REP STOSB */
+#define X86_FEATURE_FSRC               (12*32+12) /* "" Fast short REP {CMPSB,SCASB} */
 #define X86_FEATURE_LKGS               (12*32+18) /* "" Load "kernel" (userspace) GS */
 #define X86_FEATURE_AMX_FP16           (12*32+21) /* "" AMX fp16 Support */
 #define X86_FEATURE_AVX_IFMA            (12*32+23) /* "" Support for VPMADD52[H,L]UQ */
+#define X86_FEATURE_LAM                        (12*32+26) /* Linear Address Masking */
 
 /* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */
 #define X86_FEATURE_CLZERO             (13*32+ 0) /* CLZERO instruction */
 #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_CPPC               (13*32+27) /* Collaborative Processor Performance Control */
+#define X86_FEATURE_AMD_PSFD            (13*32+28) /* "" Predictive Store Forwarding Disable */
 #define X86_FEATURE_BTC_NO             (13*32+29) /* "" Not vulnerable to Branch Type Confusion */
 #define X86_FEATURE_BRS                        (13*32+31) /* Branch Sampling available */
 
 #define X86_FEATURE_VGIF               (15*32+16) /* Virtual GIF */
 #define X86_FEATURE_X2AVIC             (15*32+18) /* Virtual x2apic */
 #define X86_FEATURE_V_SPEC_CTRL                (15*32+20) /* Virtual SPEC_CTRL */
+#define X86_FEATURE_VNMI               (15*32+25) /* Virtual NMI */
 #define X86_FEATURE_SVME_ADDR_CHK      (15*32+28) /* "" SVME addr check */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (ECX), word 16 */
 #define X86_FEATURE_V_TSC_AUX          (19*32+ 9) /* "" Virtual TSC_AUX */
 #define X86_FEATURE_SME_COHERENT       (19*32+10) /* "" AMD hardware-enforced cache coherency */
 
+/* AMD-defined Extended Feature 2 EAX, CPUID level 0x80000021 (EAX), word 20 */
+#define X86_FEATURE_NO_NESTED_DATA_BP  (20*32+ 0) /* "" No Nested Data Breakpoints */
+#define X86_FEATURE_LFENCE_RDTSC       (20*32+ 2) /* "" LFENCE always serializing / synchronizes RDTSC */
+#define X86_FEATURE_NULL_SEL_CLR_BASE  (20*32+ 6) /* "" Null Selector Clears Base */
+#define X86_FEATURE_AUTOIBRS           (20*32+ 8) /* "" Automatic IBRS */
+#define X86_FEATURE_NO_SMM_CTL_MSR     (20*32+ 9) /* "" SMM_CTL MSR is not present */
+
 /*
  * BUG word(s)
  */
 #define X86_BUG_MMIO_UNKNOWN           X86_BUG(26) /* CPU is too old and its MMIO Stale Data status is unknown */
 #define X86_BUG_RETBLEED               X86_BUG(27) /* CPU is affected by RETBleed */
 #define X86_BUG_EIBRS_PBRSB            X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
+#define X86_BUG_SMT_RSB                        X86_BUG(29) /* CPU is vulnerable to Cross-Thread Return Address Predictions */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
index 5dfa4fb76f4b2ba025b4c4e45b9e4846b75128c6..fafe9be7a6f4ff6b7adc0ae3ea34d30b3d9ba79d 100644 (file)
 # define DISABLE_CALL_DEPTH_TRACKING   (1 << (X86_FEATURE_CALL_DEPTH & 31))
 #endif
 
+#ifdef CONFIG_ADDRESS_MASKING
+# define DISABLE_LAM           0
+#else
+# define DISABLE_LAM           (1 << (X86_FEATURE_LAM & 31))
+#endif
+
 #ifdef CONFIG_INTEL_IOMMU_SVM
 # define DISABLE_ENQCMD                0
 #else
 #define DISABLED_MASK10        0
 #define DISABLED_MASK11        (DISABLE_RETPOLINE|DISABLE_RETHUNK|DISABLE_UNRET| \
                         DISABLE_CALL_DEPTH_TRACKING)
-#define DISABLED_MASK12        0
+#define DISABLED_MASK12        (DISABLE_LAM)
 #define DISABLED_MASK13        0
 #define DISABLED_MASK14        0
 #define DISABLED_MASK15        0
index ad35355ee43ead14e638ac5c853fd5a82b8ee774..3aedae61af4fcb945383ea486066d43982f28462 100644 (file)
 
 /* Abbreviated from Intel SDM name IA32_INTEGRITY_CAPABILITIES */
 #define MSR_INTEGRITY_CAPS                     0x000002d9
+#define MSR_INTEGRITY_CAPS_ARRAY_BIST_BIT      2
+#define MSR_INTEGRITY_CAPS_ARRAY_BIST          BIT(MSR_INTEGRITY_CAPS_ARRAY_BIST_BIT)
 #define MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT   4
 #define MSR_INTEGRITY_CAPS_PERIODIC_BIST       BIT(MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT)
 
index 7f467fe05d42ea702d45679bc8ce27d18656b124..1a6a1f98794967d260e2898b0dbb62f830d45664 100644 (file)
@@ -559,4 +559,7 @@ struct kvm_pmu_event_filter {
 #define KVM_VCPU_TSC_CTRL 0 /* control group for the timestamp counter (TSC) */
 #define   KVM_VCPU_TSC_OFFSET 0 /* attribute for the TSC offset */
 
+/* x86-specific KVM_EXIT_HYPERCALL flags. */
+#define KVM_EXIT_HYPERCALL_LONG_MODE   BIT(0)
+
 #endif /* _ASM_X86_KVM_H */
index 500b96e71f1868dd097a2a796c8da89b5f85bed3..e8d7ebbca1a4dc4120f5ae8c924a9d1c1f35db22 100644 (file)
 #define ARCH_GET_XCOMP_GUEST_PERM      0x1024
 #define ARCH_REQ_XCOMP_GUEST_PERM      0x1025
 
+#define ARCH_XCOMP_TILECFG             17
+#define ARCH_XCOMP_TILEDATA            18
+
 #define ARCH_MAP_VDSO_X32              0x2001
 #define ARCH_MAP_VDSO_32               0x2002
 #define ARCH_MAP_VDSO_64               0x2003
 
+#define ARCH_GET_UNTAG_MASK            0x4001
+#define ARCH_ENABLE_TAGGED_ADDR                0x4002
+#define ARCH_GET_MAX_TAG_BITS          0x4003
+#define ARCH_FORCE_TAGGED_SVA          0x4004
+
 #endif /* _ASM_X86_PRCTL_H */
index b8ddfc4c4ab047cc43a48acf2385fcb58134036e..bc48a4dabe5dbd96dff834bc7a65dc14997d020e 100644 (file)
@@ -2,6 +2,9 @@
 #ifndef __NR_fork
 #define __NR_fork 2
 #endif
+#ifndef __NR_execve
+#define __NR_execve 11
+#endif
 #ifndef __NR_getppid
 #define __NR_getppid 64
 #endif
index a91ac666f758274c3f1ebf411cdf3469d69b93d2..d055b82d22ccd083975a874e5a96abbeff8f496b 100644 (file)
@@ -9,13 +9,6 @@
 
 .section .noinstr.text, "ax"
 
-/*
- * We build a jump to memcpy_orig by default which gets NOPped out on
- * the majority of x86 CPUs which set REP_GOOD. In addition, CPUs which
- * have the enhanced REP MOVSB/STOSB feature (ERMS), change those NOPs
- * to a jmp to memcpy_erms which does the REP; MOVSB mem copy.
- */
-
 /*
  * memcpy - Copy a memory block.
  *
  *
  * Output:
  * rax original destination
+ *
+ * The FSRM alternative should be done inline (avoiding the call and
+ * the disgusting return handling), but that would require some help
+ * from the compiler for better calling conventions.
+ *
+ * The 'rep movsb' itself is small enough to replace the call, but the
+ * two register moves blow up the code. And one of them is "needed"
+ * only for the return value that is the same as the source input,
+ * which the compiler could/should do much better anyway.
  */
 SYM_TYPED_FUNC_START(__memcpy)
-       ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \
-                     "jmp memcpy_erms", X86_FEATURE_ERMS
+       ALTERNATIVE "jmp memcpy_orig", "", X86_FEATURE_FSRM
 
        movq %rdi, %rax
        movq %rdx, %rcx
-       shrq $3, %rcx
-       andl $7, %edx
-       rep movsq
-       movl %edx, %ecx
        rep movsb
        RET
 SYM_FUNC_END(__memcpy)
@@ -45,17 +42,6 @@ EXPORT_SYMBOL(__memcpy)
 SYM_FUNC_ALIAS(memcpy, __memcpy)
 EXPORT_SYMBOL(memcpy)
 
-/*
- * memcpy_erms() - enhanced fast string memcpy. This is faster and
- * simpler than memcpy. Use memcpy_erms when possible.
- */
-SYM_FUNC_START_LOCAL(memcpy_erms)
-       movq %rdi, %rax
-       movq %rdx, %rcx
-       rep movsb
-       RET
-SYM_FUNC_END(memcpy_erms)
-
 SYM_FUNC_START_LOCAL(memcpy_orig)
        movq %rdi, %rax
 
index 6143b1a6fa2caa0d5977d22c3f1c23456ff6d3bf..7c59a704c4584bf7ef3e6a50f2021c31e6f15029 100644 (file)
  * rdx   count (bytes)
  *
  * rax   original destination
+ *
+ * The FSRS alternative should be done inline (avoiding the call and
+ * the disgusting return handling), but that would require some help
+ * from the compiler for better calling conventions.
+ *
+ * The 'rep stosb' itself is small enough to replace the call, but all
+ * the register moves blow up the code. And two of them are "needed"
+ * only for the return value that is the same as the source input,
+ * which the compiler could/should do much better anyway.
  */
 SYM_FUNC_START(__memset)
-       /*
-        * Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended
-        * to use it when possible. If not available, use fast string instructions.
-        *
-        * Otherwise, use original memset function.
-        */
-       ALTERNATIVE_2 "jmp memset_orig", "", X86_FEATURE_REP_GOOD, \
-                     "jmp memset_erms", X86_FEATURE_ERMS
+       ALTERNATIVE "jmp memset_orig", "", X86_FEATURE_FSRS
 
        movq %rdi,%r9
+       movb %sil,%al
        movq %rdx,%rcx
-       andl $7,%edx
-       shrq $3,%rcx
-       /* expand byte value  */
-       movzbl %sil,%esi
-       movabs $0x0101010101010101,%rax
-       imulq %rsi,%rax
-       rep stosq
-       movl %edx,%ecx
        rep stosb
        movq %r9,%rax
        RET
@@ -48,26 +43,6 @@ EXPORT_SYMBOL(__memset)
 SYM_FUNC_ALIAS(memset, __memset)
 EXPORT_SYMBOL(memset)
 
-/*
- * ISO C memset - set a memory block to a byte value. This function uses
- * enhanced rep stosb to override the fast string function.
- * The code is simpler and shorter than the fast string function as well.
- *
- * rdi   destination
- * rsi   value (char)
- * rdx   count (bytes)
- *
- * rax   original destination
- */
-SYM_FUNC_START_LOCAL(memset_erms)
-       movq %rdi,%r9
-       movb %sil,%al
-       movq %rdx,%rcx
-       rep stosb
-       movq %r9,%rax
-       RET
-SYM_FUNC_END(memset_erms)
-
 SYM_FUNC_START_LOCAL(memset_orig)
        movq %rdi,%r10
 
diff --git a/tools/counter/.gitignore b/tools/counter/.gitignore
new file mode 100644 (file)
index 0000000..9fd290d
--- /dev/null
@@ -0,0 +1,2 @@
+/counter_example
+/include/linux/counter.h
index 8843f0fa61199e94e65fa034627426db9d5ed139..a0f4cab71fe5ff2341e581d6d942225ce2d240f2 100644 (file)
@@ -40,6 +40,7 @@ $(OUTPUT)counter_example: $(COUNTER_EXAMPLE)
 clean:
        rm -f $(ALL_PROGRAMS)
        rm -rf $(OUTPUT)include/linux/counter.h
+       rmdir -p $(OUTPUT)include/linux
        find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete
 
 install: $(ALL_PROGRAMS)
index c61d061247e1773ae2b81eaae21a899976184607..52a0be45410c97e8f02c0ccc301855fbc57864b2 100644 (file)
@@ -94,7 +94,7 @@ static void print_attributes(struct gpio_v2_line_info *info)
        for (i = 0; i < info->num_attrs; i++) {
                if (info->attrs[i].id == GPIO_V2_LINE_ATTR_ID_DEBOUNCE)
                        fprintf(stdout, ", debounce_period=%dusec",
-                               info->attrs[0].debounce_period_us);
+                               info->attrs[i].debounce_period_us);
        }
 }
 
index b54bd860dff6ffcd763c8f9466a06375e2bb3a70..7ce02a22373254a72ec8d185a9bf81859d6acbb4 100644 (file)
@@ -4,7 +4,6 @@
 
 /* Just disable it so we can build arch/x86/lib/memcpy_64.S for perf bench: */
 
-#define altinstruction_entry #
-#define ALTERNATIVE_2 #
+#define ALTERNATIVE #
 
 #endif
index cef3b1c25335a73696cf5643c2ffcba2d5414f26..51ac441a37c3e38ff325896199bd3af3ff79438a 100644 (file)
  */
 #define CORESIGHT_LEGACY_CPU_TRACE_ID(cpu)  (0x10 + (cpu * 2))
 
-/* CoreSight trace ID is currently the bottom 7 bits of the value */
-#define CORESIGHT_TRACE_ID_VAL_MASK    GENMASK(6, 0)
-
-/*
- * perf record will set the legacy meta data values as unused initially.
- * This allows perf report to manage the decoders created when dynamic
- * allocation in operation.
- */
-#define CORESIGHT_TRACE_ID_UNUSED_FLAG BIT(31)
-
-/* Value to set for unused trace ID values */
-#define CORESIGHT_TRACE_ID_UNUSED_VAL  0x7F
-
 /*
  * Below are the definition of bit offsets for perf option, and works as
  * arbitrary values for all ETM versions.
index 642808520d9228f1b7a26b712a3f828164e6337b..a87bbbbca2d48ada91efcc8aaab469ba51f0224a 100644 (file)
@@ -972,6 +972,19 @@ extern "C" {
 #define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
 #define DRM_IOCTL_SET_VERSION          DRM_IOWR(0x07, struct drm_set_version)
 #define DRM_IOCTL_MODESET_CTL           DRM_IOW(0x08, struct drm_modeset_ctl)
+/**
+ * DRM_IOCTL_GEM_CLOSE - Close a GEM handle.
+ *
+ * GEM handles are not reference-counted by the kernel. User-space is
+ * responsible for managing their lifetime. For example, if user-space imports
+ * the same memory object twice on the same DRM file description, the same GEM
+ * handle is returned by both imports, and user-space needs to ensure
+ * &DRM_IOCTL_GEM_CLOSE is performed once only. The same situation can happen
+ * when a memory object is allocated, then exported and imported again on the
+ * same DRM file description. The &DRM_IOCTL_MODE_GETFB2 IOCTL is an exception
+ * and always returns fresh new GEM handles even if an existing GEM handle
+ * already refers to the same memory object before the IOCTL is performed.
+ */
 #define DRM_IOCTL_GEM_CLOSE            DRM_IOW (0x09, struct drm_gem_close)
 #define DRM_IOCTL_GEM_FLINK            DRM_IOWR(0x0a, struct drm_gem_flink)
 #define DRM_IOCTL_GEM_OPEN             DRM_IOWR(0x0b, struct drm_gem_open)
@@ -1012,7 +1025,37 @@ extern "C" {
 #define DRM_IOCTL_UNLOCK               DRM_IOW( 0x2b, struct drm_lock)
 #define DRM_IOCTL_FINISH               DRM_IOW( 0x2c, struct drm_lock)
 
+/**
+ * DRM_IOCTL_PRIME_HANDLE_TO_FD - Convert a GEM handle to a DMA-BUF FD.
+ *
+ * User-space sets &drm_prime_handle.handle with the GEM handle to export and
+ * &drm_prime_handle.flags, and gets back a DMA-BUF file descriptor in
+ * &drm_prime_handle.fd.
+ *
+ * The export can fail for any driver-specific reason, e.g. because export is
+ * not supported for this specific GEM handle (but might be for others).
+ *
+ * Support for exporting DMA-BUFs is advertised via &DRM_PRIME_CAP_EXPORT.
+ */
 #define DRM_IOCTL_PRIME_HANDLE_TO_FD    DRM_IOWR(0x2d, struct drm_prime_handle)
+/**
+ * DRM_IOCTL_PRIME_FD_TO_HANDLE - Convert a DMA-BUF FD to a GEM handle.
+ *
+ * User-space sets &drm_prime_handle.fd with a DMA-BUF file descriptor to
+ * import, and gets back a GEM handle in &drm_prime_handle.handle.
+ * &drm_prime_handle.flags is unused.
+ *
+ * If an existing GEM handle refers to the memory object backing the DMA-BUF,
+ * that GEM handle is returned. Therefore user-space which needs to handle
+ * arbitrary DMA-BUFs must have a user-space lookup data structure to manually
+ * reference-count duplicated GEM handles. For more information see
+ * &DRM_IOCTL_GEM_CLOSE.
+ *
+ * The import can fail for any driver-specific reason, e.g. because import is
+ * only supported for DMA-BUFs allocated on this DRM device.
+ *
+ * Support for importing DMA-BUFs is advertised via &DRM_PRIME_CAP_IMPORT.
+ */
 #define DRM_IOCTL_PRIME_FD_TO_HANDLE    DRM_IOWR(0x2e, struct drm_prime_handle)
 
 #define DRM_IOCTL_AGP_ACQUIRE          DRM_IO(  0x30)
@@ -1104,8 +1147,13 @@ extern "C" {
  * struct as the output.
  *
  * If the client is DRM master or has &CAP_SYS_ADMIN, &drm_mode_fb_cmd2.handles
- * will be filled with GEM buffer handles. Planes are valid until one has a
- * zero handle -- this can be used to compute the number of planes.
+ * will be filled with GEM buffer handles. Fresh new GEM handles are always
+ * returned, even if another GEM handle referring to the same memory object
+ * already exists on the DRM file description. The caller is responsible for
+ * removing the new handles, e.g. via the &DRM_IOCTL_GEM_CLOSE IOCTL. The same
+ * new handle will be returned for multiple planes in case they use the same
+ * memory object. Planes are valid until one has a zero handle -- this can be
+ * used to compute the number of planes.
  *
  * Otherwise, &drm_mode_fb_cmd2.handles will be zeroed and planes are valid
  * until one has a zero &drm_mode_fb_cmd2.pitches.
@@ -1113,6 +1161,11 @@ extern "C" {
  * If the framebuffer has a format modifier, &DRM_MODE_FB_MODIFIERS will be set
  * in &drm_mode_fb_cmd2.flags and &drm_mode_fb_cmd2.modifier will contain the
  * modifier. Otherwise, user-space must ignore &drm_mode_fb_cmd2.modifier.
+ *
+ * To obtain DMA-BUF FDs for each plane without leaking GEM handles, user-space
+ * can export each handle via &DRM_IOCTL_PRIME_HANDLE_TO_FD, then immediately
+ * close each unique handle via &DRM_IOCTL_GEM_CLOSE, making sure to not
+ * double-close handles which are specified multiple times in the array.
  */
 #define DRM_IOCTL_MODE_GETFB2          DRM_IOWR(0xCE, struct drm_mode_fb_cmd2)
 
index 8df261c5ab9b1a222b8d2aa000266a8568c43580..dba7c5a5b25e90367a80dec0830ff0258a9165ad 100644 (file)
@@ -2491,7 +2491,7 @@ struct i915_context_param_engines {
 #define I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE 0 /* see i915_context_engines_load_balance */
 #define I915_CONTEXT_ENGINES_EXT_BOND 1 /* see i915_context_engines_bond */
 #define I915_CONTEXT_ENGINES_EXT_PARALLEL_SUBMIT 2 /* see i915_context_engines_parallel_submit */
-       struct i915_engine_class_instance engines[0];
+       struct i915_engine_class_instance engines[];
 } __attribute__((packed));
 
 #define I915_DEFINE_CONTEXT_PARAM_ENGINES(name__, N__) struct { \
@@ -2676,6 +2676,10 @@ enum drm_i915_oa_format {
        I915_OAR_FORMAT_A32u40_A4u32_B8_C8,
        I915_OA_FORMAT_A24u40_A14u32_B8_C8,
 
+       /* MTL OAM */
+       I915_OAM_FORMAT_MPEC8u64_B8_C8,
+       I915_OAM_FORMAT_MPEC8u32_B8_C8,
+
        I915_OA_FORMAT_MAX          /* non-ABI */
 };
 
@@ -2758,6 +2762,25 @@ enum drm_i915_perf_property_id {
         */
        DRM_I915_PERF_PROP_POLL_OA_PERIOD,
 
+       /**
+        * Multiple engines may be mapped to the same OA unit. The OA unit is
+        * identified by class:instance of any engine mapped to it.
+        *
+        * This parameter specifies the engine class and must be passed along
+        * with DRM_I915_PERF_PROP_OA_ENGINE_INSTANCE.
+        *
+        * This property is available in perf revision 6.
+        */
+       DRM_I915_PERF_PROP_OA_ENGINE_CLASS,
+
+       /**
+        * This parameter specifies the engine instance and must be passed along
+        * with DRM_I915_PERF_PROP_OA_ENGINE_CLASS.
+        *
+        * This property is available in perf revision 6.
+        */
+       DRM_I915_PERF_PROP_OA_ENGINE_INSTANCE,
+
        DRM_I915_PERF_PROP_MAX /* non-ABI */
 };
 
index af2a44c08683def16a73892a7efe798bfb1b8aba..a429381e7ca507fe7f4d86f4e7fa229cdcda078b 100644 (file)
@@ -28,7 +28,7 @@
 #define _BITUL(x)      (_UL(1) << (x))
 #define _BITULL(x)     (_ULL(1) << (x))
 
-#define __ALIGN_KERNEL(x, a)           __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
+#define __ALIGN_KERNEL(x, a)           __ALIGN_KERNEL_MASK(x, (__typeof__(x))(a) - 1)
 #define __ALIGN_KERNEL_MASK(x, mask)   (((x) + (mask)) & ~(mask))
 
 #define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
index 07a4cb149305be99b1b661887abf5e37c2affc9a..e682ab628dfa66bcbc10f9b4adc08f2a61db377b 100644 (file)
@@ -162,6 +162,8 @@ struct in_addr {
 #define MCAST_MSFILTER                 48
 #define IP_MULTICAST_ALL               49
 #define IP_UNICAST_IF                  50
+#define IP_LOCAL_PORT_RANGE            51
+#define IP_PROTOCOL                    52
 
 #define MCAST_EXCLUDE  0
 #define MCAST_INCLUDE  1
index 4003a166328cc38027b4037527da91738944cf6b..737318b1c1d9a16345853c6c561847bf6270e435 100644 (file)
@@ -341,8 +341,13 @@ struct kvm_run {
                        __u64 nr;
                        __u64 args[6];
                        __u64 ret;
-                       __u32 longmode;
-                       __u32 pad;
+
+                       union {
+#ifndef __KERNEL__
+                               __u32 longmode;
+#endif
+                               __u64 flags;
+                       };
                } hypercall;
                /* KVM_EXIT_TPR_ACCESS */
                struct {
@@ -1184,6 +1189,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_S390_PROTECTED_ASYNC_DISABLE 224
 #define KVM_CAP_DIRTY_LOG_RING_WITH_BITMAP 225
 #define KVM_CAP_PMU_EVENT_MASKED_EVENTS 226
+#define KVM_CAP_COUNTER_OFFSET 227
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1543,6 +1549,8 @@ struct kvm_s390_ucas_mapping {
 #define KVM_SET_PMU_EVENT_FILTER  _IOW(KVMIO,  0xb2, struct kvm_pmu_event_filter)
 #define KVM_PPC_SVM_OFF                  _IO(KVMIO,  0xb3)
 #define KVM_ARM_MTE_COPY_TAGS    _IOR(KVMIO,  0xb4, struct kvm_arm_copy_mte_tags)
+/* Available with KVM_CAP_COUNTER_OFFSET */
+#define KVM_ARM_SET_COUNTER_OFFSET _IOW(KVMIO,  0xb5, struct kvm_arm_counter_offset)
 
 /* ioctl for vm fd */
 #define KVM_CREATE_DEVICE        _IOWR(KVMIO,  0xe0, struct kvm_create_device)
index 759b3f53e53f02373e90e4eb00ffec92f4c4802d..f23d9a16507f6f46b19179d176e5e409ee94d395 100644 (file)
@@ -290,6 +290,8 @@ struct prctl_mm_map {
 #define PR_SET_VMA             0x53564d41
 # define PR_SET_VMA_ANON_NAME          0
 
+#define PR_GET_AUXV                    0x41555856
+
 #define PR_SET_MEMORY_MERGE            67
 #define PR_GET_MEMORY_MERGE            68
 #endif /* _LINUX_PRCTL_H */
index de6810e94abed3e91de3ef42d1eaca0353c1b8d3..0aa955aa82463a63872a037dbd6ef7d3f08dfec1 100644 (file)
@@ -429,9 +429,14 @@ struct snd_pcm_sw_params {
        snd_pcm_uframes_t avail_min;            /* min avail frames for wakeup */
        snd_pcm_uframes_t xfer_align;           /* obsolete: xfer size need to be a multiple */
        snd_pcm_uframes_t start_threshold;      /* min hw_avail frames for automatic start */
-       snd_pcm_uframes_t stop_threshold;       /* min avail frames for automatic stop */
-       snd_pcm_uframes_t silence_threshold;    /* min distance from noise for silence filling */
-       snd_pcm_uframes_t silence_size;         /* silence block size */
+       /*
+        * The following two thresholds alleviate playback buffer underruns; when
+        * hw_avail drops below the threshold, the respective action is triggered:
+        */
+       snd_pcm_uframes_t stop_threshold;       /* - stop playback */
+       snd_pcm_uframes_t silence_threshold;    /* - pre-fill buffer with silence */
+       snd_pcm_uframes_t silence_size;         /* max size of silence pre-fill; when >= boundary,
+                                                * fill played area with silence immediately */
        snd_pcm_uframes_t boundary;             /* pointers wrap point */
        unsigned int proto;                     /* protocol version */
        unsigned int tstamp_type;               /* timestamp type (req. proto >= 2.0.12) */
@@ -570,7 +575,8 @@ struct __snd_pcm_mmap_status64 {
 struct __snd_pcm_mmap_control64 {
        __pad_before_uframe __pad1;
        snd_pcm_uframes_t appl_ptr;      /* RW: appl ptr (0...boundary-1) */
-       __pad_before_uframe __pad2;
+       __pad_before_uframe __pad2;      // This should be __pad_after_uframe, but binary
+                                        // backwards compatibility constraints prevent a fix.
 
        __pad_before_uframe __pad3;
        snd_pcm_uframes_t  avail_min;    /* RW: min available frames for wakeup */
index aa77bcae4807ea940251dcfbcb044e4515de995c..3144f33196be48b877ea262e43fabcfe2cfddab1 100644 (file)
@@ -591,8 +591,9 @@ class YnlFamily(SpecFamily):
                         print('Unexpected message: ' + repr(gm))
                         continue
 
-                rsp.append(self._decode(gm.raw_attrs, op.attr_set.name)
-                           | gm.fixed_header_attrs)
+                rsp_msg = self._decode(gm.raw_attrs, op.attr_set.name)
+                rsp_msg.update(gm.fixed_header_attrs)
+                rsp.append(rsp_msg)
 
         if not rsp:
             return None
index 4884520f954f4b2a6659705918d8673451139065..a794d9eca93d8e4d2da798fa0e5eedfe4bd4b017 100644 (file)
@@ -216,6 +216,12 @@ ifeq ($(call get-executable,$(BISON)),)
   dummy := $(error Error: $(BISON) is missing on this system, please install it)
 endif
 
+ifeq ($(BUILD_BPF_SKEL),1)
+  ifeq ($(call get-executable,$(CLANG)),)
+    dummy := $(error $(CLANG) is missing on this system, please install it to be able to build with BUILD_BPF_SKEL=1)
+  endif
+endif
+
 ifneq ($(OUTPUT),)
   ifeq ($(shell expr $(shell $(BISON) --version | grep bison | sed -e 's/.\+ \([0-9]\+\).\([0-9]\+\).\([0-9]\+\)/\1\2\3/g') \>\= 371), 1)
     BISON_FILE_PREFIX_MAP := --file-prefix-map=$(OUTPUT)=
@@ -921,6 +927,7 @@ ifndef NO_DEMANGLE
     EXTLIBS += -lstdc++
     CFLAGS += -DHAVE_CXA_DEMANGLE_SUPPORT
     CXXFLAGS += -DHAVE_CXA_DEMANGLE_SUPPORT
+    $(call detected,CONFIG_CXX_DEMANGLE)
   endif
   ifdef BUILD_NONDISTRO
     ifeq ($(filter -liberty,$(EXTLIBS)),)
index a42a6a99c2bca93e18dca795bd5e16cff2932ade..f48794816d82afb110e0bc5cbbc754a29f1b5509 100644 (file)
@@ -181,7 +181,6 @@ HOSTCC  ?= gcc
 HOSTLD  ?= ld
 HOSTAR  ?= ar
 CLANG   ?= clang
-LLVM_STRIP ?= llvm-strip
 
 PKG_CONFIG = $(CROSS_COMPILE)pkg-config
 
@@ -1057,15 +1056,33 @@ $(SKEL_TMP_OUT) $(LIBAPI_OUTPUT) $(LIBBPF_OUTPUT) $(LIBPERF_OUTPUT) $(LIBSUBCMD_
 
 ifdef BUILD_BPF_SKEL
 BPFTOOL := $(SKEL_TMP_OUT)/bootstrap/bpftool
-BPF_INCLUDE := -I$(SKEL_TMP_OUT)/.. -I$(LIBBPF_INCLUDE)
+# Get Clang's default includes on this system, as opposed to those seen by
+# '-target bpf'. This fixes "missing" files on some architectures/distros,
+# such as asm/byteorder.h, asm/socket.h, asm/sockios.h, sys/cdefs.h etc.
+#
+# Use '-idirafter': Don't interfere with include mechanics except where the
+# build would have failed anyways.
+define get_sys_includes
+$(shell $(1) $(2) -v -E - </dev/null 2>&1 \
+       | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') \
+$(shell $(1) $(2) -dM -E - </dev/null | grep '__riscv_xlen ' | awk '{printf("-D__riscv_xlen=%d -D__BITS_PER_LONG=%d", $$3, $$3)}')
+endef
+
+ifneq ($(CROSS_COMPILE),)
+CLANG_TARGET_ARCH = --target=$(notdir $(CROSS_COMPILE:%-=%))
+endif
+
+CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG),$(CLANG_TARGET_ARCH))
+BPF_INCLUDE := -I$(SKEL_TMP_OUT)/.. -I$(LIBBPF_INCLUDE) $(CLANG_SYS_INCLUDES)
+TOOLS_UAPI_INCLUDE := -I$(srctree)/tools/include/uapi
 
 $(BPFTOOL): | $(SKEL_TMP_OUT)
        $(Q)CFLAGS= $(MAKE) -C ../bpf/bpftool \
                OUTPUT=$(SKEL_TMP_OUT)/ bootstrap
 
 $(SKEL_TMP_OUT)/%.bpf.o: util/bpf_skel/%.bpf.c $(LIBBPF) | $(SKEL_TMP_OUT)
-       $(QUIET_CLANG)$(CLANG) -g -O2 -target bpf -Wall -Werror $(BPF_INCLUDE) \
-         -c $(filter util/bpf_skel/%.bpf.c,$^) -o $@ && $(LLVM_STRIP) -g $@
+       $(QUIET_CLANG)$(CLANG) -g -O2 -target bpf -Wall -Werror $(BPF_INCLUDE) $(TOOLS_UAPI_INCLUDE) \
+         -c $(filter util/bpf_skel/%.bpf.c,$^) -o $@
 
 $(SKEL_OUT)/%.skel.h: $(SKEL_TMP_OUT)/%.bpf.o | $(BPFTOOL)
        $(QUIET_GENSKEL)$(BPFTOOL) gen skeleton $< > $@
index 77cb03e6ff875e49195213c6dfa2a7170de057dd..9ca040bfb1aa7937c81f7ba4444c7867c49c1812 100644 (file)
@@ -78,9 +78,9 @@ static int cs_etm_validate_context_id(struct auxtrace_record *itr,
        char path[PATH_MAX];
        int err;
        u32 val;
-       u64 contextid =
-               evsel->core.attr.config &
-               (perf_pmu__format_bits(&cs_etm_pmu->format, "contextid1") |
+       u64 contextid = evsel->core.attr.config &
+               (perf_pmu__format_bits(&cs_etm_pmu->format, "contextid") |
+                perf_pmu__format_bits(&cs_etm_pmu->format, "contextid1") |
                 perf_pmu__format_bits(&cs_etm_pmu->format, "contextid2"));
 
        if (!contextid)
@@ -114,8 +114,7 @@ static int cs_etm_validate_context_id(struct auxtrace_record *itr,
                 *  0b00100 Maximum of 32-bit Context ID size.
                 *  All other values are reserved.
                 */
-               val = BMVAL(val, 5, 9);
-               if (!val || val != 0x4) {
+               if (BMVAL(val, 5, 9) != 0x4) {
                        pr_err("%s: CONTEXTIDR_EL1 isn't supported, disable with %s/contextid1=0/\n",
                               CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME);
                        return -EINVAL;
index 860a8b42b4b5b4aaaf09b59ce8f5be0ea9fe63dc..a9623b128ece2270059002f184f2dcffadbdaa2d 100644 (file)
@@ -12,7 +12,7 @@
 #include "arm-spe.h"
 #include "hisi-ptt.h"
 #include "../../../util/pmu.h"
-#include "../cs-etm.h"
+#include "../../../util/cs-etm.h"
 
 struct perf_event_attr
 *perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
index d730666ab95d21c4d2b834776d552980e9c6fa27..80b9f6287fe2f6ac13628d1882fcc239f5b305e1 100644 (file)
@@ -29,8 +29,8 @@ static int _get_cpuid(char *buf, size_t sz, struct perf_cpu_map *cpus)
                char path[PATH_MAX];
                FILE *file;
 
-               scnprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d"MIDR,
-                               sysfs, cpus->map[cpu]);
+               scnprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d" MIDR,
+                         sysfs, RC_CHK_ACCESS(cpus)->map[cpu].cpu);
 
                file = fopen(path, "r");
                if (!file) {
index fa143acb4c8d0cc9b20b84964f8f9d304ec5466f..ef1ed645097c62e1cc6ecd791b8ecd762201f42d 100644 (file)
@@ -18,7 +18,7 @@ static struct perf_pmu *pmu__find_core_pmu(void)
                 * The cpumap should cover all CPUs. Otherwise, some CPUs may
                 * not support some events or have different event IDs.
                 */
-               if (pmu->cpus->nr != cpu__max_cpu().cpu)
+               if (RC_CHK_ACCESS(pmu->cpus)->nr != cpu__max_cpu().cpu)
                        return NULL;
 
                return pmu;
index 799147658dee20dde3993818f977579429898e4d..b68f47541169f9afdc0b440ee9ead767d76471fc 100644 (file)
 444  common    landlock_create_ruleset sys_landlock_create_ruleset     sys_landlock_create_ruleset
 445  common    landlock_add_rule       sys_landlock_add_rule           sys_landlock_add_rule
 446  common    landlock_restrict_self  sys_landlock_restrict_self      sys_landlock_restrict_self
-# 447 reserved for memfd_secret
+447  common    memfd_secret            sys_memfd_secret                sys_memfd_secret
 448  common    process_mrelease        sys_process_mrelease            sys_process_mrelease
 449  common    futex_waitv             sys_futex_waitv                 sys_futex_waitv
 450  common    set_mempolicy_home_node sys_set_mempolicy_home_node     sys_set_mempolicy_home_node
index 50ae8bd58296eca6357986be401139f9dee4d95d..6188e19d312967d426ffd59cc9f9e4939c7db557 100644 (file)
@@ -7,7 +7,3 @@ MEMCPY_FN(memcpy_orig,
 MEMCPY_FN(__memcpy,
        "x86-64-movsq",
        "movsq-based memcpy() in arch/x86/lib/memcpy_64.S")
-
-MEMCPY_FN(memcpy_erms,
-       "x86-64-movsb",
-       "movsb-based memcpy() in arch/x86/lib/memcpy_64.S")
index 6eb45a2aa8db39a96a238a276121a983788ffec3..1b9fef7efcdcc08e635e28db25b2f32f2fa9fd41 100644 (file)
@@ -2,7 +2,7 @@
 
 /* Various wrappers to make the kernel .S file build in user-space: */
 
-// memcpy_orig and memcpy_erms are being defined as SYM_L_LOCAL but we need it
+// memcpy_orig is being defined as SYM_L_LOCAL but we need it
 #define SYM_FUNC_START_LOCAL(name)                      \
         SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN)
 #define memcpy MEMCPY /* don't hide glibc's memcpy() */
index dac6d2b7c39b2d39423fee72ae898cb9af83edea..247c72fdfb9d4083834177ab7c39ab36ae8900e6 100644 (file)
@@ -7,7 +7,3 @@ MEMSET_FN(memset_orig,
 MEMSET_FN(__memset,
        "x86-64-stosq",
        "movsq-based memset() in arch/x86/lib/memset_64.S")
-
-MEMSET_FN(memset_erms,
-       "x86-64-stosb",
-       "movsb-based memset() in arch/x86/lib/memset_64.S")
index 6f093c483842eaa2cafb9995400b7e3e18924b68..abd26c95f1aa00217b7aebf01b67e66916865ce4 100644 (file)
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-// memset_orig and memset_erms are being defined as SYM_L_LOCAL but we need it
+// memset_orig is being defined as SYM_L_LOCAL but we need it
 #define SYM_FUNC_START_LOCAL(name)                      \
         SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN)
 #define memset MEMSET /* don't hide glibc's memset() */
index 810e3376c7d6cb4c0f5733cc9d8659f103383fb4..f9906f52e4fa795a84f1402f6b7512a1adf0af50 100644 (file)
@@ -1175,7 +1175,7 @@ int cmd_ftrace(int argc, const char **argv)
        OPT_BOOLEAN('b', "use-bpf", &ftrace.target.use_bpf,
                    "Use BPF to measure function latency"),
 #endif
-       OPT_BOOLEAN('n', "--use-nsec", &ftrace.use_nsec,
+       OPT_BOOLEAN('n', "use-nsec", &ftrace.use_nsec,
                    "Use nano-second histogram"),
        OPT_PARENT(common_options),
        };
index 006f522d0e7f6a182f2c635f7d5b6ec50a9c6bf2..c57be48d65bb039e2ffe67b4702b47254d900af3 100644 (file)
@@ -3647,6 +3647,13 @@ static int process_stat_config_event(struct perf_session *session __maybe_unused
                                     union perf_event *event)
 {
        perf_event__read_stat_config(&stat_config, &event->stat_config);
+
+       /*
+        * Aggregation modes are not used since post-processing scripts are
+        * supposed to take care of such requirements
+        */
+       stat_config.aggr_mode = AGGR_NONE;
+
        return 0;
 }
 
index cc9fa48d636f02039a31aec60a9be0dc0c97bfc0..b9ad32f21e575b4c1963fc84b84f57b405ad00bd 100644 (file)
@@ -667,6 +667,13 @@ static enum counter_recovery stat_handle_error(struct evsel *counter)
                        evsel_list->core.threads->err_thread = -1;
                        return COUNTER_RETRY;
                }
+       } else if (counter->skippable) {
+               if (verbose > 0)
+                       ui__warning("skipping event %s that kernel failed to open .\n",
+                                   evsel__name(counter));
+               counter->supported = false;
+               counter->errored = true;
+               return COUNTER_SKIP;
        }
 
        evsel__open_strerror(counter, &target, errno, msg, sizeof(msg));
@@ -1890,15 +1897,28 @@ static int add_default_attributes(void)
                 * caused by exposing latent bugs. This is fixed properly in:
                 * https://lore.kernel.org/lkml/bff481ba-e60a-763f-0aa0-3ee53302c480@linux.intel.com/
                 */
-               if (metricgroup__has_metric("TopdownL1") && !perf_pmu__has_hybrid() &&
-                   metricgroup__parse_groups(evsel_list, "TopdownL1",
-                                           /*metric_no_group=*/false,
-                                           /*metric_no_merge=*/false,
-                                           /*metric_no_threshold=*/true,
-                                           stat_config.user_requested_cpu_list,
-                                           stat_config.system_wide,
-                                           &stat_config.metric_events) < 0)
-                       return -1;
+               if (metricgroup__has_metric("TopdownL1") && !perf_pmu__has_hybrid()) {
+                       struct evlist *metric_evlist = evlist__new();
+                       struct evsel *metric_evsel;
+
+                       if (!metric_evlist)
+                               return -1;
+
+                       if (metricgroup__parse_groups(metric_evlist, "TopdownL1",
+                                                       /*metric_no_group=*/false,
+                                                       /*metric_no_merge=*/false,
+                                                       /*metric_no_threshold=*/true,
+                                                       stat_config.user_requested_cpu_list,
+                                                       stat_config.system_wide,
+                                                       &stat_config.metric_events) < 0)
+                               return -1;
+
+                       evlist__for_each_entry(metric_evlist, metric_evsel) {
+                               metric_evsel->skippable = true;
+                       }
+                       evlist__splice_list_tail(evsel_list, &metric_evlist->core.entries);
+                       evlist__delete(metric_evlist);
+               }
 
                /* Platform specific attrs */
                if (evlist__add_default_attrs(evsel_list, default_null_attrs) < 0)
index 75d80e70e5cd18a3648723b1bbe86bbcab1a0d92..1f90475539423da87e1c77981ed3d4dc1f037875 100644 (file)
         "MetricGroup": "TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "Counts the total number of issue slots  that were not consumed by the backend due to backend stalls.  Note that uops must be available for consumption in order for this event to count.  If a uop is not available (IQ is empty), this event will not count.   The rest of these subevents count backend stalls, in cycles, due to an outstanding request which is memory bound vs core bound.   The subevents are not slot based events and therefore can not be precisely added or subtracted from the Backend_Bound_Aux subevents which are slot based.",
         "ScaleUnit": "100%",
         "Unit": "cpu_atom"
         "MetricGroup": "TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound_aux",
         "MetricThreshold": "tma_backend_bound_aux > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "Counts the total number of issue slots  that were not consumed by the backend due to backend stalls.  Note that UOPS must be available for consumption in order for this event to count.  If a uop is not available (IQ is empty), this event will not count.  All of these subevents count backend stalls, in slots, due to a resource limitation.   These are not cycle based events and therefore can not be precisely added or subtracted from the Backend_Bound subevents which are cycle based.  These subevents are supplementary to Backend_Bound and can be used to analyze results from a resource perspective at allocation.",
         "ScaleUnit": "100%",
         "Unit": "cpu_atom"
         "MetricGroup": "TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "Counts the total number of issue slots that were not consumed by the backend because allocation is stalled due to a mispredicted jump or a machine clear. Only issue slots wasted due to fast nukes such as memory ordering nukes are counted. Other nukes are not accounted for. Counts all issue slots blocked during this recovery window including relevant microcode flows and while uops are not yet available in the instruction queue (IQ). Also includes the issue slots that were consumed by the backend but were thrown away because they were younger than the mispredict or machine clear.",
         "ScaleUnit": "100%",
         "Unit": "cpu_atom"
         "MetricGroup": "TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_base",
         "MetricThreshold": "tma_base > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "ScaleUnit": "100%",
         "Unit": "cpu_atom"
     },
         "MetricGroup": "TopdownL2;tma_L2_group;tma_bad_speculation_group",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.05",
+        "MetricgroupNoGroup": "TopdownL2",
         "ScaleUnit": "100%",
         "Unit": "cpu_atom"
     },
         "MetricGroup": "TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "ScaleUnit": "100%",
         "Unit": "cpu_atom"
     },
         "MetricGroup": "TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "ScaleUnit": "100%",
         "Unit": "cpu_atom"
     },
         "MetricGroup": "TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "ScaleUnit": "100%",
         "Unit": "cpu_atom"
     },
         "MetricGroup": "TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "ScaleUnit": "100%",
         "Unit": "cpu_atom"
     },
         "MetricGroup": "TopdownL2;tma_L2_group;tma_bad_speculation_group",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.05",
+        "MetricgroupNoGroup": "TopdownL2",
         "ScaleUnit": "100%",
         "Unit": "cpu_atom"
     },
         "MetricGroup": "TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "ScaleUnit": "100%",
         "Unit": "cpu_atom"
     },
         "MetricGroup": "TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_ms_uops",
         "MetricThreshold": "tma_ms_uops > 0.05",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "Counts the number of uops that are from the complex flows issued by the micro-sequencer (MS).  This includes uops from flows due to complex instructions, faults, assists, and inserted flows.",
         "ScaleUnit": "100%",
         "Unit": "cpu_atom"
         "MetricGroup": "TopdownL2;tma_L2_group;tma_backend_bound_aux_group",
         "MetricName": "tma_resource_bound",
         "MetricThreshold": "tma_resource_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "Counts the total number of issue slots  that were not consumed by the backend due to backend stalls.  Note that uops must be available for consumption in order for this event to count.  If a uop is not available (IQ is empty), this event will not count.",
         "ScaleUnit": "100%",
         "Unit": "cpu_atom"
         "MetricGroup": "TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.75",
+        "MetricgroupNoGroup": "TopdownL1",
         "ScaleUnit": "100%",
         "Unit": "cpu_atom"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound. Sample with: TOPDOWN.BACKEND_BOUND_SLOTS",
         "ScaleUnit": "100%",
         "Unit": "cpu_core"
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%",
         "Unit": "cpu_core"
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: TOPDOWN.BR_MISPREDICT_SLOTS. Related metrics: tma_info_branch_misprediction_cost, tma_info_mispredictions, tma_mispredicts_resteers",
         "ScaleUnit": "100%",
         "Unit": "cpu_core"
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%",
         "Unit": "cpu_core"
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 6 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Sample with: FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_2_PS. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_info_dsb_misses, tma_info_iptb, tma_lcp",
         "ScaleUnit": "100%",
         "Unit": "cpu_core"
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: FRONTEND_RETIRED.LATENCY_GE_16_PS;FRONTEND_RETIRED.LATENCY_GE_8_PS",
         "ScaleUnit": "100%",
         "Unit": "cpu_core"
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound. Sample with: FRONTEND_RETIRED.LATENCY_GE_4_PS",
         "ScaleUnit": "100%",
         "Unit": "cpu_core"
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences. Sample with: UOPS_RETIRED.HEAVY",
         "ScaleUnit": "100%",
         "Unit": "cpu_core"
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%",
         "Unit": "cpu_core"
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_contested_accesses, tma_data_sharing, tma_false_sharing, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%",
         "Unit": "cpu_core"
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%",
         "Unit": "cpu_core"
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.SLOTS",
         "ScaleUnit": "100%",
         "Unit": "cpu_core"
index 1a85d935c733ca6840b2cba048640435d17f1058..0402adbf7d9278138dabeb21a6e785c429281e59 100644 (file)
@@ -98,6 +98,7 @@
         "MetricGroup": "TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "Counts the total number of issue slots  that were not consumed by the backend due to backend stalls.  Note that uops must be available for consumption in order for this event to count.  If a uop is not available (IQ is empty), this event will not count.   The rest of these subevents count backend stalls, in cycles, due to an outstanding request which is memory bound vs core bound.   The subevents are not slot based events and therefore can not be precisely added or subtracted from the Backend_Bound_Aux subevents which are slot based.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound_aux",
         "MetricThreshold": "tma_backend_bound_aux > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "Counts the total number of issue slots  that were not consumed by the backend due to backend stalls.  Note that UOPS must be available for consumption in order for this event to count.  If a uop is not available (IQ is empty), this event will not count.  All of these subevents count backend stalls, in slots, due to a resource limitation.   These are not cycle based events and therefore can not be precisely added or subtracted from the Backend_Bound subevents which are cycle based.  These subevents are supplementary to Backend_Bound and can be used to analyze results from a resource perspective at allocation.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "Counts the total number of issue slots that were not consumed by the backend because allocation is stalled due to a mispredicted jump or a machine clear. Only issue slots wasted due to fast nukes such as memory ordering nukes are counted. Other nukes are not accounted for. Counts all issue slots blocked during this recovery window including relevant microcode flows and while uops are not yet available in the instruction queue (IQ). Also includes the issue slots that were consumed by the backend but were thrown away because they were younger than the mispredict or machine clear.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_base",
         "MetricThreshold": "tma_base > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "ScaleUnit": "100%"
     },
     {
         "MetricGroup": "TopdownL2;tma_L2_group;tma_bad_speculation_group",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.05",
+        "MetricgroupNoGroup": "TopdownL2",
         "ScaleUnit": "100%"
     },
     {
         "MetricGroup": "TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "ScaleUnit": "100%"
     },
     {
         "MetricGroup": "TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "ScaleUnit": "100%"
     },
     {
         "MetricGroup": "TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "ScaleUnit": "100%"
     },
     {
         "MetricGroup": "TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "ScaleUnit": "100%"
     },
     {
         "MetricGroup": "TopdownL2;tma_L2_group;tma_bad_speculation_group",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.05",
+        "MetricgroupNoGroup": "TopdownL2",
         "ScaleUnit": "100%"
     },
     {
         "MetricGroup": "TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "ScaleUnit": "100%"
     },
     {
         "MetricGroup": "TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_ms_uops",
         "MetricThreshold": "tma_ms_uops > 0.05",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "Counts the number of uops that are from the complex flows issued by the micro-sequencer (MS).  This includes uops from flows due to complex instructions, faults, assists, and inserted flows.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TopdownL2;tma_L2_group;tma_backend_bound_aux_group",
         "MetricName": "tma_resource_bound",
         "MetricThreshold": "tma_resource_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "Counts the total number of issue slots  that were not consumed by the backend due to backend stalls.  Note that uops must be available for consumption in order for this event to count.  If a uop is not available (IQ is empty), this event will not count.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.75",
+        "MetricgroupNoGroup": "TopdownL1",
         "ScaleUnit": "100%"
     },
     {
index 51cf8560a8d38c187c870dc57c95a607acf7bc0a..f9e2316601e1eeaa3177205848f6a886b042316d 100644 (file)
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: BR_MISP_RETIRED.ALL_BRANCHES. Related metrics: tma_info_branch_misprediction_cost, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 4 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_info_iptb, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: RS_EVENTS.EMPTY_END",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_contested_accesses, tma_data_sharing, tma_false_sharing, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.RETIRE_SLOTS",
         "ScaleUnit": "100%"
     },
index fb57c7382408447e953e19e6e9d548708bb86a56..e9c46d336a8e0d6baf845c02bc96c65a1aede21f 100644 (file)
@@ -97,6 +97,7 @@
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound. Sample with: TOPDOWN.BACKEND_BOUND_SLOTS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: TOPDOWN.BR_MISPREDICT_SLOTS. Related metrics: tma_info_branch_misprediction_cost, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 4 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Sample with: FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_2_PS. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_info_iptb, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: FRONTEND_RETIRED.LATENCY_GE_16_PS;FRONTEND_RETIRED.LATENCY_GE_8_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound. Sample with: FRONTEND_RETIRED.LATENCY_GE_4_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_contested_accesses, tma_data_sharing, tma_false_sharing, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.SLOTS",
         "ScaleUnit": "100%"
     },
index 65ec0c9e55d1216f086a2964be8a10710999ab17..437b9867acb9f70d4b462e9aea02f5c59c106614 100644 (file)
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: BR_MISP_RETIRED.ALL_BRANCHES. Related metrics: tma_info_branch_misprediction_cost, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 4 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_info_iptb, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: RS_EVENTS.EMPTY_END",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_contested_accesses, tma_data_sharing, tma_false_sharing, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.RETIRE_SLOTS",
         "ScaleUnit": "100%"
     },
index 8f7dc72accd06e426de4c83762b02a50feca98a2..875c766222e36234b6250da7c6dcd2c4fb79c535 100644 (file)
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: BR_MISP_RETIRED.ALL_BRANCHES. Related metrics: tma_info_branch_misprediction_cost, tma_info_mispredictions, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 4 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Sample with: FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_2_PS. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_info_dsb_misses, tma_info_iptb, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: FRONTEND_RETIRED.LATENCY_GE_16_PS;FRONTEND_RETIRED.LATENCY_GE_8_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound. Sample with: FRONTEND_RETIRED.LATENCY_GE_4_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_contested_accesses, tma_data_sharing, tma_false_sharing, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.RETIRE_SLOTS",
         "ScaleUnit": "100%"
     },
index 2528418200bb85e1442c323859d2f2e5d0667a8e..9570a88d6d1c1c399de6ce13bcf444d49c8cf7ba 100644 (file)
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: BR_MISP_RETIRED.ALL_BRANCHES. Related metrics: tma_info_branch_misprediction_cost, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 4 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_info_iptb, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: RS_EVENTS.EMPTY_END",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_contested_accesses, tma_data_sharing, tma_false_sharing, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.RETIRE_SLOTS",
         "ScaleUnit": "100%"
     },
index 11f152c346eb056dcf169307aa753f4732e1b40b..a522202cf6844cb9ae9f1ddcfe754a6b31f2ee12 100644 (file)
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: BR_MISP_RETIRED.ALL_BRANCHES. Related metrics: tma_info_branch_misprediction_cost, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 4 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_info_iptb, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: RS_EVENTS.EMPTY_END",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_contested_accesses, tma_data_sharing, tma_false_sharing, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.RETIRE_SLOTS",
         "ScaleUnit": "100%"
     },
index f45ae3483df4859b461cffab5c53461dfa4d287c..1a2154f28b7b5f34c7d555c27e5e88edbedbf792 100644 (file)
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound. Sample with: TOPDOWN.BACKEND_BOUND_SLOTS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: BR_MISP_RETIRED.ALL_BRANCHES. Related metrics: tma_info_branch_misprediction_cost, tma_info_mispredictions, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 5 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Sample with: FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_2_PS. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_info_dsb_misses, tma_info_iptb, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: FRONTEND_RETIRED.LATENCY_GE_16_PS;FRONTEND_RETIRED.LATENCY_GE_8_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound. Sample with: FRONTEND_RETIRED.LATENCY_GE_4_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_contested_accesses, tma_data_sharing, tma_false_sharing, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.SLOTS",
         "ScaleUnit": "100%"
     },
index 0f9b174dfc22ae658f3ad8a3a2b208087f420d29..1ef772b40e045bc516436b245b5f973ab0d2e617 100644 (file)
@@ -80,6 +80,7 @@
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound. Sample with: TOPDOWN.BACKEND_BOUND_SLOTS",
         "ScaleUnit": "100%"
     },
@@ -89,6 +90,7 @@
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: BR_MISP_RETIRED.ALL_BRANCHES. Related metrics: tma_info_branch_misprediction_cost, tma_info_mispredictions, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 5 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Sample with: FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_2_PS. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_info_dsb_misses, tma_info_iptb, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: FRONTEND_RETIRED.LATENCY_GE_16_PS;FRONTEND_RETIRED.LATENCY_GE_8_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound. Sample with: FRONTEND_RETIRED.LATENCY_GE_4_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_contested_accesses, tma_data_sharing, tma_false_sharing, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.SLOTS",
         "ScaleUnit": "100%"
     },
index 5247f69c13b641557573b2784553658226afdf17..11080ccffd5145bdba23ad55dae94fcdd87d03fc 100644 (file)
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: BR_MISP_RETIRED.ALL_BRANCHES. Related metrics: tma_info_branch_misprediction_cost, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 4 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_info_iptb, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: RS_EVENTS.EMPTY_END",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_contested_accesses, tma_data_sharing, tma_false_sharing, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.RETIRE_SLOTS",
         "ScaleUnit": "100%"
     },
index 89469b10fa3040194e559e9c8caefce281d23fa1..65a46d659c0a2bc145ee1d378b2787feb5f03a4c 100644 (file)
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: BR_MISP_RETIRED.ALL_BRANCHES. Related metrics: tma_info_branch_misprediction_cost, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 4 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_info_iptb, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: RS_EVENTS.EMPTY_END",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_contested_accesses, tma_data_sharing, tma_false_sharing, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.RETIRE_SLOTS",
         "ScaleUnit": "100%"
     },
index e8f4e5c01c9fb4ca170f0b83e08199dd91bcd6ba..66a6f657bd6f7f4911af37fa68d0b8847ab9d04b 100644 (file)
@@ -76,6 +76,7 @@
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound.",
         "ScaleUnit": "100%"
     },
@@ -85,6 +86,7 @@
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
@@ -95,6 +97,7 @@
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: BR_MISP_RETIRED.ALL_BRANCHES. Related metrics: tma_info_branch_misprediction_cost, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 4 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: RS_EVENTS.EMPTY_END",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.RETIRE_SLOTS",
         "ScaleUnit": "100%"
     },
index 4a99fe515f4b0d7df39005fc51dc579e552ec85e..4b8bc19392a4436fceb4c00bf9e2a59ebb36bbaf 100644 (file)
@@ -76,6 +76,7 @@
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound.",
         "ScaleUnit": "100%"
     },
@@ -85,6 +86,7 @@
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
@@ -95,6 +97,7 @@
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: BR_MISP_RETIRED.ALL_BRANCHES. Related metrics: tma_info_branch_misprediction_cost, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 4 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: RS_EVENTS.EMPTY_END",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.RETIRE_SLOTS",
         "ScaleUnit": "100%"
     },
index 126300b7ae777454c263d592c1cc12b428f5377e..620fc5bd2217d85bb30c65aeac16d98f01237c8d 100644 (file)
@@ -87,6 +87,7 @@
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound. Sample with: TOPDOWN.BACKEND_BOUND_SLOTS",
         "ScaleUnit": "100%"
     },
@@ -96,6 +97,7 @@
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: TOPDOWN.BR_MISPREDICT_SLOTS. Related metrics: tma_info_branch_misprediction_cost, tma_info_mispredictions, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 6 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Sample with: FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_2_PS. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_info_dsb_misses, tma_info_iptb, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: FRONTEND_RETIRED.LATENCY_GE_16_PS;FRONTEND_RETIRED.LATENCY_GE_8_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound. Sample with: FRONTEND_RETIRED.LATENCY_GE_4_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences. Sample with: UOPS_RETIRED.HEAVY",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_contested_accesses, tma_data_sharing, tma_false_sharing, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.SLOTS",
         "ScaleUnit": "100%"
     },
index a6d212b349f5d9950823c5be8797f0eab8aa800f..21ef6c9be8167d78ab79293a9c5848897b857e4d 100644 (file)
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: BR_MISP_RETIRED.ALL_BRANCHES. Related metrics: tma_info_branch_misprediction_cost, tma_info_mispredictions, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 4 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Sample with: FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_2_PS. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_info_dsb_misses, tma_info_iptb, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: FRONTEND_RETIRED.LATENCY_GE_16_PS;FRONTEND_RETIRED.LATENCY_GE_8_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound. Sample with: FRONTEND_RETIRED.LATENCY_GE_4_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_contested_accesses, tma_data_sharing, tma_false_sharing, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.RETIRE_SLOTS",
         "ScaleUnit": "100%"
     },
index fa2f7f126a305aaefef1dd69f870cc624d0a7a37..eb6f12c0343d563451067ae928487c9e9244c1b6 100644 (file)
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: BR_MISP_RETIRED.ALL_BRANCHES. Related metrics: tma_info_branch_misprediction_cost, tma_info_mispredictions, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 4 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Sample with: FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_2_PS. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_info_dsb_misses, tma_info_iptb, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: FRONTEND_RETIRED.LATENCY_GE_16_PS;FRONTEND_RETIRED.LATENCY_GE_8_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound. Sample with: FRONTEND_RETIRED.LATENCY_GE_4_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_contested_accesses, tma_data_sharing, tma_false_sharing, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.RETIRE_SLOTS",
         "ScaleUnit": "100%"
     },
index 4c80d6be6cf1d29edee435e0838966598c418073..b442ed4acfbb41b99c9aad97c557f1cd5d6bc319 100644 (file)
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_backend_bound",
         "MetricThreshold": "tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound. Sample with: TOPDOWN.BACKEND_BOUND_SLOTS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_bad_speculation",
         "MetricThreshold": "tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;BrMispredicts;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueBM",
         "MetricName": "tma_branch_mispredicts",
         "MetricThreshold": "tma_branch_mispredicts > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Branch Misprediction.  These slots are either wasted by uops fetched from an incorrectly speculated program path; or stalls when the out-of-order part of the machine needs to recover its state from a speculative path. Sample with: BR_MISP_RETIRED.ALL_BRANCHES. Related metrics: tma_info_branch_misprediction_cost, tma_info_mispredictions, tma_mispredicts_resteers",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;Compute;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_core_bound",
         "MetricThreshold": "tma_core_bound > 0.1 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where Core non-memory issues were of a bottleneck.  Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. Hence it may indicate the machine ran out of an out-of-order resource; certain execution units are overloaded or dependencies in program's data- or instruction-flow are limiting the performance (e.g. FP-chained long-latency arithmetic operations).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "FetchBW;Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group;tma_issueFB",
         "MetricName": "tma_fetch_bandwidth",
         "MetricThreshold": "tma_fetch_bandwidth > 0.1 & tma_frontend_bound > 0.15 & tma_info_ipc / 5 > 0.35",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend bandwidth issues.  For example; inefficiencies at the instruction decoders; or restrictions for caching in the DSB (decoded uops cache) are categorized under Fetch Bandwidth. In such cases; the Frontend typically delivers suboptimal amount of uops to the Backend. Sample with: FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_1_PS;FRONTEND_RETIRED.LATENCY_GE_2_PS. Related metrics: tma_dsb_switches, tma_info_dsb_coverage, tma_info_dsb_misses, tma_info_iptb, tma_lcp",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Frontend;TmaL2;TopdownL2;tma_L2_group;tma_frontend_bound_group",
         "MetricName": "tma_fetch_latency",
         "MetricThreshold": "tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU was stalled due to Frontend latency issues.  For example; instruction-cache misses; iTLB misses or fetch stalls after a branch misprediction are categorized under Frontend Latency. In such cases; the Frontend eventually delivers no uops for some period. Sample with: FRONTEND_RETIRED.LATENCY_GE_16_PS;FRONTEND_RETIRED.LATENCY_GE_8_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "PGO;TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_frontend_bound",
         "MetricThreshold": "tma_frontend_bound > 0.15",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Pipeline_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound. Sample with: FRONTEND_RETIRED.LATENCY_GE_4_PS",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_heavy_operations",
         "MetricThreshold": "tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring heavy-weight operations -- instructions that require two or more uops or micro-coded sequences. This highly-correlates with the uop length of these instructions/sequences.",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Retire;TmaL2;TopdownL2;tma_L2_group;tma_retiring_group",
         "MetricName": "tma_light_operations",
         "MetricThreshold": "tma_light_operations > 0.6",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots where the CPU was retiring light-weight operations -- instructions that require no more than one uop (micro-operation). This correlates with total number of instructions used by the program. A uops-per-instruction (see UopPI metric) ratio of 1 or less should be expected for decently optimized software running on Intel Core/Xeon products. While this often indicates efficient X86 instructions were executed; high value does not necessarily mean better performance cannot be achieved. Sample with: INST_RETIRED.PREC_DIST",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "BadSpec;MachineClears;TmaL2;TopdownL2;tma_L2_group;tma_bad_speculation_group;tma_issueMC;tma_issueSyncxn",
         "MetricName": "tma_machine_clears",
         "MetricThreshold": "tma_machine_clears > 0.1 & tma_bad_speculation > 0.15",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the CPU has wasted due to Machine Clears.  These slots are either wasted by uops fetched prior to the clear; or stalls the out-of-order portion of the machine needs to recover its state after the clear. For example; this can happen due to memory ordering Nukes (e.g. Memory Disambiguation) or Self-Modifying-Code (SMC) nukes. Sample with: MACHINE_CLEARS.COUNT. Related metrics: tma_clears_resteers, tma_contested_accesses, tma_data_sharing, tma_false_sharing, tma_l1_bound, tma_microcode_sequencer, tma_ms_switches, tma_remote_cache",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "Backend;TmaL2;TopdownL2;tma_L2_group;tma_backend_bound_group",
         "MetricName": "tma_memory_bound",
         "MetricThreshold": "tma_memory_bound > 0.2 & tma_backend_bound > 0.2",
+        "MetricgroupNoGroup": "TopdownL2",
         "PublicDescription": "This metric represents fraction of slots the Memory subsystem within the Backend was a bottleneck.  Memory Bound estimates fraction of slots where pipeline is likely stalled due to demand load or store instructions. This accounts mainly for (1) non-completed in-flight memory demand loads which coincides with execution units starvation; in addition to (2) cases where stores could impose backpressure on the pipeline when many of them get buffered at the same time (less common out of the two).",
         "ScaleUnit": "100%"
     },
         "MetricGroup": "TmaL1;TopdownL1;tma_L1_group",
         "MetricName": "tma_retiring",
         "MetricThreshold": "tma_retiring > 0.7 | tma_heavy_operations > 0.1",
+        "MetricgroupNoGroup": "TopdownL1",
         "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category.  Retiring of 100% would indicate the maximum Pipeline_Width throughput was achieved.  Maximizing Retiring typically increases the Instructions-per-cycle (see IPC metric). Note that a high Retiring value does not necessary mean there is no room for more performance.  For example; Heavy-operations or Microcode Assists are categorized under Retiring. They often indicate suboptimal performance and can often be optimized or avoided. Sample with: UOPS_RETIRED.SLOTS",
         "ScaleUnit": "100%"
     },
index ca99b9cfe4ada503f08ba6f2f3b1f23fe699b53e..f57a8f2740257792f8aca97e28bbcfe6708e7870 100755 (executable)
@@ -52,7 +52,8 @@ _json_event_attributes = [
 # Attributes that are in pmu_metric rather than pmu_event.
 _json_metric_attributes = [
     'metric_name', 'metric_group', 'metric_expr', 'metric_threshold', 'desc',
-    'long_desc', 'unit', 'compat', 'aggr_mode', 'event_grouping'
+    'long_desc', 'unit', 'compat', 'metricgroup_no_group', 'aggr_mode',
+    'event_grouping'
 ]
 # Attributes that are bools or enum int values, encoded as '0', '1',...
 _json_enum_attributes = ['aggr_mode', 'deprecated', 'event_grouping', 'perpkg']
@@ -303,6 +304,7 @@ class JsonEvent:
     self.deprecated = jd.get('Deprecated')
     self.metric_name = jd.get('MetricName')
     self.metric_group = jd.get('MetricGroup')
+    self.metricgroup_no_group = jd.get('MetricgroupNoGroup')
     self.event_grouping = convert_metric_constraint(jd.get('MetricConstraint'))
     self.metric_expr = None
     if 'MetricExpr' in jd:
index b7dff8f1021fde0a0377ae7e52197999f57b1fb4..80349685cf4d88062eda3017486433d91bc4946c 100644 (file)
@@ -59,6 +59,7 @@ struct pmu_metric {
        const char *compat;
        const char *desc;
        const char *long_desc;
+       const char *metricgroup_no_group;
        enum aggr_mode_class aggr_mode;
        enum metric_event_groups event_grouping;
 };
index ccfef861e9315c3c8cc464040fd7a7e72200657e..e890c261ad2695d83061be879a280778a283c79a 100644 (file)
@@ -152,7 +152,7 @@ def parse_version(version):
 #   - expected values assignments
 class Test(object):
     def __init__(self, path, options):
-        parser = configparser.SafeConfigParser()
+        parser = configparser.ConfigParser()
         parser.read(path)
 
         log.warning("running '%s'" % path)
@@ -247,7 +247,7 @@ class Test(object):
         return True
 
     def load_events(self, path, events):
-        parser_event = configparser.SafeConfigParser()
+        parser_event = configparser.ConfigParser()
         parser_event.read(path)
 
         # The event record section header contains 'event' word,
@@ -261,7 +261,7 @@ class Test(object):
             # Read parent event if there's any
             if (':' in section):
                 base = section[section.index(':') + 1:]
-                parser_base = configparser.SafeConfigParser()
+                parser_base = configparser.ConfigParser()
                 parser_base.read(self.test_dir + '/' + base)
                 base_items = parser_base.items('event')
 
index a21fb65bc012ebfb8230b528109a73d3a29cb2ed..fccd8ec4d1b0225ce30bb51659a8aed5ab1f4574 100644 (file)
@@ -16,7 +16,7 @@ pinned=0
 exclusive=0
 exclude_user=0
 exclude_kernel=0|1
-exclude_hv=0
+exclude_hv=0|1
 exclude_idle=0
 mmap=0
 comm=0
index d8ea6a88163fbd1405cd072ad6cd94d4b68e029e..a1e2da0a9a6ddb10c6acc9eba1beae5cc39b6346 100644 (file)
@@ -40,7 +40,6 @@ fd=6
 type=0
 config=7
 optional=1
-
 # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
 [event7:base-stat]
 fd=7
@@ -89,79 +88,98 @@ enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
+# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
 [event13:base-stat]
 fd=13
 group_fd=11
 type=4
-config=33024
+config=33280
 disabled=0
 enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
+# PERF_TYPE_RAW / topdown-be-bound (0x8300)
 [event14:base-stat]
 fd=14
 group_fd=11
 type=4
-config=33280
+config=33536
 disabled=0
 enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-be-bound (0x8300)
+# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
 [event15:base-stat]
 fd=15
 group_fd=11
 type=4
-config=33536
+config=33024
 disabled=0
 enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-heavy-ops (0x8400)
+# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING
 [event16:base-stat]
 fd=16
-group_fd=11
 type=4
-config=33792
-disabled=0
-enable_on_exec=0
-read_format=15
+config=4109
 optional=1
 
-# PERF_TYPE_RAW / topdown-br-mispredict (0x8500)
+# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/
 [event17:base-stat]
 fd=17
-group_fd=11
 type=4
-config=34048
-disabled=0
-enable_on_exec=0
-read_format=15
+config=17039629
 optional=1
 
-# PERF_TYPE_RAW / topdown-fetch-lat (0x8600)
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD
 [event18:base-stat]
 fd=18
-group_fd=11
 type=4
-config=34304
-disabled=0
-enable_on_exec=0
-read_format=15
+config=60
 optional=1
 
-# PERF_TYPE_RAW / topdown-mem-bound (0x8700)
+# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY
 [event19:base-stat]
 fd=19
-group_fd=11
 type=4
-config=34560
-disabled=0
-enable_on_exec=0
-read_format=15
+config=2097421
+optional=1
+
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK
+[event20:base-stat]
+fd=20
+type=4
+config=316
+optional=1
+
+# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE
+[event21:base-stat]
+fd=21
+type=4
+config=412
+optional=1
+
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE
+[event22:base-stat]
+fd=22
+type=4
+config=572
+optional=1
+
+# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS
+[event23:base-stat]
+fd=23
+type=4
+config=706
+optional=1
+
+# PERF_TYPE_RAW / UOPS_ISSUED.ANY
+[event24:base-stat]
+fd=24
+type=4
+config=270
 optional=1
index b656ab93c5bf910ded52eebca2fa7f985d7b6221..1c52cb05c900d79c2d65dc4c620c0aa151820547 100644 (file)
@@ -90,89 +90,108 @@ enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
+# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
 [event13:base-stat]
 fd=13
 group_fd=11
 type=4
-config=33024
+config=33280
 disabled=0
 enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
+# PERF_TYPE_RAW / topdown-be-bound (0x8300)
 [event14:base-stat]
 fd=14
 group_fd=11
 type=4
-config=33280
+config=33536
 disabled=0
 enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-be-bound (0x8300)
+# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
 [event15:base-stat]
 fd=15
 group_fd=11
 type=4
-config=33536
+config=33024
 disabled=0
 enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-heavy-ops (0x8400)
+# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING
 [event16:base-stat]
 fd=16
-group_fd=11
 type=4
-config=33792
-disabled=0
-enable_on_exec=0
-read_format=15
+config=4109
 optional=1
 
-# PERF_TYPE_RAW / topdown-br-mispredict (0x8500)
+# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/
 [event17:base-stat]
 fd=17
-group_fd=11
 type=4
-config=34048
-disabled=0
-enable_on_exec=0
-read_format=15
+config=17039629
 optional=1
 
-# PERF_TYPE_RAW / topdown-fetch-lat (0x8600)
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD
 [event18:base-stat]
 fd=18
-group_fd=11
 type=4
-config=34304
-disabled=0
-enable_on_exec=0
-read_format=15
+config=60
 optional=1
 
-# PERF_TYPE_RAW / topdown-mem-bound (0x8700)
+# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY
 [event19:base-stat]
 fd=19
-group_fd=11
 type=4
-config=34560
-disabled=0
-enable_on_exec=0
-read_format=15
+config=2097421
+optional=1
+
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK
+[event20:base-stat]
+fd=20
+type=4
+config=316
+optional=1
+
+# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE
+[event21:base-stat]
+fd=21
+type=4
+config=412
+optional=1
+
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE
+[event22:base-stat]
+fd=22
+type=4
+config=572
+optional=1
+
+# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS
+[event23:base-stat]
+fd=23
+type=4
+config=706
+optional=1
+
+# PERF_TYPE_RAW / UOPS_ISSUED.ANY
+[event24:base-stat]
+fd=24
+type=4
+config=270
 optional=1
 
 # PERF_TYPE_HW_CACHE /
 #  PERF_COUNT_HW_CACHE_L1D                <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)
-[event20:base-stat]
-fd=20
+[event25:base-stat]
+fd=25
 type=3
 config=0
 optional=1
@@ -181,8 +200,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_L1D                <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)
-[event21:base-stat]
-fd=21
+[event26:base-stat]
+fd=26
 type=3
 config=65536
 optional=1
@@ -191,8 +210,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_LL                 <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)
-[event22:base-stat]
-fd=22
+[event27:base-stat]
+fd=27
 type=3
 config=2
 optional=1
@@ -201,8 +220,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_LL                 <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)
-[event23:base-stat]
-fd=23
+[event28:base-stat]
+fd=28
 type=3
 config=65538
 optional=1
index 97625090a1c4c299b3ee528b4c084b862c3cfab0..7e961d24a885a7178b7e08785bec3ab7dac95a41 100644 (file)
@@ -90,89 +90,108 @@ enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
+# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
 [event13:base-stat]
 fd=13
 group_fd=11
 type=4
-config=33024
+config=33280
 disabled=0
 enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
+# PERF_TYPE_RAW / topdown-be-bound (0x8300)
 [event14:base-stat]
 fd=14
 group_fd=11
 type=4
-config=33280
+config=33536
 disabled=0
 enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-be-bound (0x8300)
+# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
 [event15:base-stat]
 fd=15
 group_fd=11
 type=4
-config=33536
+config=33024
 disabled=0
 enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-heavy-ops (0x8400)
+# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING
 [event16:base-stat]
 fd=16
-group_fd=11
 type=4
-config=33792
-disabled=0
-enable_on_exec=0
-read_format=15
+config=4109
 optional=1
 
-# PERF_TYPE_RAW / topdown-br-mispredict (0x8500)
+# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/
 [event17:base-stat]
 fd=17
-group_fd=11
 type=4
-config=34048
-disabled=0
-enable_on_exec=0
-read_format=15
+config=17039629
 optional=1
 
-# PERF_TYPE_RAW / topdown-fetch-lat (0x8600)
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD
 [event18:base-stat]
 fd=18
-group_fd=11
 type=4
-config=34304
-disabled=0
-enable_on_exec=0
-read_format=15
+config=60
 optional=1
 
-# PERF_TYPE_RAW / topdown-mem-bound (0x8700)
+# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY
 [event19:base-stat]
 fd=19
-group_fd=11
 type=4
-config=34560
-disabled=0
-enable_on_exec=0
-read_format=15
+config=2097421
+optional=1
+
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK
+[event20:base-stat]
+fd=20
+type=4
+config=316
+optional=1
+
+# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE
+[event21:base-stat]
+fd=21
+type=4
+config=412
+optional=1
+
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE
+[event22:base-stat]
+fd=22
+type=4
+config=572
+optional=1
+
+# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS
+[event23:base-stat]
+fd=23
+type=4
+config=706
+optional=1
+
+# PERF_TYPE_RAW / UOPS_ISSUED.ANY
+[event24:base-stat]
+fd=24
+type=4
+config=270
 optional=1
 
 # PERF_TYPE_HW_CACHE /
 #  PERF_COUNT_HW_CACHE_L1D                <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)
-[event20:base-stat]
-fd=20
+[event25:base-stat]
+fd=25
 type=3
 config=0
 optional=1
@@ -181,8 +200,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_L1D                <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)
-[event21:base-stat]
-fd=21
+[event26:base-stat]
+fd=26
 type=3
 config=65536
 optional=1
@@ -191,8 +210,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_LL                 <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)
-[event22:base-stat]
-fd=22
+[event27:base-stat]
+fd=27
 type=3
 config=2
 optional=1
@@ -201,8 +220,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_LL                 <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)
-[event23:base-stat]
-fd=23
+[event28:base-stat]
+fd=28
 type=3
 config=65538
 optional=1
@@ -211,8 +230,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_L1I                <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)
-[event24:base-stat]
-fd=24
+[event29:base-stat]
+fd=29
 type=3
 config=1
 optional=1
@@ -221,8 +240,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_L1I                <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)
-[event25:base-stat]
-fd=25
+[event30:base-stat]
+fd=30
 type=3
 config=65537
 optional=1
@@ -231,8 +250,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_DTLB               <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)
-[event26:base-stat]
-fd=26
+[event31:base-stat]
+fd=31
 type=3
 config=3
 optional=1
@@ -241,8 +260,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_DTLB               <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)
-[event27:base-stat]
-fd=27
+[event32:base-stat]
+fd=32
 type=3
 config=65539
 optional=1
@@ -251,8 +270,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_ITLB               <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)
-[event28:base-stat]
-fd=28
+[event33:base-stat]
+fd=33
 type=3
 config=4
 optional=1
@@ -261,8 +280,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_ITLB               <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)
-[event29:base-stat]
-fd=29
+[event34:base-stat]
+fd=34
 type=3
 config=65540
 optional=1
index d555042e3fbfe6f978a074d073f35adbce333c6b..e50535f45977c6774897699b47b3d86bb8d62b14 100644 (file)
@@ -90,89 +90,108 @@ enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
+# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
 [event13:base-stat]
 fd=13
 group_fd=11
 type=4
-config=33024
+config=33280
 disabled=0
 enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
+# PERF_TYPE_RAW / topdown-be-bound (0x8300)
 [event14:base-stat]
 fd=14
 group_fd=11
 type=4
-config=33280
+config=33536
 disabled=0
 enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-be-bound (0x8300)
+# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
 [event15:base-stat]
 fd=15
 group_fd=11
 type=4
-config=33536
+config=33024
 disabled=0
 enable_on_exec=0
 read_format=15
 optional=1
 
-# PERF_TYPE_RAW / topdown-heavy-ops (0x8400)
+# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING
 [event16:base-stat]
 fd=16
-group_fd=11
 type=4
-config=33792
-disabled=0
-enable_on_exec=0
-read_format=15
+config=4109
 optional=1
 
-# PERF_TYPE_RAW / topdown-br-mispredict (0x8500)
+# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/
 [event17:base-stat]
 fd=17
-group_fd=11
 type=4
-config=34048
-disabled=0
-enable_on_exec=0
-read_format=15
+config=17039629
 optional=1
 
-# PERF_TYPE_RAW / topdown-fetch-lat (0x8600)
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD
 [event18:base-stat]
 fd=18
-group_fd=11
 type=4
-config=34304
-disabled=0
-enable_on_exec=0
-read_format=15
+config=60
 optional=1
 
-# PERF_TYPE_RAW / topdown-mem-bound (0x8700)
+# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY
 [event19:base-stat]
 fd=19
-group_fd=11
 type=4
-config=34560
-disabled=0
-enable_on_exec=0
-read_format=15
+config=2097421
+optional=1
+
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK
+[event20:base-stat]
+fd=20
+type=4
+config=316
+optional=1
+
+# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE
+[event21:base-stat]
+fd=21
+type=4
+config=412
+optional=1
+
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE
+[event22:base-stat]
+fd=22
+type=4
+config=572
+optional=1
+
+# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS
+[event23:base-stat]
+fd=23
+type=4
+config=706
+optional=1
+
+# PERF_TYPE_RAW / UOPS_ISSUED.ANY
+[event24:base-stat]
+fd=24
+type=4
+config=270
 optional=1
 
 # PERF_TYPE_HW_CACHE /
 #  PERF_COUNT_HW_CACHE_L1D                <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)
-[event20:base-stat]
-fd=20
+[event25:base-stat]
+fd=25
 type=3
 config=0
 optional=1
@@ -181,8 +200,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_L1D                <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)
-[event21:base-stat]
-fd=21
+[event26:base-stat]
+fd=26
 type=3
 config=65536
 optional=1
@@ -191,8 +210,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_LL                 <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)
-[event22:base-stat]
-fd=22
+[event27:base-stat]
+fd=27
 type=3
 config=2
 optional=1
@@ -201,8 +220,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_LL                 <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)
-[event23:base-stat]
-fd=23
+[event28:base-stat]
+fd=28
 type=3
 config=65538
 optional=1
@@ -211,8 +230,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_L1I                <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)
-[event24:base-stat]
-fd=24
+[event29:base-stat]
+fd=29
 type=3
 config=1
 optional=1
@@ -221,8 +240,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_L1I                <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)
-[event25:base-stat]
-fd=25
+[event30:base-stat]
+fd=30
 type=3
 config=65537
 optional=1
@@ -231,8 +250,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_DTLB               <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)
-[event26:base-stat]
-fd=26
+[event31:base-stat]
+fd=31
 type=3
 config=3
 optional=1
@@ -241,8 +260,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_DTLB               <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)
-[event27:base-stat]
-fd=27
+[event32:base-stat]
+fd=32
 type=3
 config=65539
 optional=1
@@ -251,8 +270,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_ITLB               <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)
-[event28:base-stat]
-fd=28
+[event33:base-stat]
+fd=33
 type=3
 config=4
 optional=1
@@ -261,8 +280,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_ITLB               <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)
-[event29:base-stat]
-fd=29
+[event34:base-stat]
+fd=34
 type=3
 config=65540
 optional=1
@@ -271,8 +290,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_L1D                <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_PREFETCH        <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)
-[event30:base-stat]
-fd=30
+[event35:base-stat]
+fd=35
 type=3
 config=512
 optional=1
@@ -281,8 +300,8 @@ optional=1
 #  PERF_COUNT_HW_CACHE_L1D                <<  0  |
 # (PERF_COUNT_HW_CACHE_OP_PREFETCH        <<  8) |
 # (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)
-[event31:base-stat]
-fd=31
+[event36:base-stat]
+fd=36
 type=3
 config=66048
 optional=1
index cbf0e0c749066559ce55da17b4e0bb31d8417c2b..733ead151c636a39ac5e58fc01eb09e53736e6c6 100644 (file)
@@ -120,7 +120,8 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u
 
        p = "FOO/0";
        ret = expr__parse(&val, ctx, p);
-       TEST_ASSERT_VAL("division by zero", ret == -1);
+       TEST_ASSERT_VAL("division by zero", ret == 0);
+       TEST_ASSERT_VAL("division by zero", isnan(val));
 
        p = "BAR/";
        ret = expr__parse(&val, ctx, p);
index 1185b79e6274886e2444bdddd1506f3c5ad5ab9c..c05148ea400cbc5b7525c9746798c23ab3748553 100644 (file)
@@ -38,6 +38,7 @@ static void load_runtime_stat(struct evlist *evlist, struct value *vals)
        evlist__alloc_aggr_stats(evlist, 1);
        evlist__for_each_entry(evlist, evsel) {
                count = find_value(evsel->name, vals);
+               evsel->supported = true;
                evsel->stats->aggr->counts.val = count;
                if (evsel__name_is(evsel, "duration_time"))
                        update_stats(&walltime_nsecs_stats, count);
index 2c1d3f70499510bf47225f7c205e92124636a4cc..b154fbb15d544c0419553f072fc7398b672eacf7 100755 (executable)
@@ -28,6 +28,18 @@ test_stat_record_report() {
   echo "stat record and report test [Success]"
 }
 
+test_stat_record_script() {
+  echo "stat record and script test"
+  if ! perf stat record -o - true | perf script -i - 2>&1 | \
+    grep -E -q "CPU[[:space:]]+THREAD[[:space:]]+VAL[[:space:]]+ENA[[:space:]]+RUN[[:space:]]+TIME[[:space:]]+EVENT"
+  then
+    echo "stat record and script test [Failed]"
+    err=1
+    return
+  fi
+  echo "stat record and script test [Success]"
+}
+
 test_stat_repeat_weak_groups() {
   echo "stat repeat weak groups test"
   if ! perf stat -e '{cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles}' \
@@ -93,6 +105,7 @@ test_topdown_weak_groups() {
 
 test_default_stat
 test_stat_record_report
+test_stat_record_script
 test_stat_repeat_weak_groups
 test_topdown_groups
 test_topdown_weak_groups
index 4ddb17cb83c5f406a80bfa321a042978d483de95..3a8b9bffa022553cd96aaf39d6e3da05c88990b9 100755 (executable)
@@ -506,6 +506,13 @@ test_sample()
                echo "perf record failed with --aux-sample"
                return 1
        fi
+       # Check with event with PMU name
+       if perf_record_no_decode -o "${perfdatafile}" -e br_misp_retired.all_branches:u uname ; then
+               if ! perf_record_no_decode -o "${perfdatafile}" -e '{intel_pt//,br_misp_retired.all_branches/aux-sample-size=8192/}:u' uname ; then
+                       echo "perf record failed with --aux-sample-size"
+                       return 1
+               fi
+       fi
        echo OK
        return 0
 }
index 90cea88119268f84e179e208180f11565900595a..499539d1c479400d643e4f31ceb9a53a0c3687d6 100755 (executable)
@@ -56,7 +56,7 @@ if [ $? -ne 0 ]; then
        exit 1
 fi
 
-if ! perf inject -i $PERF_DATA -o $PERF_INJ_DATA -j; then
+if ! DEBUGINFOD_URLS='' perf inject -i $PERF_DATA -o $PERF_INJ_DATA -j; then
        echo "Fail to inject samples"
        exit 1
 fi
index fe022ca67e6095338af9a84f391d4dfa3322734b..a211348d320444c3a4e22c5a1667c96e04e1c741 100644 (file)
 
 static DEFINE_STRARRAY_OFFSET(x86_arch_prctl_codes_1, "ARCH_", x86_arch_prctl_codes_1_offset);
 static DEFINE_STRARRAY_OFFSET(x86_arch_prctl_codes_2, "ARCH_", x86_arch_prctl_codes_2_offset);
+static DEFINE_STRARRAY_OFFSET(x86_arch_prctl_codes_3, "ARCH_", x86_arch_prctl_codes_3_offset);
 
 static struct strarray *x86_arch_prctl_codes[] = {
        &strarray__x86_arch_prctl_codes_1,
        &strarray__x86_arch_prctl_codes_2,
+       &strarray__x86_arch_prctl_codes_3,
 };
 
 static DEFINE_STRARRAYS(x86_arch_prctl_codes);
index 57fa6aaffe700c8ba7bfe347a360a09e1ebe33f5..fd5c740512c527dd7719b908a09120f1c21bb60d 100755 (executable)
@@ -24,3 +24,4 @@ print_range () {
 
 print_range 1 0x1 0x1001
 print_range 2 0x2 0x2001
+print_range 3 0x4 0x4001
index bd18fe5f27195449c1eca64c1bc4ae172af6e6cd..f9df1df1eec03c3ccce267db49942066cbc9692f 100644 (file)
@@ -214,7 +214,7 @@ perf-$(CONFIG_ZSTD) += zstd.o
 
 perf-$(CONFIG_LIBCAP) += cap.o
 
-perf-y += demangle-cxx.o
+perf-$(CONFIG_CXX_DEMANGLE) += demangle-cxx.o
 perf-y += demangle-ocaml.o
 perf-y += demangle-java.o
 perf-y += demangle-rust.o
index 8d3cfbb3cc65bdab777235861dbf7321f8f78993..1d48226ae75d446162cd62b6a8ec70ff03f1bde7 100644 (file)
@@ -416,6 +416,8 @@ int contention_end(u64 *ctx)
        return 0;
 }
 
+struct rq {};
+
 extern struct rq runqueues __ksym;
 
 struct rq___old {
index cffe493af1ed5f3110ad0481c820f5e90688f267..fb94f5280626635007430f9952ad0dcbdd502cc8 100644 (file)
@@ -25,7 +25,7 @@ struct perf_sample_data___new {
 } __attribute__((preserve_access_index));
 
 /* new kernel perf_mem_data_src definition */
-union perf_mem_data_src__new {
+union perf_mem_data_src___new {
        __u64 val;
        struct {
                __u64   mem_op:5,       /* type of opcode */
@@ -108,7 +108,7 @@ static inline __u64 perf_get_sample(struct bpf_perf_event_data_kern *kctx,
                if (entry->part == 7)
                        return kctx->data->data_src.mem_blk;
                if (entry->part == 8) {
-                       union perf_mem_data_src__new *data = (void *)&kctx->data->data_src;
+                       union perf_mem_data_src___new *data = (void *)&kctx->data->data_src;
 
                        if (bpf_core_field_exists(data->mem_hops))
                                return data->mem_hops;
index 449b1ea91fc481430b1a6eba2d073b4407aa2bcf..c7ed51b0c1ef9db341336ea637e77110c3eb7fd9 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __VMLINUX_H
 #define __VMLINUX_H
 
+#include <linux/stddef.h> // for define __always_inline
 #include <linux/bpf.h>
 #include <linux/types.h>
 #include <linux/perf_event.h>
index 70cac0375b340b1b6e226d6c0be97e36cf4a146d..ecca40787ac9ad844ad57c3229554273f015043e 100644 (file)
@@ -227,6 +227,19 @@ struct cs_etm_packet_queue {
 #define INFO_HEADER_SIZE (sizeof(((struct perf_record_auxtrace_info *)0)->type) + \
                          sizeof(((struct perf_record_auxtrace_info *)0)->reserved__))
 
+/* CoreSight trace ID is currently the bottom 7 bits of the value */
+#define CORESIGHT_TRACE_ID_VAL_MASK    GENMASK(6, 0)
+
+/*
+ * perf record will set the legacy meta data values as unused initially.
+ * This allows perf report to manage the decoders created when dynamic
+ * allocation in operation.
+ */
+#define CORESIGHT_TRACE_ID_UNUSED_FLAG BIT(31)
+
+/* Value to set for unused trace ID values */
+#define CORESIGHT_TRACE_ID_UNUSED_VAL  0x7F
+
 int cs_etm__process_auxtrace_info(union perf_event *event,
                                  struct perf_session *session);
 struct perf_event_attr *cs_etm_get_default_config(struct perf_pmu *pmu);
index 356c07f03be6bfce64fd6208611b720f1a3639c2..c2dbb5647e754998fb9090e3075ebaf2db9f65f9 100644 (file)
@@ -282,6 +282,7 @@ void evsel__init(struct evsel *evsel,
        evsel->bpf_fd      = -1;
        INIT_LIST_HEAD(&evsel->config_terms);
        INIT_LIST_HEAD(&evsel->bpf_counter_list);
+       INIT_LIST_HEAD(&evsel->bpf_filters);
        perf_evsel__object.init(evsel);
        evsel->sample_size = __evsel__sample_size(attr->sample_type);
        evsel__calc_id_pos(evsel);
@@ -290,6 +291,7 @@ void evsel__init(struct evsel *evsel,
        evsel->per_pkg_mask  = NULL;
        evsel->collect_stat  = false;
        evsel->pmu_name      = NULL;
+       evsel->skippable     = false;
 }
 
 struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx)
@@ -828,26 +830,26 @@ bool evsel__name_is(struct evsel *evsel, const char *name)
 
 const char *evsel__group_pmu_name(const struct evsel *evsel)
 {
-       const struct evsel *leader;
+       struct evsel *leader = evsel__leader(evsel);
+       struct evsel *pos;
 
-       /* If the pmu_name is set use it. pmu_name isn't set for CPU and software events. */
-       if (evsel->pmu_name)
-               return evsel->pmu_name;
        /*
         * Software events may be in a group with other uncore PMU events. Use
-        * the pmu_name of the group leader to avoid breaking the software event
-        * out of the group.
+        * the pmu_name of the first non-software event to avoid breaking the
+        * software event out of the group.
         *
         * Aux event leaders, like intel_pt, expect a group with events from
         * other PMUs, so substitute the AUX event's PMU in this case.
         */
-       leader  = evsel__leader(evsel);
-       if ((evsel->core.attr.type == PERF_TYPE_SOFTWARE || evsel__is_aux_event(leader)) &&
-           leader->pmu_name) {
-               return leader->pmu_name;
+       if (evsel->core.attr.type == PERF_TYPE_SOFTWARE || evsel__is_aux_event(leader)) {
+               /* Starting with the leader, find the first event with a named PMU. */
+               for_each_group_evsel(pos, leader) {
+                       if (pos->pmu_name)
+                               return pos->pmu_name;
+               }
        }
 
-       return "cpu";
+       return evsel->pmu_name ?: "cpu";
 }
 
 const char *evsel__metric_id(const struct evsel *evsel)
@@ -1725,9 +1727,13 @@ static int get_group_fd(struct evsel *evsel, int cpu_map_idx, int thread)
                return -1;
 
        fd = FD(leader, cpu_map_idx, thread);
-       BUG_ON(fd == -1);
+       BUG_ON(fd == -1 && !leader->skippable);
 
-       return fd;
+       /*
+        * When the leader has been skipped, return -2 to distinguish from no
+        * group leader case.
+        */
+       return fd == -1 ? -2 : fd;
 }
 
 static void evsel__remove_fd(struct evsel *pos, int nr_cpus, int nr_threads, int thread_idx)
@@ -2109,6 +2115,12 @@ retry_open:
 
                        group_fd = get_group_fd(evsel, idx, thread);
 
+                       if (group_fd == -2) {
+                               pr_debug("broken group leader for %s\n", evsel->name);
+                               err = -EINVAL;
+                               goto out_close;
+                       }
+
                        test_attr__ready();
 
                        /* Debug message used by test scripts */
index d575390d80bc3198900bd28221de8c97c0346348..0f54f28a69c25a191845fe5839452f04e2a12cd7 100644 (file)
@@ -95,6 +95,7 @@ struct evsel {
                bool                    weak_group;
                bool                    bpf_counter;
                bool                    use_config_name;
+               bool                    skippable;
                int                     bpf_fd;
                struct bpf_object       *bpf_obj;
                struct list_head        config_terms;
@@ -150,10 +151,8 @@ struct evsel {
         */
        struct bpf_counter_ops  *bpf_counter_ops;
 
-       union {
-               struct list_head        bpf_counter_list; /* for perf-stat -b */
-               struct list_head        bpf_filters; /* for perf-record --filter */
-       };
+       struct list_head        bpf_counter_list; /* for perf-stat -b */
+       struct list_head        bpf_filters; /* for perf-record --filter */
 
        /* for perf-stat --use-bpf */
        int                     bperf_leader_prog_fd;
index 250e444bf0325f2d18e58e98176bde0181c3e48c..4ce931cccb633a3f9478bbd2275d3c7735fb2417 100644 (file)
@@ -225,7 +225,11 @@ expr: NUMBER
 {
        if (fpclassify($3.val) == FP_ZERO) {
                pr_debug("division by zero\n");
-               YYABORT;
+               assert($3.ids == NULL);
+               if (compute_ids)
+                       ids__free($1.ids);
+               $$.val = NAN;
+               $$.ids = NULL;
        } else if (!compute_ids || (is_const($1.val) && is_const($3.val))) {
                assert($1.ids == NULL);
                assert($3.ids == NULL);
index c566c6859302697b10314677c182a6cfbb9fd90c..5e9c657dd3f7a548447fbecfee77ea1d8207642f 100644 (file)
@@ -1144,12 +1144,12 @@ static int metricgroup__add_metric_callback(const struct pmu_metric *pm,
        struct metricgroup__add_metric_data *data = vdata;
        int ret = 0;
 
-       if (pm->metric_expr &&
-               (match_metric(pm->metric_group, data->metric_name) ||
-                match_metric(pm->metric_name, data->metric_name))) {
+       if (pm->metric_expr && match_pm_metric(pm, data->metric_name)) {
+               bool metric_no_group = data->metric_no_group ||
+                       match_metric(data->metric_name, pm->metricgroup_no_group);
 
                data->has_match = true;
-               ret = add_metric(data->list, pm, data->modifier, data->metric_no_group,
+               ret = add_metric(data->list, pm, data->modifier, metric_no_group,
                                 data->metric_no_threshold, data->user_requested_cpu_list,
                                 data->system_wide, /*root_metric=*/NULL,
                                 /*visited_metrics=*/NULL, table);
@@ -1672,7 +1672,7 @@ static int metricgroup__topdown_max_level_callback(const struct pmu_metric *pm,
 {
        unsigned int *max_level = data;
        unsigned int level;
-       const char *p = strstr(pm->metric_group, "TopdownL");
+       const char *p = strstr(pm->metric_group ?: "", "TopdownL");
 
        if (!p || p[8] == '\0')
                return 0;
index d71019dcd61420200e501a2fb19a65b7d055e53a..34ba840ae19a2971e9c34c78be6bdc0b5d2c1a24 100644 (file)
@@ -2140,25 +2140,32 @@ static int evlist__cmp(void *state, const struct list_head *l, const struct list
        int *leader_idx = state;
        int lhs_leader_idx = *leader_idx, rhs_leader_idx = *leader_idx, ret;
        const char *lhs_pmu_name, *rhs_pmu_name;
+       bool lhs_has_group = false, rhs_has_group = false;
 
        /*
         * First sort by grouping/leader. Read the leader idx only if the evsel
         * is part of a group, as -1 indicates no group.
         */
-       if (lhs_core->leader != lhs_core || lhs_core->nr_members > 1)
+       if (lhs_core->leader != lhs_core || lhs_core->nr_members > 1) {
+               lhs_has_group = true;
                lhs_leader_idx = lhs_core->leader->idx;
-       if (rhs_core->leader != rhs_core || rhs_core->nr_members > 1)
+       }
+       if (rhs_core->leader != rhs_core || rhs_core->nr_members > 1) {
+               rhs_has_group = true;
                rhs_leader_idx = rhs_core->leader->idx;
+       }
 
        if (lhs_leader_idx != rhs_leader_idx)
                return lhs_leader_idx - rhs_leader_idx;
 
-       /* Group by PMU. Groups can't span PMUs. */
-       lhs_pmu_name = evsel__group_pmu_name(lhs);
-       rhs_pmu_name = evsel__group_pmu_name(rhs);
-       ret = strcmp(lhs_pmu_name, rhs_pmu_name);
-       if (ret)
-               return ret;
+       /* Group by PMU if there is a group. Groups can't span PMUs. */
+       if (lhs_has_group && rhs_has_group) {
+               lhs_pmu_name = evsel__group_pmu_name(lhs);
+               rhs_pmu_name = evsel__group_pmu_name(rhs);
+               ret = strcmp(lhs_pmu_name, rhs_pmu_name);
+               if (ret)
+                       return ret;
+       }
 
        /* Architecture specific sorting. */
        return arch_evlist__cmp(lhs, rhs);
index 73b2ff2ddf2981be9b4c97f91957ebac8d040c8e..bf5a6c14dfcdb100afca945b417e8e00bd43e7cc 100644 (file)
@@ -431,7 +431,7 @@ static void print_metric_json(struct perf_stat_config *config __maybe_unused,
        struct outstate *os = ctx;
        FILE *out = os->fh;
 
-       fprintf(out, "\"metric-value\" : %f, ", val);
+       fprintf(out, "\"metric-value\" : \"%f\", ", val);
        fprintf(out, "\"metric-unit\" : \"%s\"", unit);
        if (!config->metric_only)
                fprintf(out, "}");
index eeccab6751d7c40e330232ace919a88e81a316e7..1566a206ba42cd044aefd57b2dcfe0d32043d69e 100644 (file)
@@ -403,12 +403,25 @@ static int prepare_metric(struct evsel **metric_events,
                        if (!aggr)
                                break;
 
-                       /*
-                        * If an event was scaled during stat gathering, reverse
-                        * the scale before computing the metric.
-                        */
-                       val = aggr->counts.val * (1.0 / metric_events[i]->scale);
-                       source_count = evsel__source_count(metric_events[i]);
+                        if (!metric_events[i]->supported) {
+                               /*
+                                * Not supported events will have a count of 0,
+                                * which can be confusing in a
+                                * metric. Explicitly set the value to NAN. Not
+                                * counted events (enable time of 0) are read as
+                                * 0.
+                                */
+                               val = NAN;
+                               source_count = 0;
+                       } else {
+                               /*
+                                * If an event was scaled during stat gathering,
+                                * reverse the scale before computing the
+                                * metric.
+                                */
+                               val = aggr->counts.val * (1.0 / metric_events[i]->scale);
+                               source_count = evsel__source_count(metric_events[i]);
+                       }
                }
                n = strdup(evsel__metric_id(metric_events[i]));
                if (!n)
index b2ed9cc5226551e64a01bb59d7df4671f24388b7..63882a4db5c7445e3c2390932622338083c66d14 100644 (file)
 #include <bfd.h>
 #endif
 
+#if defined(HAVE_LIBBFD_SUPPORT) || defined(HAVE_CPLUS_DEMANGLE_SUPPORT)
+#ifndef DMGL_PARAMS
+#define DMGL_PARAMS     (1 << 0)  /* Include function args */
+#define DMGL_ANSI       (1 << 1)  /* Include const, volatile, etc */
+#endif
+#endif
+
 #ifndef EM_AARCH64
 #define EM_AARCH64     183  /* ARM 64 bit */
 #endif
@@ -271,6 +278,26 @@ static bool want_demangle(bool is_kernel_sym)
        return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
 }
 
+/*
+ * Demangle C++ function signature, typically replaced by demangle-cxx.cpp
+ * version.
+ */
+__weak char *cxx_demangle_sym(const char *str __maybe_unused, bool params __maybe_unused,
+                             bool modifiers __maybe_unused)
+{
+#ifdef HAVE_LIBBFD_SUPPORT
+       int flags = (params ? DMGL_PARAMS : 0) | (modifiers ? DMGL_ANSI : 0);
+
+       return bfd_demangle(NULL, str, flags);
+#elif defined(HAVE_CPLUS_DEMANGLE_SUPPORT)
+       int flags = (params ? DMGL_PARAMS : 0) | (modifiers ? DMGL_ANSI : 0);
+
+       return cplus_demangle(str, flags);
+#else
+       return NULL;
+#endif
+}
+
 static char *demangle_sym(struct dso *dso, int kmodule, const char *elf_name)
 {
        char *demangled = NULL;
index 0ce29ee4c2e4634592bb3ec993ab26988ca80d8c..a7a59c6bacda81644d72c3023ad824365bfb33f5 100644 (file)
@@ -40,25 +40,34 @@ static int sysfs_get_enabled(char *path, int *mode)
 {
        int fd;
        char yes_no;
+       int ret = 0;
 
        *mode = 0;
 
        fd = open(path, O_RDONLY);
-       if (fd == -1)
-               return -1;
+       if (fd == -1) {
+               ret = -1;
+               goto out;
+       }
 
        if (read(fd, &yes_no, 1) != 1) {
-               close(fd);
-               return -1;
+               ret = -1;
+               goto out_close;
        }
 
        if (yes_no == '1') {
                *mode = 1;
-               return 0;
+               goto out_close;
        } else if (yes_no == '0') {
-               return 0;
+               goto out_close;
+       } else {
+               ret = -1;
+               goto out_close;
        }
-       return -1;
+out_close:
+       close(fd);
+out:
+       return ret;
 }
 
 int powercap_get_enabled(int *mode)
index e7d48cb563c0efbec1e75c4e6b018190a3d4e34a..ae6af354a81db518dc779a20094f406ef4e948db 100644 (file)
@@ -70,8 +70,8 @@ static int max_freq_mode;
  */
 static unsigned long max_frequency;
 
-static unsigned long long tsc_at_measure_start;
-static unsigned long long tsc_at_measure_end;
+static unsigned long long *tsc_at_measure_start;
+static unsigned long long *tsc_at_measure_end;
 static unsigned long long *mperf_previous_count;
 static unsigned long long *aperf_previous_count;
 static unsigned long long *mperf_current_count;
@@ -169,7 +169,7 @@ static int mperf_get_count_percent(unsigned int id, double *percent,
        aperf_diff = aperf_current_count[cpu] - aperf_previous_count[cpu];
 
        if (max_freq_mode == MAX_FREQ_TSC_REF) {
-               tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
+               tsc_diff = tsc_at_measure_end[cpu] - tsc_at_measure_start[cpu];
                *percent = 100.0 * mperf_diff / tsc_diff;
                dprint("%s: TSC Ref - mperf_diff: %llu, tsc_diff: %llu\n",
                       mperf_cstates[id].name, mperf_diff, tsc_diff);
@@ -206,7 +206,7 @@ static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
 
        if (max_freq_mode == MAX_FREQ_TSC_REF) {
                /* Calculate max_freq from TSC count */
-               tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
+               tsc_diff = tsc_at_measure_end[cpu] - tsc_at_measure_start[cpu];
                time_diff = timespec_diff_us(time_start, time_end);
                max_frequency = tsc_diff / time_diff;
        }
@@ -225,33 +225,27 @@ static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
 static int mperf_start(void)
 {
        int cpu;
-       unsigned long long dbg;
 
        clock_gettime(CLOCK_REALTIME, &time_start);
-       mperf_get_tsc(&tsc_at_measure_start);
 
-       for (cpu = 0; cpu < cpu_count; cpu++)
+       for (cpu = 0; cpu < cpu_count; cpu++) {
+               mperf_get_tsc(&tsc_at_measure_start[cpu]);
                mperf_init_stats(cpu);
+       }
 
-       mperf_get_tsc(&dbg);
-       dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start);
        return 0;
 }
 
 static int mperf_stop(void)
 {
-       unsigned long long dbg;
        int cpu;
 
-       for (cpu = 0; cpu < cpu_count; cpu++)
+       for (cpu = 0; cpu < cpu_count; cpu++) {
                mperf_measure_stats(cpu);
+               mperf_get_tsc(&tsc_at_measure_end[cpu]);
+       }
 
-       mperf_get_tsc(&tsc_at_measure_end);
        clock_gettime(CLOCK_REALTIME, &time_end);
-
-       mperf_get_tsc(&dbg);
-       dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end);
-
        return 0;
 }
 
@@ -353,7 +347,8 @@ struct cpuidle_monitor *mperf_register(void)
        aperf_previous_count = calloc(cpu_count, sizeof(unsigned long long));
        mperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
        aperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
-
+       tsc_at_measure_start = calloc(cpu_count, sizeof(unsigned long long));
+       tsc_at_measure_end = calloc(cpu_count, sizeof(unsigned long long));
        mperf_monitor.name_len = strlen(mperf_monitor.name);
        return &mperf_monitor;
 }
@@ -364,6 +359,8 @@ void mperf_unregister(void)
        free(aperf_previous_count);
        free(mperf_current_count);
        free(aperf_current_count);
+       free(tsc_at_measure_start);
+       free(tsc_at_measure_end);
        free(is_valid);
 }
 
index fba7bec96acd184297189798d1708ef1e6e2df7e..6f9347ade82cde19fac94be0bea8736192f2ec3b 100644 (file)
@@ -6,6 +6,7 @@ ldflags-y += --wrap=acpi_pci_find_root
 ldflags-y += --wrap=nvdimm_bus_register
 ldflags-y += --wrap=devm_cxl_port_enumerate_dports
 ldflags-y += --wrap=devm_cxl_setup_hdm
+ldflags-y += --wrap=devm_cxl_enable_hdm
 ldflags-y += --wrap=devm_cxl_add_passthrough_decoder
 ldflags-y += --wrap=devm_cxl_enumerate_decoders
 ldflags-y += --wrap=cxl_await_media_ready
index ba572d03c6875b28fb1638237f98a3384d149c5c..34b48027b3defae85003edbb24a697113fcf322f 100644 (file)
@@ -1256,6 +1256,7 @@ static int cxl_mock_mem_probe(struct platform_device *pdev)
        if (rc)
                return rc;
 
+       cxlds->media_ready = true;
        rc = cxl_dev_state_identify(cxlds);
        if (rc)
                return rc;
index c4e53f22e42159735cb14254f2cb464d86b9f085..28441652764405d0e2fae9add9c4f7372c15facc 100644 (file)
@@ -19,7 +19,7 @@ void register_cxl_mock_ops(struct cxl_mock_ops *ops)
 }
 EXPORT_SYMBOL_GPL(register_cxl_mock_ops);
 
-static DEFINE_SRCU(cxl_mock_srcu);
+DEFINE_STATIC_SRCU(cxl_mock_srcu);
 
 void unregister_cxl_mock_ops(struct cxl_mock_ops *ops)
 {
@@ -149,6 +149,21 @@ struct cxl_hdm *__wrap_devm_cxl_setup_hdm(struct cxl_port *port,
 }
 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_setup_hdm, CXL);
 
+int __wrap_devm_cxl_enable_hdm(struct cxl_port *port, struct cxl_hdm *cxlhdm)
+{
+       int index, rc;
+       struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
+
+       if (ops && ops->is_mock_port(port->uport))
+               rc = 0;
+       else
+               rc = devm_cxl_enable_hdm(port, cxlhdm);
+       put_cxl_mock_ops(index);
+
+       return rc;
+}
+EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_enable_hdm, CXL);
+
 int __wrap_devm_cxl_add_passthrough_decoder(struct cxl_port *port)
 {
        int rc, index;
index c49e5403ad0edc178b08d194ba9bca211814f27d..28d2c77262bed75b33baa51f06a4c413d7bf58fb 100644 (file)
@@ -197,7 +197,7 @@ $(OUTPUT)/urandom_read: urandom_read.c urandom_read_aux.c $(OUTPUT)/liburandom_r
 
 $(OUTPUT)/sign-file: ../../../../scripts/sign-file.c
        $(call msg,SIGN-FILE,,$@)
-       $(Q)$(CC) $(shell $(HOSTPKG_CONFIG)--cflags libcrypto 2> /dev/null) \
+       $(Q)$(CC) $(shell $(HOSTPKG_CONFIG) --cflags libcrypto 2> /dev/null) \
                  $< -o $@ \
                  $(shell $(HOSTPKG_CONFIG) --libs libcrypto 2> /dev/null || echo -lcrypto)
 
index 0ce25a967481e028180cd1fc33151ff6d9214a9a..064cc5e8d9ade372415b852712270e84847f80ff 100644 (file)
@@ -2,6 +2,7 @@
 // Copyright (c) 2020 Cloudflare
 #include <error.h>
 #include <netinet/tcp.h>
+#include <sys/epoll.h>
 
 #include "test_progs.h"
 #include "test_skmsg_load_helpers.skel.h"
@@ -9,8 +10,12 @@
 #include "test_sockmap_invalid_update.skel.h"
 #include "test_sockmap_skb_verdict_attach.skel.h"
 #include "test_sockmap_progs_query.skel.h"
+#include "test_sockmap_pass_prog.skel.h"
+#include "test_sockmap_drop_prog.skel.h"
 #include "bpf_iter_sockmap.skel.h"
 
+#include "sockmap_helpers.h"
+
 #define TCP_REPAIR             19      /* TCP sock is under repair right now */
 
 #define TCP_REPAIR_ON          1
@@ -350,6 +355,126 @@ out:
        test_sockmap_progs_query__destroy(skel);
 }
 
+#define MAX_EVENTS 10
+static void test_sockmap_skb_verdict_shutdown(void)
+{
+       struct epoll_event ev, events[MAX_EVENTS];
+       int n, err, map, verdict, s, c1, p1;
+       struct test_sockmap_pass_prog *skel;
+       int epollfd;
+       int zero = 0;
+       char b;
+
+       skel = test_sockmap_pass_prog__open_and_load();
+       if (!ASSERT_OK_PTR(skel, "open_and_load"))
+               return;
+
+       verdict = bpf_program__fd(skel->progs.prog_skb_verdict);
+       map = bpf_map__fd(skel->maps.sock_map_rx);
+
+       err = bpf_prog_attach(verdict, map, BPF_SK_SKB_STREAM_VERDICT, 0);
+       if (!ASSERT_OK(err, "bpf_prog_attach"))
+               goto out;
+
+       s = socket_loopback(AF_INET, SOCK_STREAM);
+       if (s < 0)
+               goto out;
+       err = create_pair(s, AF_INET, SOCK_STREAM, &c1, &p1);
+       if (err < 0)
+               goto out;
+
+       err = bpf_map_update_elem(map, &zero, &c1, BPF_NOEXIST);
+       if (err < 0)
+               goto out_close;
+
+       shutdown(p1, SHUT_WR);
+
+       ev.events = EPOLLIN;
+       ev.data.fd = c1;
+
+       epollfd = epoll_create1(0);
+       if (!ASSERT_GT(epollfd, -1, "epoll_create(0)"))
+               goto out_close;
+       err = epoll_ctl(epollfd, EPOLL_CTL_ADD, c1, &ev);
+       if (!ASSERT_OK(err, "epoll_ctl(EPOLL_CTL_ADD)"))
+               goto out_close;
+       err = epoll_wait(epollfd, events, MAX_EVENTS, -1);
+       if (!ASSERT_EQ(err, 1, "epoll_wait(fd)"))
+               goto out_close;
+
+       n = recv(c1, &b, 1, SOCK_NONBLOCK);
+       ASSERT_EQ(n, 0, "recv_timeout(fin)");
+out_close:
+       close(c1);
+       close(p1);
+out:
+       test_sockmap_pass_prog__destroy(skel);
+}
+
+static void test_sockmap_skb_verdict_fionread(bool pass_prog)
+{
+       int expected, zero = 0, sent, recvd, avail;
+       int err, map, verdict, s, c0, c1, p0, p1;
+       struct test_sockmap_pass_prog *pass;
+       struct test_sockmap_drop_prog *drop;
+       char buf[256] = "0123456789";
+
+       if (pass_prog) {
+               pass = test_sockmap_pass_prog__open_and_load();
+               if (!ASSERT_OK_PTR(pass, "open_and_load"))
+                       return;
+               verdict = bpf_program__fd(pass->progs.prog_skb_verdict);
+               map = bpf_map__fd(pass->maps.sock_map_rx);
+               expected = sizeof(buf);
+       } else {
+               drop = test_sockmap_drop_prog__open_and_load();
+               if (!ASSERT_OK_PTR(drop, "open_and_load"))
+                       return;
+               verdict = bpf_program__fd(drop->progs.prog_skb_verdict);
+               map = bpf_map__fd(drop->maps.sock_map_rx);
+               /* On drop data is consumed immediately and copied_seq inc'd */
+               expected = 0;
+       }
+
+
+       err = bpf_prog_attach(verdict, map, BPF_SK_SKB_STREAM_VERDICT, 0);
+       if (!ASSERT_OK(err, "bpf_prog_attach"))
+               goto out;
+
+       s = socket_loopback(AF_INET, SOCK_STREAM);
+       if (!ASSERT_GT(s, -1, "socket_loopback(s)"))
+               goto out;
+       err = create_socket_pairs(s, AF_INET, SOCK_STREAM, &c0, &c1, &p0, &p1);
+       if (!ASSERT_OK(err, "create_socket_pairs(s)"))
+               goto out;
+
+       err = bpf_map_update_elem(map, &zero, &c1, BPF_NOEXIST);
+       if (!ASSERT_OK(err, "bpf_map_update_elem(c1)"))
+               goto out_close;
+
+       sent = xsend(p1, &buf, sizeof(buf), 0);
+       ASSERT_EQ(sent, sizeof(buf), "xsend(p0)");
+       err = ioctl(c1, FIONREAD, &avail);
+       ASSERT_OK(err, "ioctl(FIONREAD) error");
+       ASSERT_EQ(avail, expected, "ioctl(FIONREAD)");
+       /* On DROP test there will be no data to read */
+       if (pass_prog) {
+               recvd = recv_timeout(c1, &buf, sizeof(buf), SOCK_NONBLOCK, IO_TIMEOUT_SEC);
+               ASSERT_EQ(recvd, sizeof(buf), "recv_timeout(c0)");
+       }
+
+out_close:
+       close(c0);
+       close(p0);
+       close(c1);
+       close(p1);
+out:
+       if (pass_prog)
+               test_sockmap_pass_prog__destroy(pass);
+       else
+               test_sockmap_drop_prog__destroy(drop);
+}
+
 void test_sockmap_basic(void)
 {
        if (test__start_subtest("sockmap create_update_free"))
@@ -384,4 +509,10 @@ void test_sockmap_basic(void)
                test_sockmap_progs_query(BPF_SK_SKB_STREAM_VERDICT);
        if (test__start_subtest("sockmap skb_verdict progs query"))
                test_sockmap_progs_query(BPF_SK_SKB_VERDICT);
+       if (test__start_subtest("sockmap skb_verdict shutdown"))
+               test_sockmap_skb_verdict_shutdown();
+       if (test__start_subtest("sockmap skb_verdict fionread"))
+               test_sockmap_skb_verdict_fionread(true);
+       if (test__start_subtest("sockmap skb_verdict fionread on drop"))
+               test_sockmap_skb_verdict_fionread(false);
 }
diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h b/tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h
new file mode 100644 (file)
index 0000000..d126654
--- /dev/null
@@ -0,0 +1,390 @@
+#ifndef __SOCKMAP_HELPERS__
+#define __SOCKMAP_HELPERS__
+
+#include <linux/vm_sockets.h>
+
+#define IO_TIMEOUT_SEC 30
+#define MAX_STRERR_LEN 256
+#define MAX_TEST_NAME 80
+
+/* workaround for older vm_sockets.h */
+#ifndef VMADDR_CID_LOCAL
+#define VMADDR_CID_LOCAL 1
+#endif
+
+#define __always_unused        __attribute__((__unused__))
+
+#define _FAIL(errnum, fmt...)                                                  \
+       ({                                                                     \
+               error_at_line(0, (errnum), __func__, __LINE__, fmt);           \
+               CHECK_FAIL(true);                                              \
+       })
+#define FAIL(fmt...) _FAIL(0, fmt)
+#define FAIL_ERRNO(fmt...) _FAIL(errno, fmt)
+#define FAIL_LIBBPF(err, msg)                                                  \
+       ({                                                                     \
+               char __buf[MAX_STRERR_LEN];                                    \
+               libbpf_strerror((err), __buf, sizeof(__buf));                  \
+               FAIL("%s: %s", (msg), __buf);                                  \
+       })
+
+/* Wrappers that fail the test on error and report it. */
+
+#define xaccept_nonblock(fd, addr, len)                                        \
+       ({                                                                     \
+               int __ret =                                                    \
+                       accept_timeout((fd), (addr), (len), IO_TIMEOUT_SEC);   \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("accept");                                  \
+               __ret;                                                         \
+       })
+
+#define xbind(fd, addr, len)                                                   \
+       ({                                                                     \
+               int __ret = bind((fd), (addr), (len));                         \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("bind");                                    \
+               __ret;                                                         \
+       })
+
+#define xclose(fd)                                                             \
+       ({                                                                     \
+               int __ret = close((fd));                                       \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("close");                                   \
+               __ret;                                                         \
+       })
+
+#define xconnect(fd, addr, len)                                                \
+       ({                                                                     \
+               int __ret = connect((fd), (addr), (len));                      \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("connect");                                 \
+               __ret;                                                         \
+       })
+
+#define xgetsockname(fd, addr, len)                                            \
+       ({                                                                     \
+               int __ret = getsockname((fd), (addr), (len));                  \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("getsockname");                             \
+               __ret;                                                         \
+       })
+
+#define xgetsockopt(fd, level, name, val, len)                                 \
+       ({                                                                     \
+               int __ret = getsockopt((fd), (level), (name), (val), (len));   \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("getsockopt(" #name ")");                   \
+               __ret;                                                         \
+       })
+
+#define xlisten(fd, backlog)                                                   \
+       ({                                                                     \
+               int __ret = listen((fd), (backlog));                           \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("listen");                                  \
+               __ret;                                                         \
+       })
+
+#define xsetsockopt(fd, level, name, val, len)                                 \
+       ({                                                                     \
+               int __ret = setsockopt((fd), (level), (name), (val), (len));   \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("setsockopt(" #name ")");                   \
+               __ret;                                                         \
+       })
+
+#define xsend(fd, buf, len, flags)                                             \
+       ({                                                                     \
+               ssize_t __ret = send((fd), (buf), (len), (flags));             \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("send");                                    \
+               __ret;                                                         \
+       })
+
+#define xrecv_nonblock(fd, buf, len, flags)                                    \
+       ({                                                                     \
+               ssize_t __ret = recv_timeout((fd), (buf), (len), (flags),      \
+                                            IO_TIMEOUT_SEC);                  \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("recv");                                    \
+               __ret;                                                         \
+       })
+
+#define xsocket(family, sotype, flags)                                         \
+       ({                                                                     \
+               int __ret = socket(family, sotype, flags);                     \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("socket");                                  \
+               __ret;                                                         \
+       })
+
+#define xbpf_map_delete_elem(fd, key)                                          \
+       ({                                                                     \
+               int __ret = bpf_map_delete_elem((fd), (key));                  \
+               if (__ret < 0)                                               \
+                       FAIL_ERRNO("map_delete");                              \
+               __ret;                                                         \
+       })
+
+#define xbpf_map_lookup_elem(fd, key, val)                                     \
+       ({                                                                     \
+               int __ret = bpf_map_lookup_elem((fd), (key), (val));           \
+               if (__ret < 0)                                               \
+                       FAIL_ERRNO("map_lookup");                              \
+               __ret;                                                         \
+       })
+
+#define xbpf_map_update_elem(fd, key, val, flags)                              \
+       ({                                                                     \
+               int __ret = bpf_map_update_elem((fd), (key), (val), (flags));  \
+               if (__ret < 0)                                               \
+                       FAIL_ERRNO("map_update");                              \
+               __ret;                                                         \
+       })
+
+#define xbpf_prog_attach(prog, target, type, flags)                            \
+       ({                                                                     \
+               int __ret =                                                    \
+                       bpf_prog_attach((prog), (target), (type), (flags));    \
+               if (__ret < 0)                                               \
+                       FAIL_ERRNO("prog_attach(" #type ")");                  \
+               __ret;                                                         \
+       })
+
+#define xbpf_prog_detach2(prog, target, type)                                  \
+       ({                                                                     \
+               int __ret = bpf_prog_detach2((prog), (target), (type));        \
+               if (__ret < 0)                                               \
+                       FAIL_ERRNO("prog_detach2(" #type ")");                 \
+               __ret;                                                         \
+       })
+
+#define xpthread_create(thread, attr, func, arg)                               \
+       ({                                                                     \
+               int __ret = pthread_create((thread), (attr), (func), (arg));   \
+               errno = __ret;                                                 \
+               if (__ret)                                                     \
+                       FAIL_ERRNO("pthread_create");                          \
+               __ret;                                                         \
+       })
+
+#define xpthread_join(thread, retval)                                          \
+       ({                                                                     \
+               int __ret = pthread_join((thread), (retval));                  \
+               errno = __ret;                                                 \
+               if (__ret)                                                     \
+                       FAIL_ERRNO("pthread_join");                            \
+               __ret;                                                         \
+       })
+
+static inline int poll_read(int fd, unsigned int timeout_sec)
+{
+       struct timeval timeout = { .tv_sec = timeout_sec };
+       fd_set rfds;
+       int r;
+
+       FD_ZERO(&rfds);
+       FD_SET(fd, &rfds);
+
+       r = select(fd + 1, &rfds, NULL, NULL, &timeout);
+       if (r == 0)
+               errno = ETIME;
+
+       return r == 1 ? 0 : -1;
+}
+
+static inline int accept_timeout(int fd, struct sockaddr *addr, socklen_t *len,
+                                unsigned int timeout_sec)
+{
+       if (poll_read(fd, timeout_sec))
+               return -1;
+
+       return accept(fd, addr, len);
+}
+
+static inline int recv_timeout(int fd, void *buf, size_t len, int flags,
+                              unsigned int timeout_sec)
+{
+       if (poll_read(fd, timeout_sec))
+               return -1;
+
+       return recv(fd, buf, len, flags);
+}
+
+static inline void init_addr_loopback4(struct sockaddr_storage *ss,
+                                      socklen_t *len)
+{
+       struct sockaddr_in *addr4 = memset(ss, 0, sizeof(*ss));
+
+       addr4->sin_family = AF_INET;
+       addr4->sin_port = 0;
+       addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+       *len = sizeof(*addr4);
+}
+
+static inline void init_addr_loopback6(struct sockaddr_storage *ss,
+                                      socklen_t *len)
+{
+       struct sockaddr_in6 *addr6 = memset(ss, 0, sizeof(*ss));
+
+       addr6->sin6_family = AF_INET6;
+       addr6->sin6_port = 0;
+       addr6->sin6_addr = in6addr_loopback;
+       *len = sizeof(*addr6);
+}
+
+static inline void init_addr_loopback_vsock(struct sockaddr_storage *ss,
+                                           socklen_t *len)
+{
+       struct sockaddr_vm *addr = memset(ss, 0, sizeof(*ss));
+
+       addr->svm_family = AF_VSOCK;
+       addr->svm_port = VMADDR_PORT_ANY;
+       addr->svm_cid = VMADDR_CID_LOCAL;
+       *len = sizeof(*addr);
+}
+
+static inline void init_addr_loopback(int family, struct sockaddr_storage *ss,
+                                     socklen_t *len)
+{
+       switch (family) {
+       case AF_INET:
+               init_addr_loopback4(ss, len);
+               return;
+       case AF_INET6:
+               init_addr_loopback6(ss, len);
+               return;
+       case AF_VSOCK:
+               init_addr_loopback_vsock(ss, len);
+               return;
+       default:
+               FAIL("unsupported address family %d", family);
+       }
+}
+
+static inline struct sockaddr *sockaddr(struct sockaddr_storage *ss)
+{
+       return (struct sockaddr *)ss;
+}
+
+static inline int add_to_sockmap(int sock_mapfd, int fd1, int fd2)
+{
+       u64 value;
+       u32 key;
+       int err;
+
+       key = 0;
+       value = fd1;
+       err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
+       if (err)
+               return err;
+
+       key = 1;
+       value = fd2;
+       return xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
+}
+
+static inline int create_pair(int s, int family, int sotype, int *c, int *p)
+{
+       struct sockaddr_storage addr;
+       socklen_t len;
+       int err = 0;
+
+       len = sizeof(addr);
+       err = xgetsockname(s, sockaddr(&addr), &len);
+       if (err)
+               return err;
+
+       *c = xsocket(family, sotype, 0);
+       if (*c < 0)
+               return errno;
+       err = xconnect(*c, sockaddr(&addr), len);
+       if (err) {
+               err = errno;
+               goto close_cli0;
+       }
+
+       *p = xaccept_nonblock(s, NULL, NULL);
+       if (*p < 0) {
+               err = errno;
+               goto close_cli0;
+       }
+       return err;
+close_cli0:
+       close(*c);
+       return err;
+}
+
+static inline int create_socket_pairs(int s, int family, int sotype,
+                                     int *c0, int *c1, int *p0, int *p1)
+{
+       int err;
+
+       err = create_pair(s, family, sotype, c0, p0);
+       if (err)
+               return err;
+
+       err = create_pair(s, family, sotype, c1, p1);
+       if (err) {
+               close(*c0);
+               close(*p0);
+       }
+       return err;
+}
+
+static inline int enable_reuseport(int s, int progfd)
+{
+       int err, one = 1;
+
+       err = xsetsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
+       if (err)
+               return -1;
+       err = xsetsockopt(s, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &progfd,
+                         sizeof(progfd));
+       if (err)
+               return -1;
+
+       return 0;
+}
+
+static inline int socket_loopback_reuseport(int family, int sotype, int progfd)
+{
+       struct sockaddr_storage addr;
+       socklen_t len;
+       int err, s;
+
+       init_addr_loopback(family, &addr, &len);
+
+       s = xsocket(family, sotype, 0);
+       if (s == -1)
+               return -1;
+
+       if (progfd >= 0)
+               enable_reuseport(s, progfd);
+
+       err = xbind(s, sockaddr(&addr), len);
+       if (err)
+               goto close;
+
+       if (sotype & SOCK_DGRAM)
+               return s;
+
+       err = xlisten(s, SOMAXCONN);
+       if (err)
+               goto close;
+
+       return s;
+close:
+       xclose(s);
+       return -1;
+}
+
+static inline int socket_loopback(int family, int sotype)
+{
+       return socket_loopback_reuseport(family, sotype, -1);
+}
+
+
+#endif // __SOCKMAP_HELPERS__
index 141c1e5944ee3e264e5869171e27478f4280d78e..b4f6f3a50ae5836ba8a50dbffc6aea7542cd77fd 100644 (file)
 #include <unistd.h>
 #include <linux/vm_sockets.h>
 
-/* workaround for older vm_sockets.h */
-#ifndef VMADDR_CID_LOCAL
-#define VMADDR_CID_LOCAL 1
-#endif
-
 #include <bpf/bpf.h>
 #include <bpf/libbpf.h>
 
 #include "test_progs.h"
 #include "test_sockmap_listen.skel.h"
 
-#define IO_TIMEOUT_SEC 30
-#define MAX_STRERR_LEN 256
-#define MAX_TEST_NAME 80
-
-#define __always_unused        __attribute__((__unused__))
-
-#define _FAIL(errnum, fmt...)                                                  \
-       ({                                                                     \
-               error_at_line(0, (errnum), __func__, __LINE__, fmt);           \
-               CHECK_FAIL(true);                                              \
-       })
-#define FAIL(fmt...) _FAIL(0, fmt)
-#define FAIL_ERRNO(fmt...) _FAIL(errno, fmt)
-#define FAIL_LIBBPF(err, msg)                                                  \
-       ({                                                                     \
-               char __buf[MAX_STRERR_LEN];                                    \
-               libbpf_strerror((err), __buf, sizeof(__buf));                  \
-               FAIL("%s: %s", (msg), __buf);                                  \
-       })
-
-/* Wrappers that fail the test on error and report it. */
-
-#define xaccept_nonblock(fd, addr, len)                                        \
-       ({                                                                     \
-               int __ret =                                                    \
-                       accept_timeout((fd), (addr), (len), IO_TIMEOUT_SEC);   \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("accept");                                  \
-               __ret;                                                         \
-       })
-
-#define xbind(fd, addr, len)                                                   \
-       ({                                                                     \
-               int __ret = bind((fd), (addr), (len));                         \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("bind");                                    \
-               __ret;                                                         \
-       })
-
-#define xclose(fd)                                                             \
-       ({                                                                     \
-               int __ret = close((fd));                                       \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("close");                                   \
-               __ret;                                                         \
-       })
-
-#define xconnect(fd, addr, len)                                                \
-       ({                                                                     \
-               int __ret = connect((fd), (addr), (len));                      \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("connect");                                 \
-               __ret;                                                         \
-       })
-
-#define xgetsockname(fd, addr, len)                                            \
-       ({                                                                     \
-               int __ret = getsockname((fd), (addr), (len));                  \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("getsockname");                             \
-               __ret;                                                         \
-       })
-
-#define xgetsockopt(fd, level, name, val, len)                                 \
-       ({                                                                     \
-               int __ret = getsockopt((fd), (level), (name), (val), (len));   \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("getsockopt(" #name ")");                   \
-               __ret;                                                         \
-       })
-
-#define xlisten(fd, backlog)                                                   \
-       ({                                                                     \
-               int __ret = listen((fd), (backlog));                           \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("listen");                                  \
-               __ret;                                                         \
-       })
-
-#define xsetsockopt(fd, level, name, val, len)                                 \
-       ({                                                                     \
-               int __ret = setsockopt((fd), (level), (name), (val), (len));   \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("setsockopt(" #name ")");                   \
-               __ret;                                                         \
-       })
-
-#define xsend(fd, buf, len, flags)                                             \
-       ({                                                                     \
-               ssize_t __ret = send((fd), (buf), (len), (flags));             \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("send");                                    \
-               __ret;                                                         \
-       })
-
-#define xrecv_nonblock(fd, buf, len, flags)                                    \
-       ({                                                                     \
-               ssize_t __ret = recv_timeout((fd), (buf), (len), (flags),      \
-                                            IO_TIMEOUT_SEC);                  \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("recv");                                    \
-               __ret;                                                         \
-       })
-
-#define xsocket(family, sotype, flags)                                         \
-       ({                                                                     \
-               int __ret = socket(family, sotype, flags);                     \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("socket");                                  \
-               __ret;                                                         \
-       })
-
-#define xbpf_map_delete_elem(fd, key)                                          \
-       ({                                                                     \
-               int __ret = bpf_map_delete_elem((fd), (key));                  \
-               if (__ret < 0)                                               \
-                       FAIL_ERRNO("map_delete");                              \
-               __ret;                                                         \
-       })
-
-#define xbpf_map_lookup_elem(fd, key, val)                                     \
-       ({                                                                     \
-               int __ret = bpf_map_lookup_elem((fd), (key), (val));           \
-               if (__ret < 0)                                               \
-                       FAIL_ERRNO("map_lookup");                              \
-               __ret;                                                         \
-       })
-
-#define xbpf_map_update_elem(fd, key, val, flags)                              \
-       ({                                                                     \
-               int __ret = bpf_map_update_elem((fd), (key), (val), (flags));  \
-               if (__ret < 0)                                               \
-                       FAIL_ERRNO("map_update");                              \
-               __ret;                                                         \
-       })
-
-#define xbpf_prog_attach(prog, target, type, flags)                            \
-       ({                                                                     \
-               int __ret =                                                    \
-                       bpf_prog_attach((prog), (target), (type), (flags));    \
-               if (__ret < 0)                                               \
-                       FAIL_ERRNO("prog_attach(" #type ")");                  \
-               __ret;                                                         \
-       })
-
-#define xbpf_prog_detach2(prog, target, type)                                  \
-       ({                                                                     \
-               int __ret = bpf_prog_detach2((prog), (target), (type));        \
-               if (__ret < 0)                                               \
-                       FAIL_ERRNO("prog_detach2(" #type ")");                 \
-               __ret;                                                         \
-       })
-
-#define xpthread_create(thread, attr, func, arg)                               \
-       ({                                                                     \
-               int __ret = pthread_create((thread), (attr), (func), (arg));   \
-               errno = __ret;                                                 \
-               if (__ret)                                                     \
-                       FAIL_ERRNO("pthread_create");                          \
-               __ret;                                                         \
-       })
-
-#define xpthread_join(thread, retval)                                          \
-       ({                                                                     \
-               int __ret = pthread_join((thread), (retval));                  \
-               errno = __ret;                                                 \
-               if (__ret)                                                     \
-                       FAIL_ERRNO("pthread_join");                            \
-               __ret;                                                         \
-       })
-
-static int poll_read(int fd, unsigned int timeout_sec)
-{
-       struct timeval timeout = { .tv_sec = timeout_sec };
-       fd_set rfds;
-       int r;
-
-       FD_ZERO(&rfds);
-       FD_SET(fd, &rfds);
-
-       r = select(fd + 1, &rfds, NULL, NULL, &timeout);
-       if (r == 0)
-               errno = ETIME;
-
-       return r == 1 ? 0 : -1;
-}
-
-static int accept_timeout(int fd, struct sockaddr *addr, socklen_t *len,
-                         unsigned int timeout_sec)
-{
-       if (poll_read(fd, timeout_sec))
-               return -1;
-
-       return accept(fd, addr, len);
-}
-
-static int recv_timeout(int fd, void *buf, size_t len, int flags,
-                       unsigned int timeout_sec)
-{
-       if (poll_read(fd, timeout_sec))
-               return -1;
-
-       return recv(fd, buf, len, flags);
-}
-
-static void init_addr_loopback4(struct sockaddr_storage *ss, socklen_t *len)
-{
-       struct sockaddr_in *addr4 = memset(ss, 0, sizeof(*ss));
-
-       addr4->sin_family = AF_INET;
-       addr4->sin_port = 0;
-       addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-       *len = sizeof(*addr4);
-}
-
-static void init_addr_loopback6(struct sockaddr_storage *ss, socklen_t *len)
-{
-       struct sockaddr_in6 *addr6 = memset(ss, 0, sizeof(*ss));
-
-       addr6->sin6_family = AF_INET6;
-       addr6->sin6_port = 0;
-       addr6->sin6_addr = in6addr_loopback;
-       *len = sizeof(*addr6);
-}
-
-static void init_addr_loopback_vsock(struct sockaddr_storage *ss, socklen_t *len)
-{
-       struct sockaddr_vm *addr = memset(ss, 0, sizeof(*ss));
-
-       addr->svm_family = AF_VSOCK;
-       addr->svm_port = VMADDR_PORT_ANY;
-       addr->svm_cid = VMADDR_CID_LOCAL;
-       *len = sizeof(*addr);
-}
-
-static void init_addr_loopback(int family, struct sockaddr_storage *ss,
-                              socklen_t *len)
-{
-       switch (family) {
-       case AF_INET:
-               init_addr_loopback4(ss, len);
-               return;
-       case AF_INET6:
-               init_addr_loopback6(ss, len);
-               return;
-       case AF_VSOCK:
-               init_addr_loopback_vsock(ss, len);
-               return;
-       default:
-               FAIL("unsupported address family %d", family);
-       }
-}
-
-static inline struct sockaddr *sockaddr(struct sockaddr_storage *ss)
-{
-       return (struct sockaddr *)ss;
-}
-
-static int enable_reuseport(int s, int progfd)
-{
-       int err, one = 1;
-
-       err = xsetsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
-       if (err)
-               return -1;
-       err = xsetsockopt(s, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &progfd,
-                         sizeof(progfd));
-       if (err)
-               return -1;
-
-       return 0;
-}
-
-static int socket_loopback_reuseport(int family, int sotype, int progfd)
-{
-       struct sockaddr_storage addr;
-       socklen_t len;
-       int err, s;
-
-       init_addr_loopback(family, &addr, &len);
-
-       s = xsocket(family, sotype, 0);
-       if (s == -1)
-               return -1;
-
-       if (progfd >= 0)
-               enable_reuseport(s, progfd);
-
-       err = xbind(s, sockaddr(&addr), len);
-       if (err)
-               goto close;
-
-       if (sotype & SOCK_DGRAM)
-               return s;
-
-       err = xlisten(s, SOMAXCONN);
-       if (err)
-               goto close;
-
-       return s;
-close:
-       xclose(s);
-       return -1;
-}
-
-static int socket_loopback(int family, int sotype)
-{
-       return socket_loopback_reuseport(family, sotype, -1);
-}
+#include "sockmap_helpers.h"
 
 static void test_insert_invalid(struct test_sockmap_listen *skel __always_unused,
                                int family, int sotype, int mapfd)
@@ -984,31 +671,12 @@ static const char *redir_mode_str(enum redir_mode mode)
        }
 }
 
-static int add_to_sockmap(int sock_mapfd, int fd1, int fd2)
-{
-       u64 value;
-       u32 key;
-       int err;
-
-       key = 0;
-       value = fd1;
-       err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
-       if (err)
-               return err;
-
-       key = 1;
-       value = fd2;
-       return xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
-}
-
 static void redir_to_connected(int family, int sotype, int sock_mapfd,
                               int verd_mapfd, enum redir_mode mode)
 {
        const char *log_prefix = redir_mode_str(mode);
-       struct sockaddr_storage addr;
        int s, c0, c1, p0, p1;
        unsigned int pass;
-       socklen_t len;
        int err, n;
        u32 key;
        char b;
@@ -1019,36 +687,13 @@ static void redir_to_connected(int family, int sotype, int sock_mapfd,
        if (s < 0)
                return;
 
-       len = sizeof(addr);
-       err = xgetsockname(s, sockaddr(&addr), &len);
+       err = create_socket_pairs(s, family, sotype, &c0, &c1, &p0, &p1);
        if (err)
                goto close_srv;
 
-       c0 = xsocket(family, sotype, 0);
-       if (c0 < 0)
-               goto close_srv;
-       err = xconnect(c0, sockaddr(&addr), len);
-       if (err)
-               goto close_cli0;
-
-       p0 = xaccept_nonblock(s, NULL, NULL);
-       if (p0 < 0)
-               goto close_cli0;
-
-       c1 = xsocket(family, sotype, 0);
-       if (c1 < 0)
-               goto close_peer0;
-       err = xconnect(c1, sockaddr(&addr), len);
-       if (err)
-               goto close_cli1;
-
-       p1 = xaccept_nonblock(s, NULL, NULL);
-       if (p1 < 0)
-               goto close_cli1;
-
        err = add_to_sockmap(sock_mapfd, p0, p1);
        if (err)
-               goto close_peer1;
+               goto close;
 
        n = write(mode == REDIR_INGRESS ? c1 : p1, "a", 1);
        if (n < 0)
@@ -1056,12 +701,12 @@ static void redir_to_connected(int family, int sotype, int sock_mapfd,
        if (n == 0)
                FAIL("%s: incomplete write", log_prefix);
        if (n < 1)
-               goto close_peer1;
+               goto close;
 
        key = SK_PASS;
        err = xbpf_map_lookup_elem(verd_mapfd, &key, &pass);
        if (err)
-               goto close_peer1;
+               goto close;
        if (pass != 1)
                FAIL("%s: want pass count 1, have %d", log_prefix, pass);
        n = recv_timeout(c0, &b, 1, 0, IO_TIMEOUT_SEC);
@@ -1070,13 +715,10 @@ static void redir_to_connected(int family, int sotype, int sock_mapfd,
        if (n == 0)
                FAIL("%s: incomplete recv", log_prefix);
 
-close_peer1:
+close:
        xclose(p1);
-close_cli1:
        xclose(c1);
-close_peer0:
        xclose(p0);
-close_cli0:
        xclose(c0);
 close_srv:
        xclose(s);
diff --git a/tools/testing/selftests/bpf/progs/test_sockmap_drop_prog.c b/tools/testing/selftests/bpf/progs/test_sockmap_drop_prog.c
new file mode 100644 (file)
index 0000000..2931480
--- /dev/null
@@ -0,0 +1,32 @@
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_endian.h>
+
+struct {
+       __uint(type, BPF_MAP_TYPE_SOCKMAP);
+       __uint(max_entries, 20);
+       __type(key, int);
+       __type(value, int);
+} sock_map_rx SEC(".maps");
+
+struct {
+       __uint(type, BPF_MAP_TYPE_SOCKMAP);
+       __uint(max_entries, 20);
+       __type(key, int);
+       __type(value, int);
+} sock_map_tx SEC(".maps");
+
+struct {
+       __uint(type, BPF_MAP_TYPE_SOCKMAP);
+       __uint(max_entries, 20);
+       __type(key, int);
+       __type(value, int);
+} sock_map_msg SEC(".maps");
+
+SEC("sk_skb")
+int prog_skb_verdict(struct __sk_buff *skb)
+{
+       return SK_DROP;
+}
+
+char _license[] SEC("license") = "GPL";
index baf9ebc6d903f0a8b97dcb01b8d0870aa33c28fd..99d2ea9fb658f35701f419797f48c722ced85b27 100644 (file)
@@ -191,7 +191,7 @@ SEC("sockops")
 int bpf_sockmap(struct bpf_sock_ops *skops)
 {
        __u32 lport, rport;
-       int op, err, ret;
+       int op, ret;
 
        op = (int) skops->op;
 
@@ -203,10 +203,10 @@ int bpf_sockmap(struct bpf_sock_ops *skops)
                if (lport == 10000) {
                        ret = 1;
 #ifdef SOCKMAP
-                       err = bpf_sock_map_update(skops, &sock_map, &ret,
+                       bpf_sock_map_update(skops, &sock_map, &ret,
                                                  BPF_NOEXIST);
 #else
-                       err = bpf_sock_hash_update(skops, &sock_map, &ret,
+                       bpf_sock_hash_update(skops, &sock_map, &ret,
                                                   BPF_NOEXIST);
 #endif
                }
@@ -218,10 +218,10 @@ int bpf_sockmap(struct bpf_sock_ops *skops)
                if (bpf_ntohl(rport) == 10001) {
                        ret = 10;
 #ifdef SOCKMAP
-                       err = bpf_sock_map_update(skops, &sock_map, &ret,
+                       bpf_sock_map_update(skops, &sock_map, &ret,
                                                  BPF_NOEXIST);
 #else
-                       err = bpf_sock_hash_update(skops, &sock_map, &ret,
+                       bpf_sock_hash_update(skops, &sock_map, &ret,
                                                   BPF_NOEXIST);
 #endif
                }
@@ -230,8 +230,6 @@ int bpf_sockmap(struct bpf_sock_ops *skops)
                break;
        }
 
-       __sink(err);
-
        return 0;
 }
 
diff --git a/tools/testing/selftests/bpf/progs/test_sockmap_pass_prog.c b/tools/testing/selftests/bpf/progs/test_sockmap_pass_prog.c
new file mode 100644 (file)
index 0000000..1d86a71
--- /dev/null
@@ -0,0 +1,32 @@
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_endian.h>
+
+struct {
+       __uint(type, BPF_MAP_TYPE_SOCKMAP);
+       __uint(max_entries, 20);
+       __type(key, int);
+       __type(value, int);
+} sock_map_rx SEC(".maps");
+
+struct {
+       __uint(type, BPF_MAP_TYPE_SOCKMAP);
+       __uint(max_entries, 20);
+       __type(key, int);
+       __type(value, int);
+} sock_map_tx SEC(".maps");
+
+struct {
+       __uint(type, BPF_MAP_TYPE_SOCKMAP);
+       __uint(max_entries, 20);
+       __type(key, int);
+       __type(value, int);
+} sock_map_msg SEC(".maps");
+
+SEC("sk_skb")
+int prog_skb_verdict(struct __sk_buff *skb)
+{
+       return SK_PASS;
+}
+
+char _license[] SEC("license") = "GPL";
index db29a3146a8611ab5891e615dc1925916c4a6074..607ba5c38977f20dfb5b2133ce3c0a71b31cf59b 100755 (executable)
@@ -6,6 +6,7 @@
 ALL_TESTS="
        prio
        arp_validate
+       num_grat_arp
 "
 
 REQUIRE_MZ=no
@@ -255,6 +256,55 @@ arp_validate()
        arp_validate_ns "active-backup"
 }
 
+garp_test()
+{
+       local param="$1"
+       local active_slave exp_num real_num i
+       RET=0
+
+       # create bond
+       bond_reset "${param}"
+
+       bond_check_connection
+       [ $RET -ne 0 ] && log_test "num_grat_arp" "$retmsg"
+
+
+       # Add tc rules to count GARP number
+       for i in $(seq 0 2); do
+               tc -n ${g_ns} filter add dev s$i ingress protocol arp pref 1 handle 101 \
+                       flower skip_hw arp_op request arp_sip ${s_ip4} arp_tip ${s_ip4} action pass
+       done
+
+       # Do failover
+       active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
+       ip -n ${s_ns} link set ${active_slave} down
+
+       exp_num=$(echo "${param}" | cut -f6 -d ' ')
+       sleep $((exp_num + 2))
+
+       active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
+
+       # check result
+       real_num=$(tc_rule_handle_stats_get "dev s${active_slave#eth} ingress" 101 ".packets" "-n ${g_ns}")
+       if [ "${real_num}" -ne "${exp_num}" ]; then
+               echo "$real_num garp packets sent on active slave ${active_slave}"
+               RET=1
+       fi
+
+       for i in $(seq 0 2); do
+               tc -n ${g_ns} filter del dev s$i ingress
+       done
+}
+
+num_grat_arp()
+{
+       local val
+       for val in 10 20 30 50; do
+               garp_test "mode active-backup miimon 100 num_grat_arp $val peer_notify_delay 1000"
+               log_test "num_grat_arp" "active-backup miimon num_grat_arp $val"
+       done
+}
+
 trap cleanup EXIT
 
 setup_prepare
index 4045ca97fb22d986369bd80b722561cfedd0e013..69ab99a560434a7a7ddd6a99662896d72e94c3ca 100644 (file)
@@ -61,6 +61,8 @@ server_create()
                ip -n ${g_ns} link set s${i} up
                ip -n ${g_ns} link set s${i} master br0
                ip -n ${s_ns} link set eth${i} master bond0
+
+               tc -n ${g_ns} qdisc add dev s${i} clsact
        done
 
        ip -n ${s_ns} link set bond0 up
index d6e106fbce11c7706e061cf23a920b8d0cb03459..a1e955d2de4cc6ce6c99c440d6b1e3cb337031b9 100644 (file)
@@ -1,7 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0
 all:
 
-TEST_PROGS := ftracetest
+TEST_PROGS_EXTENDED := ftracetest
+TEST_PROGS := ftracetest-ktap
 TEST_FILES := test.d settings
 EXTRA_CLEAN := $(OUTPUT)/logs/*
 
index c3311c8c4089062a57be297a8dc42f09ff6b4906..2506621e75dfb2893c747b9108b030357f07fcb3 100755 (executable)
@@ -13,6 +13,7 @@ echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]"
 echo " Options:"
 echo "         -h|--help  Show help message"
 echo "         -k|--keep  Keep passed test logs"
+echo "         -K|--ktap  Output in KTAP format"
 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)"
@@ -85,6 +86,10 @@ parse_opts() { # opts
       KEEP_LOG=1
       shift 1
     ;;
+    --ktap|-K)
+      KTAP=1
+      shift 1
+    ;;
     --verbose|-v|-vv|-vvv)
       if [ $VERBOSE -eq -1 ]; then
        usage "--console can not use with --verbose"
@@ -178,6 +183,7 @@ TEST_DIR=$TOP_DIR/test.d
 TEST_CASES=`find_testcases $TEST_DIR`
 LOG_DIR=$TOP_DIR/logs/`date +%Y%m%d-%H%M%S`/
 KEEP_LOG=0
+KTAP=0
 DEBUG=0
 VERBOSE=0
 UNSUPPORTED_RESULT=0
@@ -229,7 +235,7 @@ prlog() { # messages
     newline=
     shift
   fi
-  printf "$*$newline"
+  [ "$KTAP" != "1" ] && printf "$*$newline"
   [ "$LOG_FILE" ] && printf "$*$newline" | strip_esc >> $LOG_FILE
 }
 catlog() { #file
@@ -260,11 +266,11 @@ TOTAL_RESULT=0
 
 INSTANCE=
 CASENO=0
+CASENAME=
 
 testcase() { # testfile
   CASENO=$((CASENO+1))
-  desc=`grep "^#[ \t]*description:" $1 | cut -f2- -d:`
-  prlog -n "[$CASENO]$INSTANCE$desc"
+  CASENAME=`grep "^#[ \t]*description:" $1 | cut -f2- -d:`
 }
 
 checkreq() { # testfile
@@ -277,40 +283,68 @@ test_on_instance() { # testfile
   grep -q "^#[ \t]*flags:.*instance" $1
 }
 
+ktaptest() { # result comment
+  if [ "$KTAP" != "1" ]; then
+    return
+  fi
+
+  local result=
+  if [ "$1" = "1" ]; then
+    result="ok"
+  else
+    result="not ok"
+  fi
+  shift
+
+  local comment=$*
+  if [ "$comment" != "" ]; then
+    comment="# $comment"
+  fi
+
+  echo $CASENO $result $INSTANCE$CASENAME $comment
+}
+
 eval_result() { # sigval
   case $1 in
     $PASS)
       prlog "  [${color_green}PASS${color_reset}]"
+      ktaptest 1
       PASSED_CASES="$PASSED_CASES $CASENO"
       return 0
     ;;
     $FAIL)
       prlog "  [${color_red}FAIL${color_reset}]"
+      ktaptest 0
       FAILED_CASES="$FAILED_CASES $CASENO"
       return 1 # this is a bug.
     ;;
     $UNRESOLVED)
       prlog "  [${color_blue}UNRESOLVED${color_reset}]"
+      ktaptest 0 UNRESOLVED
       UNRESOLVED_CASES="$UNRESOLVED_CASES $CASENO"
       return $UNRESOLVED_RESULT # depends on use case
     ;;
     $UNTESTED)
       prlog "  [${color_blue}UNTESTED${color_reset}]"
+      ktaptest 1 SKIP
       UNTESTED_CASES="$UNTESTED_CASES $CASENO"
       return 0
     ;;
     $UNSUPPORTED)
       prlog "  [${color_blue}UNSUPPORTED${color_reset}]"
+      ktaptest 1 SKIP
       UNSUPPORTED_CASES="$UNSUPPORTED_CASES $CASENO"
       return $UNSUPPORTED_RESULT # depends on use case
     ;;
     $XFAIL)
       prlog "  [${color_green}XFAIL${color_reset}]"
+      ktaptest 1 XFAIL
       XFAILED_CASES="$XFAILED_CASES $CASENO"
       return 0
     ;;
     *)
       prlog "  [${color_blue}UNDEFINED${color_reset}]"
+      ktaptest 0 error
       UNDEFINED_CASES="$UNDEFINED_CASES $CASENO"
       return 1 # this must be a test bug
     ;;
@@ -371,6 +405,7 @@ __run_test() { # testfile
 run_test() { # testfile
   local testname=`basename $1`
   testcase $1
+  prlog -n "[$CASENO]$INSTANCE$CASENAME"
   if [ ! -z "$LOG_FILE" ] ; then
     local testlog=`mktemp $LOG_DIR/${CASENO}-${testname}-log.XXXXXX`
   else
@@ -405,6 +440,17 @@ run_test() { # testfile
 # load in the helper functions
 . $TEST_DIR/functions
 
+if [ "$KTAP" = "1" ]; then
+  echo "TAP version 13"
+
+  casecount=`echo $TEST_CASES | wc -w`
+  for t in $TEST_CASES; do
+    test_on_instance $t || continue
+    casecount=$((casecount+1))
+  done
+  echo "1..${casecount}"
+fi
+
 # Main loop
 for t in $TEST_CASES; do
   run_test $t
@@ -439,6 +485,17 @@ 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`
 
+if [ "$KTAP" = "1" ]; then
+  echo -n "# Totals:"
+  echo -n " pass:"`echo $PASSED_CASES | wc -w`
+  echo -n " faii:"`echo $FAILED_CASES | wc -w`
+  echo -n " xfail:"`echo $XFAILED_CASES | wc -w`
+  echo -n " xpass:0"
+  echo -n " skip:"`echo $UNTESTED_CASES $UNSUPPORTED_CASES | wc -w`
+  echo -n " error:"`echo $UNRESOLVED_CASES $UNDEFINED_CASES | wc -w`
+  echo
+fi
+
 cleanup
 
 # if no error, return 0
diff --git a/tools/testing/selftests/ftrace/ftracetest-ktap b/tools/testing/selftests/ftrace/ftracetest-ktap
new file mode 100755 (executable)
index 0000000..b328467
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh -e
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# ftracetest-ktap: Wrapper to integrate ftracetest with the kselftest runner
+#
+# Copyright (C) Arm Ltd., 2023
+
+./ftracetest -K
index e2ff3bf4df80f1726344a45e94f973a83e9d0faa..2de7c61d1ae308d06251bd9d072627e4120d37ce 100644 (file)
@@ -9,18 +9,33 @@ fail() { #msg
     exit_fail
 }
 
-echo "Test event filter function name"
+sample_events() {
+    echo > trace
+    echo 1 > events/kmem/kmem_cache_free/enable
+    echo 1 > tracing_on
+    ls > /dev/null
+    echo 0 > tracing_on
+    echo 0 > events/kmem/kmem_cache_free/enable
+}
+
 echo 0 > tracing_on
 echo 0 > events/enable
+
+echo "Get the most frequently calling function"
+sample_events
+
+target_func=`cut -d: -f3 trace | sed 's/call_site=\([^+]*\)+0x.*/\1/' | sort | uniq -c | sort | tail -n 1 | sed 's/^[ 0-9]*//'`
+if [ -z "$target_func" ]; then
+    exit_fail
+fi
 echo > trace
-echo 'call_site.function == exit_mmap' > events/kmem/kmem_cache_free/filter
-echo 1 > events/kmem/kmem_cache_free/enable
-echo 1 > tracing_on
-ls > /dev/null
-echo 0 > events/kmem/kmem_cache_free/enable
 
-hitcnt=`grep kmem_cache_free trace| grep exit_mmap | wc -l`
-misscnt=`grep kmem_cache_free trace| grep -v exit_mmap | wc -l`
+echo "Test event filter function name"
+echo "call_site.function == $target_func" > events/kmem/kmem_cache_free/filter
+sample_events
+
+hitcnt=`grep kmem_cache_free trace| grep $target_func | wc -l`
+misscnt=`grep kmem_cache_free trace| grep -v $target_func | wc -l`
 
 if [ $hitcnt -eq 0 ]; then
        exit_fail
@@ -30,20 +45,14 @@ if [ $misscnt -gt 0 ]; then
        exit_fail
 fi
 
-address=`grep ' exit_mmap$' /proc/kallsyms | cut -d' ' -f1`
+address=`grep " ${target_func}\$" /proc/kallsyms | cut -d' ' -f1`
 
 echo "Test event filter function address"
-echo 0 > tracing_on
-echo 0 > events/enable
-echo > trace
 echo "call_site.function == 0x$address" > events/kmem/kmem_cache_free/filter
-echo 1 > events/kmem/kmem_cache_free/enable
-echo 1 > tracing_on
-sleep 1
-echo 0 > events/kmem/kmem_cache_free/enable
+sample_events
 
-hitcnt=`grep kmem_cache_free trace| grep exit_mmap | wc -l`
-misscnt=`grep kmem_cache_free trace| grep -v exit_mmap | wc -l`
+hitcnt=`grep kmem_cache_free trace| grep $target_func | wc -l`
+misscnt=`grep kmem_cache_free trace| grep -v $target_func | wc -l`
 
 if [ $hitcnt -eq 0 ]; then
        exit_fail
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-stack-legacy.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-stack-legacy.tc
new file mode 100644 (file)
index 0000000..d0cd91a
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# description: event trigger - test inter-event histogram trigger trace action with dynamic string param (legacy stack)
+# requires: set_event synthetic_events events/sched/sched_process_exec/hist "long[] stack' >> synthetic_events":README
+
+fail() { #msg
+    echo $1
+    exit_fail
+}
+
+echo "Test create synthetic event with stack"
+
+# Test the old stacktrace keyword (for backward compatibility)
+echo 's:wake_lat pid_t pid; u64 delta; unsigned long[] stack;' > dynamic_events
+echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=stacktrace  if prev_state == 1||prev_state == 2' >> events/sched/sched_switch/trigger
+echo 'hist:keys=prev_pid:delta=common_timestamp.usecs-$ts,s=$st:onmax($delta).trace(wake_lat,prev_pid,$delta,$s)' >> events/sched/sched_switch/trigger
+echo 1 > events/synthetic/wake_lat/enable
+sleep 1
+
+if ! grep -q "=>.*sched" trace; then
+    fail "Failed to create synthetic event with stack"
+fi
+
+exit 0
index 755dbe94ccf4a6e72b4bdcd822b93455afb412a4..8f1cc9a86a0605d64ccc7e14505f6375f9c92cb2 100644 (file)
@@ -1,7 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test inter-event histogram trigger trace action with dynamic string param
-# requires: set_event synthetic_events events/sched/sched_process_exec/hist "long[]' >> synthetic_events":README
+# requires: set_event synthetic_events events/sched/sched_process_exec/hist "can be any field, or the special string 'common_stacktrace'":README
 
 fail() { #msg
     echo $1
@@ -10,9 +10,8 @@ fail() { #msg
 
 echo "Test create synthetic event with stack"
 
-
 echo 's:wake_lat pid_t pid; u64 delta; unsigned long[] stack;' > dynamic_events
-echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=stacktrace  if prev_state == 1||prev_state == 2' >> events/sched/sched_switch/trigger
+echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=common_stacktrace  if prev_state == 1||prev_state == 2' >> events/sched/sched_switch/trigger
 echo 'hist:keys=prev_pid:delta=common_timestamp.usecs-$ts,s=$st:onmax($delta).trace(wake_lat,prev_pid,$delta,$s)' >> events/sched/sched_switch/trigger
 echo 1 > events/synthetic/wake_lat/enable
 sleep 1
index 9f539d454ee4d2bb2f51603b24c94fe5789a19de..fa2ce2b9dd5fcce1aecebfa92780141346db2cd1 100755 (executable)
@@ -389,6 +389,9 @@ create_chip chip
 create_bank chip bank
 set_num_lines chip bank 8
 enable_chip chip
+DEVNAME=`configfs_dev_name chip`
+CHIPNAME=`configfs_chip_name chip bank`
+SYSFS_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio0/value"
 $BASE_DIR/gpio-mockup-cdev -b pull-up /dev/`configfs_chip_name chip bank` 0
 test `cat $SYSFS_PATH` = "1" || fail "bias setting does not work"
 remove_chip chip
index 7a5ff646e7e79efa3a83fc66f54456a761bd1c42..4761b768b773c45bbb1d22c3ac78a289f55e36ce 100644 (file)
@@ -116,6 +116,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/sev_migrate_tests
 TEST_GEN_PROGS_x86_64 += x86_64/amx_test
 TEST_GEN_PROGS_x86_64 += x86_64/max_vcpuid_cap_test
 TEST_GEN_PROGS_x86_64 += x86_64/triple_fault_event_test
+TEST_GEN_PROGS_x86_64 += x86_64/recalc_apic_map_test
 TEST_GEN_PROGS_x86_64 += access_tracking_perf_test
 TEST_GEN_PROGS_x86_64 += demand_paging_test
 TEST_GEN_PROGS_x86_64 += dirty_log_test
diff --git a/tools/testing/selftests/kvm/x86_64/recalc_apic_map_test.c b/tools/testing/selftests/kvm/x86_64/recalc_apic_map_test.c
new file mode 100644 (file)
index 0000000..4c416eb
--- /dev/null
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Test edge cases and race conditions in kvm_recalculate_apic_map().
+ */
+
+#include <sys/ioctl.h>
+#include <pthread.h>
+#include <time.h>
+
+#include "processor.h"
+#include "test_util.h"
+#include "kvm_util.h"
+#include "apic.h"
+
+#define TIMEOUT                5       /* seconds */
+
+#define LAPIC_DISABLED 0
+#define LAPIC_X2APIC   (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE)
+#define MAX_XAPIC_ID   0xff
+
+static void *race(void *arg)
+{
+       struct kvm_lapic_state lapic = {};
+       struct kvm_vcpu *vcpu = arg;
+
+       while (1) {
+               /* Trigger kvm_recalculate_apic_map(). */
+               vcpu_ioctl(vcpu, KVM_SET_LAPIC, &lapic);
+               pthread_testcancel();
+       }
+
+       return NULL;
+}
+
+int main(void)
+{
+       struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
+       struct kvm_vcpu *vcpuN;
+       struct kvm_vm *vm;
+       pthread_t thread;
+       time_t t;
+       int i;
+
+       kvm_static_assert(KVM_MAX_VCPUS > MAX_XAPIC_ID);
+
+       /*
+        * Create the max number of vCPUs supported by selftests so that KVM
+        * has decent amount of work to do when recalculating the map, i.e. to
+        * make the problematic window large enough to hit.
+        */
+       vm = vm_create_with_vcpus(KVM_MAX_VCPUS, NULL, vcpus);
+
+       /*
+        * Enable x2APIC on all vCPUs so that KVM doesn't bail from the recalc
+        * due to vCPUs having aliased xAPIC IDs (truncated to 8 bits).
+        */
+       for (i = 0; i < KVM_MAX_VCPUS; i++)
+               vcpu_set_msr(vcpus[i], MSR_IA32_APICBASE, LAPIC_X2APIC);
+
+       ASSERT_EQ(pthread_create(&thread, NULL, race, vcpus[0]), 0);
+
+       vcpuN = vcpus[KVM_MAX_VCPUS - 1];
+       for (t = time(NULL) + TIMEOUT; time(NULL) < t;) {
+               vcpu_set_msr(vcpuN, MSR_IA32_APICBASE, LAPIC_X2APIC);
+               vcpu_set_msr(vcpuN, MSR_IA32_APICBASE, LAPIC_DISABLED);
+       }
+
+       ASSERT_EQ(pthread_cancel(thread), 0);
+       ASSERT_EQ(pthread_join(thread, NULL), 0);
+
+       kvm_vm_free(vm);
+
+       return 0;
+}
index a47b26ab48f23b0ace3e247bb61cb8bcd9701db0..0f5e88c8f4ffece3833aab1929a119b22a9e063f 100755 (executable)
@@ -2283,7 +2283,7 @@ EOF
 ################################################################################
 # main
 
-while getopts :t:pP46hv:w: o
+while getopts :t:pP46hvw: o
 do
        case $o in
                t) TESTS=$OPTARG;;
index 7da8ec838c63ac0f639c63ce0b115acfd7e4dd0f..35d89dfa6f11bfb295713ba50194b408d9ed92c5 100755 (executable)
@@ -68,7 +68,7 @@ setup()
 cleanup()
 {
        $IP link del dev dummy0 &> /dev/null
-       ip netns del ns1
+       ip netns del ns1 &> /dev/null
        ip netns del ns2 &> /dev/null
 }
 
index 057c3d0ad62054f767bb2785232bbb25d8f1cf24..9ddb68dd6a089a42239554e4bd670000290f5b49 100755 (executable)
@@ -791,8 +791,9 @@ tc_rule_handle_stats_get()
        local id=$1; shift
        local handle=$1; shift
        local selector=${1:-.packets}; shift
+       local netns=${1:-""}; shift
 
-       tc -j -s filter show $id \
+       tc $netns -j -s filter show $id \
            | jq ".[] | select(.options.handle == $handle) | \
                  .options.actions[0].stats$selector"
 }
index 43a723626126153f4e9a2304154240d552b3d40d..7b936a92685949199fae2a31451a5f74c288b627 100644 (file)
@@ -9,7 +9,7 @@ TEST_PROGS := mptcp_connect.sh pm_netlink.sh mptcp_join.sh diag.sh \
 
 TEST_GEN_FILES = mptcp_connect pm_nl_ctl mptcp_sockopt mptcp_inq
 
-TEST_FILES := settings
+TEST_FILES := mptcp_lib.sh settings
 
 EXTRA_CLEAN := *.pcap
 
index ef628b16fe9b4ecaf58ebd7011351605c7cafe38..4eacdb1ab96289db7f9939a619bbab05cdbb1a70 100755 (executable)
@@ -1,6 +1,8 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
+. "$(dirname "${0}")/mptcp_lib.sh"
+
 sec=$(date +%s)
 rndh=$(printf %x $sec)-$(mktemp -u XXXXXX)
 ns="ns1-$rndh"
@@ -31,6 +33,8 @@ cleanup()
        ip netns del $ns
 }
 
+mptcp_lib_check_mptcp
+
 ip -Version > /dev/null 2>&1
 if [ $? -ne 0 ];then
        echo "SKIP: Could not run test without ip tool"
index a43d3e2f59bbeb2f616b2b69cefc330b2b06cf8d..c1f7bac1994235f350b52d90a5bce6f755a81255 100755 (executable)
@@ -1,6 +1,8 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
+. "$(dirname "${0}")/mptcp_lib.sh"
+
 time_start=$(date +%s)
 
 optstring="S:R:d:e:l:r:h4cm:f:tC"
@@ -141,6 +143,8 @@ cleanup()
        done
 }
 
+mptcp_lib_check_mptcp
+
 ip -Version > /dev/null 2>&1
 if [ $? -ne 0 ];then
        echo "SKIP: Could not run test without ip tool"
index 26310c17b4c6b68a5fb91d898516b0c7709113e4..96f63172b8feed9a023ca7cf8dcad2b93057be64 100755 (executable)
@@ -10,6 +10,8 @@
 # because it's invoked by variable name, see how the "tests" array is used
 #shellcheck disable=SC2317
 
+. "$(dirname "${0}")/mptcp_lib.sh"
+
 ret=0
 sin=""
 sinfail=""
@@ -17,6 +19,7 @@ sout=""
 cin=""
 cinfail=""
 cinsent=""
+tmpfile=""
 cout=""
 capout=""
 ns1=""
@@ -136,6 +139,8 @@ cleanup_partial()
 
 check_tools()
 {
+       mptcp_lib_check_mptcp
+
        if ! ip -Version &> /dev/null; then
                echo "SKIP: Could not run test without ip tool"
                exit $ksft_skip
@@ -175,6 +180,7 @@ cleanup()
 {
        rm -f "$cin" "$cout" "$sinfail"
        rm -f "$sin" "$sout" "$cinsent" "$cinfail"
+       rm -f "$tmpfile"
        rm -rf $evts_ns1 $evts_ns2
        cleanup_partial
 }
@@ -383,9 +389,16 @@ check_transfer()
                        fail_test
                        return 1
                fi
-               bytes="--bytes=${bytes}"
+
+               # note: BusyBox's "cmp" command doesn't support --bytes
+               tmpfile=$(mktemp)
+               head --bytes="$bytes" "$in" > "$tmpfile"
+               mv "$tmpfile" "$in"
+               head --bytes="$bytes" "$out" > "$tmpfile"
+               mv "$tmpfile" "$out"
+               tmpfile=""
        fi
-       cmp -l "$in" "$out" ${bytes} | while read -r i a b; do
+       cmp -l "$in" "$out" | while read -r i a b; do
                local sum=$((0${a} + 0${b}))
                if [ $check_invert -eq 0 ] || [ $sum -ne $((0xff)) ]; then
                        echo "[ FAIL ] $what does not match (in, out):"
diff --git a/tools/testing/selftests/net/mptcp/mptcp_lib.sh b/tools/testing/selftests/net/mptcp/mptcp_lib.sh
new file mode 100644 (file)
index 0000000..3286536
--- /dev/null
@@ -0,0 +1,40 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+readonly KSFT_FAIL=1
+readonly KSFT_SKIP=4
+
+# SELFTESTS_MPTCP_LIB_EXPECT_ALL_FEATURES env var can be set when validating all
+# features using the last version of the kernel and the selftests to make sure
+# a test is not being skipped by mistake.
+mptcp_lib_expect_all_features() {
+       [ "${SELFTESTS_MPTCP_LIB_EXPECT_ALL_FEATURES:-}" = "1" ]
+}
+
+# $1: msg
+mptcp_lib_fail_if_expected_feature() {
+       if mptcp_lib_expect_all_features; then
+               echo "ERROR: missing feature: ${*}"
+               exit ${KSFT_FAIL}
+       fi
+
+       return 1
+}
+
+# $1: file
+mptcp_lib_has_file() {
+       local f="${1}"
+
+       if [ -f "${f}" ]; then
+               return 0
+       fi
+
+       mptcp_lib_fail_if_expected_feature "${f} file not found"
+}
+
+mptcp_lib_check_mptcp() {
+       if ! mptcp_lib_has_file "/proc/sys/net/mptcp/enabled"; then
+               echo "SKIP: MPTCP support is not available"
+               exit ${KSFT_SKIP}
+       fi
+}
index 1b70c0a304cef4081ffc775efd19e73c4a0456d6..ff5adbb9c7f2b9a3e7ea655526f751b47f1b5431 100755 (executable)
@@ -1,6 +1,8 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
+. "$(dirname "${0}")/mptcp_lib.sh"
+
 ret=0
 sin=""
 sout=""
@@ -84,6 +86,8 @@ cleanup()
        rm -f "$sin" "$sout"
 }
 
+mptcp_lib_check_mptcp
+
 ip -Version > /dev/null 2>&1
 if [ $? -ne 0 ];then
        echo "SKIP: Could not run test without ip tool"
index 89839d1ff9d834f74fe389efd8b1b986520b3968..32f7533e0919a255842b640f9c9300142af21157 100755 (executable)
@@ -1,6 +1,8 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
+. "$(dirname "${0}")/mptcp_lib.sh"
+
 ksft_skip=4
 ret=0
 
@@ -34,6 +36,8 @@ cleanup()
        ip netns del $ns1
 }
 
+mptcp_lib_check_mptcp
+
 ip -Version > /dev/null 2>&1
 if [ $? -ne 0 ];then
        echo "SKIP: Could not run test without ip tool"
index 9f22f7e5027df1f352d8f4365c680a603a30923d..36a3c9d92e2055adf051d82d1623dbd044daf6c0 100755 (executable)
@@ -1,6 +1,8 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
+. "$(dirname "${0}")/mptcp_lib.sh"
+
 sec=$(date +%s)
 rndh=$(printf %x $sec)-$(mktemp -u XXXXXX)
 ns1="ns1-$rndh"
@@ -34,6 +36,8 @@ cleanup()
        done
 }
 
+mptcp_lib_check_mptcp
+
 ip -Version > /dev/null 2>&1
 if [ $? -ne 0 ];then
        echo "SKIP: Could not run test without ip tool"
index b1eb7bce599dc0e76078df68df84c9ce117eac8e..8092399d911f1afa89860737402a0f839244ce49 100755 (executable)
@@ -1,6 +1,10 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
+. "$(dirname "${0}")/mptcp_lib.sh"
+
+mptcp_lib_check_mptcp
+
 ip -Version > /dev/null 2>&1
 if [ $? -ne 0 ];then
        echo "SKIP: Cannot not run test without ip tool"
index 1003119773e5da58dbab0ea21115440a4473b723..f96282362811945e0e47be9cce1d7f41a84f18eb 100755 (executable)
@@ -232,10 +232,14 @@ setup_rt_networking()
        local nsname=rt-${rt}
 
        ip netns add ${nsname}
+
+       ip netns exec ${nsname} sysctl -wq net.ipv6.conf.all.accept_dad=0
+       ip netns exec ${nsname} sysctl -wq net.ipv6.conf.default.accept_dad=0
+
        ip link set veth-rt-${rt} netns ${nsname}
        ip -netns ${nsname} link set veth-rt-${rt} name veth0
 
-       ip -netns ${nsname} addr add ${IPv6_RT_NETWORK}::${rt}/64 dev veth0
+       ip -netns ${nsname} addr add ${IPv6_RT_NETWORK}::${rt}/64 dev veth0 nodad
        ip -netns ${nsname} link set veth0 up
        ip -netns ${nsname} link set lo up
 
@@ -254,6 +258,12 @@ setup_hs()
 
        # set the networking for the host
        ip netns add ${hsname}
+
+       # disable the rp_filter otherwise the kernel gets confused about how
+       # to route decap ipv4 packets.
+       ip netns exec ${rtname} sysctl -wq net.ipv4.conf.all.rp_filter=0
+       ip netns exec ${rtname} sysctl -wq net.ipv4.conf.default.rp_filter=0
+
        ip -netns ${hsname} link add veth0 type veth peer name ${rtveth}
        ip -netns ${hsname} link set ${rtveth} netns ${rtname}
        ip -netns ${hsname} addr add ${IPv4_HS_NETWORK}.${hs}/24 dev veth0
@@ -272,11 +282,6 @@ setup_hs()
 
        ip netns exec ${rtname} sysctl -wq net.ipv4.conf.${rtveth}.proxy_arp=1
 
-       # disable the rp_filter otherwise the kernel gets confused about how
-       # to route decap ipv4 packets.
-       ip netns exec ${rtname} sysctl -wq net.ipv4.conf.all.rp_filter=0
-       ip netns exec ${rtname} sysctl -wq net.ipv4.conf.${rtveth}.rp_filter=0
-
        ip netns exec ${rtname} sh -c "echo 1 > /proc/sys/net/vrf/strict_mode"
 }
 
index 7060bae04ec87d9ecd59d6643becb6452fdf22d5..a32f490f753996bff69c44e92269b5cec0056575 100755 (executable)
@@ -188,6 +188,26 @@ if [ $? -ne 0 ]; then
        exit $ksft_skip
 fi
 
+ip netns exec $ns2 nft -f - <<EOF
+table inet filter {
+   counter ip4dscp0 { }
+   counter ip4dscp3 { }
+
+   chain input {
+      type filter hook input priority 0; policy accept;
+      meta l4proto tcp goto {
+             ip dscp cs3 counter name ip4dscp3 accept
+             ip dscp 0 counter name ip4dscp0 accept
+      }
+   }
+}
+EOF
+
+if [ $? -ne 0 ]; then
+       echo "SKIP: Could not load nft ruleset"
+       exit $ksft_skip
+fi
+
 # test basic connectivity
 if ! ip netns exec $ns1 ping -c 1 -q 10.0.2.99 > /dev/null; then
   echo "ERROR: $ns1 cannot reach ns2" 1>&2
@@ -255,6 +275,60 @@ check_counters()
        fi
 }
 
+check_dscp()
+{
+       local what=$1
+       local ok=1
+
+       local counter=$(ip netns exec $ns2 nft reset counter inet filter ip4dscp3 | grep packets)
+
+       local pc4=${counter%*bytes*}
+       local pc4=${pc4#*packets}
+
+       local counter=$(ip netns exec $ns2 nft reset counter inet filter ip4dscp0 | grep packets)
+       local pc4z=${counter%*bytes*}
+       local pc4z=${pc4z#*packets}
+
+       case "$what" in
+       "dscp_none")
+               if [ $pc4 -gt 0 ] || [ $pc4z -eq 0 ]; then
+                       echo "FAIL: dscp counters do not match, expected dscp3 == 0, dscp0 > 0, but got $pc4,$pc4z" 1>&2
+                       ret=1
+                       ok=0
+               fi
+               ;;
+       "dscp_fwd")
+               if [ $pc4 -eq 0 ] || [ $pc4z -eq 0 ]; then
+                       echo "FAIL: dscp counters do not match, expected dscp3 and dscp0 > 0 but got $pc4,$pc4z" 1>&2
+                       ret=1
+                       ok=0
+               fi
+               ;;
+       "dscp_ingress")
+               if [ $pc4 -eq 0 ] || [ $pc4z -gt 0 ]; then
+                       echo "FAIL: dscp counters do not match, expected dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2
+                       ret=1
+                       ok=0
+               fi
+               ;;
+       "dscp_egress")
+               if [ $pc4 -eq 0 ] || [ $pc4z -gt 0 ]; then
+                       echo "FAIL: dscp counters do not match, expected dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2
+                       ret=1
+                       ok=0
+               fi
+               ;;
+       *)
+               echo "FAIL: Unknown DSCP check" 1>&2
+               ret=1
+               ok=0
+       esac
+
+       if [ $ok -eq 1 ] ;then
+               echo "PASS: $what: dscp packet counters match"
+       fi
+}
+
 check_transfer()
 {
        in=$1
@@ -286,17 +360,26 @@ test_tcp_forwarding_ip()
        ip netns exec $nsa nc -w 4 "$dstip" "$dstport" < "$nsin" > "$ns1out" &
        cpid=$!
 
-       sleep 3
+       sleep 1
 
-       if ps -p $lpid > /dev/null;then
+       prev="$(ls -l $ns1out $ns2out)"
+       sleep 1
+
+       while [[ "$prev" != "$(ls -l $ns1out $ns2out)" ]]; do
+               sleep 1;
+               prev="$(ls -l $ns1out $ns2out)"
+       done
+
+       if test -d /proc/"$lpid"/; then
                kill $lpid
        fi
 
-       if ps -p $cpid > /dev/null;then
+       if test -d /proc/"$cpid"/; then
                kill $cpid
        fi
 
-       wait
+       wait $lpid
+       wait $cpid
 
        if ! check_transfer "$nsin" "$ns2out" "ns1 -> ns2"; then
                lret=1
@@ -316,6 +399,51 @@ test_tcp_forwarding()
        return $?
 }
 
+test_tcp_forwarding_set_dscp()
+{
+       check_dscp "dscp_none"
+
+ip netns exec $nsr1 nft -f - <<EOF
+table netdev dscpmangle {
+   chain setdscp0 {
+      type filter hook ingress device "veth0" priority 0; policy accept
+       ip dscp set cs3
+  }
+}
+EOF
+if [ $? -eq 0 ]; then
+       test_tcp_forwarding_ip "$1" "$2"  10.0.2.99 12345
+       check_dscp "dscp_ingress"
+
+       ip netns exec $nsr1 nft delete table netdev dscpmangle
+else
+       echo "SKIP: Could not load netdev:ingress for veth0"
+fi
+
+ip netns exec $nsr1 nft -f - <<EOF
+table netdev dscpmangle {
+   chain setdscp0 {
+      type filter hook egress device "veth1" priority 0; policy accept
+      ip dscp set cs3
+  }
+}
+EOF
+if [ $? -eq 0 ]; then
+       test_tcp_forwarding_ip "$1" "$2"  10.0.2.99 12345
+       check_dscp "dscp_egress"
+
+       ip netns exec $nsr1 nft flush table netdev dscpmangle
+else
+       echo "SKIP: Could not load netdev:egress for veth1"
+fi
+
+       # partial.  If flowtable really works, then both dscp-is-0 and dscp-is-cs3
+       # counters should have seen packets (before and after ft offload kicks in).
+       ip netns exec $nsr1 nft -a insert rule inet filter forward ip dscp set cs3
+       test_tcp_forwarding_ip "$1" "$2"  10.0.2.99 12345
+       check_dscp "dscp_fwd"
+}
+
 test_tcp_forwarding_nat()
 {
        local lret
@@ -385,6 +513,11 @@ table ip nat {
 }
 EOF
 
+if ! test_tcp_forwarding_set_dscp $ns1 $ns2 0 ""; then
+       echo "FAIL: flow offload for ns1/ns2 with dscp update" 1>&2
+       exit 0
+fi
+
 if ! test_tcp_forwarding_nat $ns1 $ns2 0 ""; then
        echo "FAIL: flow offload for ns1/ns2 with NAT" 1>&2
        ip netns exec $nsr1 nft list ruleset
@@ -489,8 +622,8 @@ ip -net $nsr1 addr add 10.0.1.1/24 dev veth0
 ip -net $nsr1 addr add dead:1::1/64 dev veth0
 ip -net $nsr1 link set up dev veth0
 
-KEY_SHA="0x"$(ps -xaf | sha1sum | cut -d " " -f 1)
-KEY_AES="0x"$(ps -xaf | md5sum | cut -d " " -f 1)
+KEY_SHA="0x"$(ps -af | sha1sum | cut -d " " -f 1)
+KEY_AES="0x"$(ps -af | md5sum | cut -d " " -f 1)
 SPI1=$RANDOM
 SPI2=$RANDOM
 
index 75af864e07b6547ebcf43ce26a2adbc1132b1935..50aab6b57da34d0f9572f0bbc72f76f12acd6b02 100644 (file)
@@ -17,6 +17,7 @@ ENCL_CFLAGS := -Wall -Werror -static -nostdlib -nostartfiles -fPIC \
               -fno-stack-protector -mrdrnd $(INCLUDES)
 
 TEST_CUSTOM_PROGS := $(OUTPUT)/test_sgx
+TEST_FILES := $(OUTPUT)/test_encl.elf
 
 ifeq ($(CAN_BUILD_X86_64), 1)
 all: $(TEST_CUSTOM_PROGS) $(OUTPUT)/test_encl.elf
index cb5c13eee1936e16e4226d1a355fc5d249666472..479802a892d4f7aace4d72a38e8fab18e5e7dc03 100644 (file)
@@ -3962,18 +3962,19 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
        }
 
        vcpu->vcpu_idx = atomic_read(&kvm->online_vcpus);
-       r = xa_insert(&kvm->vcpu_array, vcpu->vcpu_idx, vcpu, GFP_KERNEL_ACCOUNT);
-       BUG_ON(r == -EBUSY);
+       r = xa_reserve(&kvm->vcpu_array, vcpu->vcpu_idx, GFP_KERNEL_ACCOUNT);
        if (r)
                goto unlock_vcpu_destroy;
 
        /* Now it's all set up, let userspace reach it */
        kvm_get_kvm(kvm);
        r = create_vcpu_fd(vcpu);
-       if (r < 0) {
-               xa_erase(&kvm->vcpu_array, vcpu->vcpu_idx);
-               kvm_put_kvm_no_destroy(kvm);
-               goto unlock_vcpu_destroy;
+       if (r < 0)
+               goto kvm_put_xa_release;
+
+       if (KVM_BUG_ON(!!xa_store(&kvm->vcpu_array, vcpu->vcpu_idx, vcpu, 0), kvm)) {
+               r = -EINVAL;
+               goto kvm_put_xa_release;
        }
 
        /*
@@ -3988,6 +3989,9 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
        kvm_create_vcpu_debugfs(vcpu);
        return r;
 
+kvm_put_xa_release:
+       kvm_put_kvm_no_destroy(kvm);
+       xa_release(&kvm->vcpu_array, vcpu->vcpu_idx);
 unlock_vcpu_destroy:
        mutex_unlock(&kvm->lock);
        kvm_dirty_ring_free(&vcpu->dirty_ring);
@@ -5184,7 +5188,20 @@ static void hardware_disable_all(void)
 static int hardware_enable_all(void)
 {
        atomic_t failed = ATOMIC_INIT(0);
-       int r = 0;
+       int r;
+
+       /*
+        * Do not enable hardware virtualization if the system is going down.
+        * If userspace initiated a forced reboot, e.g. reboot -f, then it's
+        * possible for an in-flight KVM_CREATE_VM to trigger hardware enabling
+        * after kvm_reboot() is called.  Note, this relies on system_state
+        * being set _before_ kvm_reboot(), which is why KVM uses a syscore ops
+        * hook instead of registering a dedicated reboot notifier (the latter
+        * runs before system_state is updated).
+        */
+       if (system_state == SYSTEM_HALT || system_state == SYSTEM_POWER_OFF ||
+           system_state == SYSTEM_RESTART)
+               return -EBUSY;
 
        /*
         * When onlining a CPU, cpu_online_mask is set before kvm_online_cpu()
@@ -5197,6 +5214,8 @@ static int hardware_enable_all(void)
        cpus_read_lock();
        mutex_lock(&kvm_lock);
 
+       r = 0;
+
        kvm_usage_count++;
        if (kvm_usage_count == 1) {
                on_each_cpu(hardware_enable_nolock, &failed, 1);
@@ -5213,26 +5232,24 @@ static int hardware_enable_all(void)
        return r;
 }
 
-static int kvm_reboot(struct notifier_block *notifier, unsigned long val,
-                     void *v)
+static void kvm_shutdown(void)
 {
        /*
-        * Some (well, at least mine) BIOSes hang on reboot if
-        * in vmx root mode.
-        *
-        * And Intel TXT required VMX off for all cpu when system shutdown.
+        * Disable hardware virtualization and set kvm_rebooting to indicate
+        * that KVM has asynchronously disabled hardware virtualization, i.e.
+        * that relevant errors and exceptions aren't entirely unexpected.
+        * Some flavors of hardware virtualization need to be disabled before
+        * transferring control to firmware (to perform shutdown/reboot), e.g.
+        * on x86, virtualization can block INIT interrupts, which are used by
+        * firmware to pull APs back under firmware control.  Note, this path
+        * is used for both shutdown and reboot scenarios, i.e. neither name is
+        * 100% comprehensive.
         */
        pr_info("kvm: exiting hardware virtualization\n");
        kvm_rebooting = true;
        on_each_cpu(hardware_disable_nolock, NULL, 1);
-       return NOTIFY_OK;
 }
 
-static struct notifier_block kvm_reboot_notifier = {
-       .notifier_call = kvm_reboot,
-       .priority = 0,
-};
-
 static int kvm_suspend(void)
 {
        /*
@@ -5263,6 +5280,7 @@ static void kvm_resume(void)
 static struct syscore_ops kvm_syscore_ops = {
        .suspend = kvm_suspend,
        .resume = kvm_resume,
+       .shutdown = kvm_shutdown,
 };
 #else /* CONFIG_KVM_GENERIC_HARDWARE_ENABLING */
 static int hardware_enable_all(void)
@@ -5967,7 +5985,6 @@ int kvm_init(unsigned vcpu_size, unsigned vcpu_align, struct module *module)
        if (r)
                return r;
 
-       register_reboot_notifier(&kvm_reboot_notifier);
        register_syscore_ops(&kvm_syscore_ops);
 #endif
 
@@ -6039,7 +6056,6 @@ err_cpu_kick_mask:
 err_vcpu_cache:
 #ifdef CONFIG_KVM_GENERIC_HARDWARE_ENABLING
        unregister_syscore_ops(&kvm_syscore_ops);
-       unregister_reboot_notifier(&kvm_reboot_notifier);
        cpuhp_remove_state_nocalls(CPUHP_AP_KVM_ONLINE);
 #endif
        return r;
@@ -6065,7 +6081,6 @@ void kvm_exit(void)
        kvm_async_pf_deinit();
 #ifdef CONFIG_KVM_GENERIC_HARDWARE_ENABLING
        unregister_syscore_ops(&kvm_syscore_ops);
-       unregister_reboot_notifier(&kvm_reboot_notifier);
        cpuhp_remove_state_nocalls(CPUHP_AP_KVM_ONLINE);
 #endif
        kvm_irqfd_exit();